Реализация виджета поиска в панели действий Android в ListFragment - PullRequest
20 голосов
/ 04 марта 2012

В настоящее время мое приложение настроено с ListFragment слева и DetailsFragment справа (аналогично расположению на планшете ниже).

layout

На панели действий у меня есть виджет поиска, который при отправке поискового запроса должен обновлять содержимое списка (в ListFragment).Я следовал руководству по поиску на устройстве Android (http://developer.android.com/guide/topics/search/search-dialog.html), но у меня возникают проблемы с поиском, чтобы обновить список в том же упражнении.

Мне удалось заставить работать некоторую форму реализациивызывая новое действие при отправке поискового запроса, но это заставляет кнопку «Назад» вести себя странно (т. е. вы нажимаете назад и переходите к предыдущему действию с виджетом поиска, по-прежнему отображающим поисковый термин).

У меня естьдобавили строки намерений в манифест следующим образом

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

Можно ли получить поисковый виджет для обновления списка текущей активности?

1 Ответ

46 голосов
/ 05 марта 2012

Да, на самом деле, это «нормальный» вариант использования. Следует помнить, что фрагмент, который использует виджет панели действий поиска, должен быть частью, которая регистрирует его в целом, поскольку виджет будет уничтожен вместе с этим фрагментом.

Вот как правильно связать это:

в вашем ListFragment пусть будет известно, что у вас есть пункты меню параметров ...

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    ..
    setHasOptionsMenu(true);
    ..
}

затем внутри того же ListFragment создайте меню параметров, переопределив обратный вызов, как только у вас появится ссылка на виджет SearchView, зарегистрируйте обратный вызов QueryTextListener:

@Override 
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.grid_default, menu); 
    SearchView searchView = (SearchView)menu.findItem(R.id.grid_default_search).getActionView();
    searchView.setOnQueryTextListener(queryListener);
}

Создайте свой виджет поиска с помощью программного (Java) или декларативного (XML) формата XML (с именем grid_default.xml, сверху):

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item     
        android:id="@+id/grid_default_search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="search"
        android:showAsAction="always"
        android:actionViewClass="android.widget.SearchView" 
    />

    <!-- other items or whatever  -->

</menu>

теперь вернемся к вашему ListFragment, вам нужно создать queryListener, который мы зарегистрировали выше:

private String grid_currentQuery = null; // holds the current query...

final private OnQueryTextListener queryListener = new OnQueryTextListener() {       

    @Override
    public boolean onQueryTextChange(String newText) {
        if (TextUtils.isEmpty(newText)) {
            getActivity().getActionBar().setSubtitle("List");               
            grid_currentQuery = null;
        } else {
            getActivity().getActionBar().setSubtitle("List - Searching for: " + newText);
            grid_currentQuery = newText;

        }   
        getLoaderManager().restartLoader(0, null, MyListFragment.this); 
        return false;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {            
        Toast.makeText(getActivity(), "Searching for: " + query + "...", Toast.LENGTH_SHORT).show();
        return false;
    }
};

теперь вы знаете, когда запрос изменяется или отправляется, в моем примере я повторяю запрос каждый раз, когда нажимается клавиша, потому что моя база данных была маленькой и быстрой с результатами, вам может потребоваться изменить это .. но вы заметите, как я просто использую виджет, чтобы установить поле частного класса внутри ListFragment для текущего текста виджета поиска (grid_currentQuery), а затем я просто звоню getLoaderManager().restartLoader(0, null, MyListFragment.this);, где внутри моего onCreateLoader я просто обновляю запрос, который я использовал так:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bargs) {

    String sort = "SortColumn ASC";
    String[] grid_columns = new String[] { "ColumnA", "ColumnB", "Etc..." };
    String grid_whereClause = "ColumnToSearchBy LIKE ?"

    if (!TextUtils.isEmpty(grid_currentQuery)) {            
        return new CursorLoader(getActivity(), DataProvider.CONTENT_URI, grid_columns, grid_whereClause, new String[] { grid_currentQuery + "%" }, sort);
    }       

    return new CursorLoader(getActivity(), DataProvider.CONTENT_URI, grid_columns, null, null, sort);
}

и это все, что вам действительно нужно сделать, я понимаю, что это как-то порезано, но это так, потому что есть еще что-то, что должно произойти, настройка адаптера, запуск загрузчика в первую очередь с использованием getLoaderManager().initLoader(0, null, this); и все остальные обратные вызовы загрузчика, которые должны быть обработаны ... но если вы следуете передовым методам, предложенным пользователями android, (используя LoaderManager s в ваших ListActivity s и ListFragments s, это должно быть довольно легко для вас ...

Надеюсь, это поможет вам задать вопрос в комментариях, если вам нужно -ck

...