Започнете нова дейност от SearchView

Имам 2 дейности: първата има лента за действие с изглед за търсене, втората трябва да показва резултатите от заявката за търсене.

androidmanifest:

    <activity
        android:name=".SearchActivity"

        ...
        android:launchMode="singleTop">           

        <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchable" />
        ...

    </activity>

   <activity
        android:name=".ResultsActivity"
        ...

         <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>

    </activity>

searchable.xml

<searchable
xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/enter_a_word" />

SearchActivity

....
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_noun_list, menu);

    // Associate searchable configuration with the SearchView
    SearchManager searchManager =  (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView =  (SearchView) menu.findItem(R.id.search).getActionView();
    searchView.setSearchableInfo( searchManager.getSearchableInfo(getComponentName()));

    return true;
}
....

РезултатиДейност:

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);

    }
...
}

проблемът е, че след въвеждане на заявка в searchview нищо не се случва. Няма грешки, нищо. Как мога да отворя дейността с резултати, след като заявката е въведена в дейността за търсене?


person Maarten    schedule 09.04.2015    source източник
comment
Така че предполагам, че имате данни за търсене, нали? Внедрявате ли и някакви интерфейси във вашата дейност?   -  person Eenvincible    schedule 09.04.2015


Отговори (3)


Този отговор е малко закъснял, но смятам, че ще бъде полезен за бъдещите зрители. Дилемата изглежда идва от неяснотата на урока за Android SearchView. Сценарият, който cover предполага, че ще показвате резултатите в същата дейност, в която се намира SearchView. В такъв сценарий маркерът за активност във файла AndroidManifest.xml ще изглежда по следния начин:

<activity
    android:name=".MainActivity"
    android:label="@string/main_activity_label"
    android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.SEARCH"/>
        </intent-filter>
        <meta-data android:name="android.app.searchable"
            android:resource="@xml/searchable" />
</activity>

След това, за да обработите резултатите в същата дейност, трябва да замените метода onNewIntent:

@Override
public void onNewIntent(Intent intent){
    setIntent(intent);
    if(Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        //now you can display the results
    }  
}

Въпреки това, в ситуация, в която искаме да покажем резултатите в друга дейност, трябва да поставим филтъра за намерения и мета таг в дейността с резултати и да въведем нов мета таг за дейността SearchView. И така, нашите дейности ще изглеждат нещо подобно във файла AndroidManifest.xml:

<activity
        android:name=".MainActivity"
        android:label="@string/main_activity_label"
        android:launchMode="singleTop">
        <!-- meta tag points to the activity which displays the results -->
        <meta-data
            android:name="android.app.default_searchable"
            android:value=".SearchResultsActivity" />
</activity>
<activity
        android:name=".SearchResultsActivity"
        android:label="@string/results_activity_label"
        android:parentActivityName="com.example.MainActivity">
        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.MainActivity" />
        <!-- meta tag and intent filter go into results activity -->
        <meta-data android:name="android.app.searchable"
            android:resource="@xml/searchable" />
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
</activity>

След това в метода onCreateOptionsMenu на нашата MainActivity активирайте SearchView (предполага се, че добавяте SearchView към ActionBar). Вместо да използваме getComponentName() в извикването на метода getSearchableInfo() на SearchManager, ние създаваме нов обект ComponentName, използвайки контекста на MainActivity и класа SearchResultsActivity:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_home, menu);
    SearchView search = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search);
    // Associate searchable configuration with the SearchView
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    search.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(this, SearchResultsActivity.class)));
    search.setQueryHint(getResources().getString(R.string.search_hint));
    return true;
}

И накрая, в нашия клас SearchResultsActivity, в метода onCreate, можем да обработваме резултатите от търсенето:

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        //use the query to search your data somehow
    }
}

Не забравяйте да създадете файла с ресурси searchable.xml и да добавите SearchView към вашето оформление.

searchable.xml (res/xml/searchable.xml; създайте xml папка под res, ако е необходимо):

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="@string/search_hint"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"/>

Оформление (пример за добавяне на SearchView към ActionBar като елемент от менюто):

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.MainActivity">
    <group android:checkableBehavior="single">
        <item android:id="@+id/action_search" android:title="Search"
            android:orderInCategory="1" app:showAsAction="collapseActionView|ifRoom"
            app:actionViewClass="android.support.v7.widget.SearchView"/>
    </group>
</menu>

Ресурси:

person chRyNaN    schedule 19.08.2015
comment
Отлична демонстрация - person Raju; 16.09.2016
comment
Проследих всяка стъпка, но резултатът от търсенето все още отива към текущата дейност, SearchResultsActivity onCreate() не се извиква, някой има същия проблем? - person Weidian Huang; 04.11.2018
comment
Открих проблема си, защото също така слушам onQueryTextSubmit() дори при текущата активност и той връща true, резултатът няма да бъде изпратен на SearchResultsActivity. Единственото нещо, което трябва да променя, е просто да върна false за onQueryTextSubmit(). - person Weidian Huang; 04.11.2018
comment
Много добро обяснение. Благодаря ти. Наистина е полезно за мен :) - person Pooja; 09.10.2019
comment
защо се нуждаем от ново име на компонент? - person Michele Dorigatti; 13.08.2020

Без да виждам кода на вашата дейност, бих ви предложил да опитате този подход - също така ако приемем, че имате всички файлове, създадени, както е посочено по-горе;

Във вашата дейност с резултати,

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.core_actions, menu);

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

    searchView.setIconifiedByDefault(false);
    searchView.setQueryHint(getString(R.string.search_hint));

    searchView.setOnQueryTextListener(this);

    return true;
}

Не забравяйте, че това е дейността, която съдържа вашите данни, които искате да направите достъпни за търсене:

Трябва да внедрите интерфейса SearchView.OnQueryTextListener в същата дейност:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_search:
            ProductsResulstActivity.this.finish();

            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

@Override
public boolean onQueryTextChange(String newText) {

    productFilterAdapter.getFilter().filter(newText);

    if (TextUtils.isEmpty(newText)) {
         listView.clearTextFilter();
     }
    else {
       listView.setFilterText(newText);
    }

    return true;
}

productFilterAdapter е адаптерът, който трябва да създадете предварително.

Той трябва да реализира филтрируем интерфейс. Надявам се това да помогне.

Ако имате нужда от допълнителна помощ, моля, уведомете ме. Късмет

person Eenvincible    schedule 09.04.2015

Разбрах проблема, аз също се сблъсках със същия, това се случва, защото предавате текущото име на компонент, като предавате

getComponentName()

Това ще бъде инициализирано от името на текущата дейност, така че трябва да го инициализирате с името на дейността, което може да се търси, в дадения по-долу формат и да предадете същия екземпляр на компонента, който стартира новата дейност.

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    search.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(this, SearchResultsActivity.class)));
    search.setQueryHint(getResources().getString(R.string.search_hint));

Надявам се, че съм отговорил на въпроса!

person Vivek Kumar Samele    schedule 10.07.2018