20

Mam obecnie zainstalowaną aplikację z ListFragment po lewej stronie i DetailsFragment po prawej stronie (podobnie do układu na tablecie poniżej).Android Actionbar Implementacja widgetu wyszukiwania W ListFragment

layout

Na pasku akcji mam widżet wyszukiwania, które gdy wyszukiwane hasło jest przedłożony powinien aktualizować zawartość listy (w ListFragment). Podążam za przewodnikiem wyszukiwania w Androidzie (http://developer.android.com/guide/topics/search/search-dialog.html), ale mam problemy z wyszukiwaniem, aby zaktualizować listę w tej samej czynności.

Udało mi się uzyskać pewną formę implementacji działając, wywołując nową czynność, gdy wyszukiwane hasło zostało przesłane, ale to powoduje, że przycisk wstecz zachowuje się dziwnie (tzn. Naciskasz wstecz i przechodzisz do poprzedniej czynności z widżetem wyszukiwania wciąż wyświetlanie szukanego terminu).

Dodałem zamiarem linie manifest następująco

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

Czy to możliwe, aby uzyskać widżet wyszukiwania, aby zaktualizować listę bieżącej działalności?

Odpowiedz

46

Tak, w rzeczywistości jest to "normalny" przypadek użycia. Trzeba pamiętać, że fragment, który korzysta z widgetu paska działań wyszukiwania, powinien być częścią, która ogólnie rejestruje, ponieważ widget zostanie zniszczony wraz z tym fragmentem.

Oto jak prawidłowo zawiązać go:

w swojej ListFragment niech będzie wiadomo, że masz opcji pozycji menu ...

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

następnie wewnątrz tego samego ListFragment utworzyć menu opcji nadrzędnymi wywołanie zwrotne, po uzyskaniu odwołania do widgetu SearchView, zarejestruj wywołanie zwrotne 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); 
} 

utwórz swój s Szukanie przez widget albo programowo (Java) lub deklaratywne (XML) tutaj jest XML (o nazwie grid_default.xml, od góry):

<?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> 

teraz z powrotem w swoim ListFragment trzeba stworzyć queryListener zarejestrowaliśmy powyżej:

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; 
    } 
}; 

teraz wiesz, kiedy zapytanie zostanie zmienione lub przesłane, w moim przykładzie, ponawiam zapytanie w dowolnym momencie, gdy mój klucz jest mały i szybki z wynikami, może będziesz musiał to zmienić .. Zauważ, że właśnie używam widżetu, aby ustawić prywatne pole klasy wewnątrz ListFragment do bieżącego tekstu widget ch (grid_currentQuery), a potem ja po prostu wywołanie getLoaderManager().restartLoader(0, null, MyListFragment.this); gdzie w moim onCreateLoader jestem po prostu aktualizowanie rekordów użyłem tak:

@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); 
} 

i to wszystko co naprawdę trzeba zrobić, zdaję sobie sprawę, jest to rodzaj posiekane ale tak jest, ponieważ jest jeszcze więcej rzeczy, które muszą się wydarzyć, ustawienie adaptera, uruchomienie programu ładującego w pierwszej kolejności przy użyciu getLoaderManager().initLoader(0, null, this); i wszystkich pozostałych wywołań ładujących, które muszą być obsługiwane ...ale jeśli są następujące najlepsze praktyki określone przedstawionych przez android ludzi, (używając LoaderManager w twoich ListActivity s i ListFragments s powinno być dość łatwe dla Ciebie ...

Mam nadzieję, że to pomaga czuć swobodnie pytać o wyjaśnienia w komentarzach, jeśli musisz -ck

+0

Bardzo dziękuję za szczegółowe wyjaśnienie.Próbuję wdrożyć go w ciągu najbliższych kilku dni i poinformować, jeśli mam jakiekolwiek problemy. – bencallis

+0

Dzięki udało mi się go zdobyć działająca bardzo pouczająca odpowiedź Jedna rzecz, którą się zastanawiałem Domyślnie w aplikacji mam 3 zakładki, każda reprezentująca kategorię podczas wyszukiwania Chciałbym usunąć te zakładki To nie jest problem, problem, który mam, to skąd wiem kiedy użytkownik ma zakończone wyszukiwanie (cofnięte), aby ponownie dodać karty. – bencallis

+0

@bencallis najbardziej chciałbyś użyć setOnCloseListener (SearchView.OnCloseListener listener) w SearchView ... – ckozl