2012-12-10 4 views
5

Vor einem Monat habe ich ActionBarSherlock 4.2 in mein Projekt eingefügt. Ich habe alles zur Arbeit, außer den Suchvorschlägen für meine SearchView. Die Art, wie ich Suchvorschläge erstellt habe, war the method in the Android documentation.Unterstützt ActionBarSherlock 4.2 Suchvorschläge für ein SearchView?

Unterstützt ActionBarSherlock Suchvorschläge? Ich habe versucht, durch the issue Liste auf der Github-Seite zu graben, aber das Problem scheint geschlossen, aber ich kann nicht scheinen, die Diskussion zu folgen und zu verstehen, ob es wirklich eine Lösung ist oder nicht. Ich dachte, dass einige von Ihnen, die ActionBarSherlock verwenden, es vielleicht besser wissen.

Antwort

12

Es tut es nicht. Aber ich habe einen Weg gefunden, den ContentProvider abzufragen. Ich habe die Quelle von SuggestionsAdapter von API 17 untersucht, wo die Abfrage ausgeführt wird, und bekam eine Idee, diese Methode zu ersetzen. Außerdem habe ich festgestellt, dass der SuggestionsAdapter von ActionbarSherlock Ihre SearchableInfo nicht verwendet.

bearbeiten com.actionbarsherlock.widget.SuggestionsAdapter in Ihrem ActionBarSherlock Projekt:

Fügen Sie eine Zeile

private SearchableInfo searchable; 

in Konstruktor hinzufügen

this.searchable = mSearchable; 

ersetzen getSuggestions Methode mit dieser:

public Cursor getSuggestions(String query, int limit) { 

    if (searchable == null) { 
     return null; 
    } 

    String authority = searchable.getSuggestAuthority(); 
    if (authority == null) { 
     return null; 
    } 

    Uri.Builder uriBuilder = new Uri.Builder() 
      .scheme(ContentResolver.SCHEME_CONTENT) 
      .authority(authority) 
      .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() 
      .fragment(""); // TODO: Remove, workaround for a bug in Uri.writeToParcel() 

    // if content path provided, insert it now 
    final String contentPath = searchable.getSuggestPath(); 
    if (contentPath != null) { 
     uriBuilder.appendEncodedPath(contentPath); 
    } 

    // append standard suggestion query path 
    uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); 

    // get the query selection, may be null 
    String selection = searchable.getSuggestSelection(); 
    // inject query, either as selection args or inline 
    String[] selArgs = null; 
    if (selection != null) { // use selection if provided 
     selArgs = new String[] { query }; 
    } else {     // no selection, use REST pattern 
     uriBuilder.appendPath(query); 
    } 

    if (limit > 0) { 
     uriBuilder.appendQueryParameter("limit", String.valueOf(limit)); 
    } 

    Uri uri = uriBuilder.build(); 

    // finally, make the query 
    return mContext.getContentResolver().query(uri, null, selection, selArgs, null); 
} 

Jetzt fragt es meinen ContentProvider ab, stürzt aber mit dem Standardadapter ab und sagt, dass keine layout_height eine XML-Datei von der Support-Bibliothek lädt. Also müssen Sie benutzerdefinierte SuggestionsAdapter verwenden. Dies ist, was für mich gearbeitet:

import com.actionbarsherlock.widget.SearchView; 

import android.app.SearchManager; 
import android.app.SearchableInfo; 
import android.content.ContentResolver; 
import android.content.Context; 
import android.database.Cursor; 
import android.net.Uri; 
import android.support.v4.widget.CursorAdapter; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

public final class DrugsSearchAdapter extends CursorAdapter 
{ 
    private static final int QUERY_LIMIT = 50; 

    private LayoutInflater inflater; 
    private SearchView searchView; 
    private SearchableInfo searchable; 

    public DrugsSearchAdapter(Context context, SearchableInfo info, SearchView searchView) 
    { 
     super(context, null, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); 
     this.searchable = info; 
     this.searchView = searchView; 
     this.inflater = LayoutInflater.from(context); 
    } 

    @Override 
    public void bindView(View v, Context context, Cursor c) 
    { 
     String name = c.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1)); 
     TextView namet = (TextView) v.findViewById(R.id.list_item_drug_name); 
     namet.setText(name); 

     String man = c.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2)); 
     TextView manuf = (TextView) v.findViewById(R.id.list_item_drug_manufacturer); 
     manuf.setText(man); 
    } 

    @Override 
    public View newView(Context arg0, Cursor arg1, ViewGroup arg2) 
    { 
     return this.inflater.inflate(R.layout.list_item_drug_search, null); 
    } 

    /** 
    * Use the search suggestions provider to obtain a live cursor. This will be called 
    * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions). 
    * The results will be processed in the UI thread and changeCursor() will be called. 
    */ 
    @Override 
    public Cursor runQueryOnBackgroundThread(CharSequence constraint) { 
     String query = (constraint == null) ? "" : constraint.toString(); 
     /** 
     * for in app search we show the progress spinner until the cursor is returned with 
     * the results. 
     */ 
     Cursor cursor = null; 
     if (searchView.getVisibility() != View.VISIBLE 
       || searchView.getWindowVisibility() != View.VISIBLE) { 
      return null; 
     } 
     try { 
      cursor = getSuggestions(searchable, query, QUERY_LIMIT); 
      // trigger fill window so the spinner stays up until the results are copied over and 
      // closer to being ready 
      if (cursor != null) { 
       cursor.getCount(); 
       return cursor; 
      } 
     } catch (RuntimeException e) { 
     } 
     // If cursor is null or an exception was thrown, stop the spinner and return null. 
     // changeCursor doesn't get called if cursor is null 
     return null; 
    } 

    public Cursor getSuggestions(SearchableInfo searchable, String query, int limit) { 

     if (searchable == null) { 
      return null; 
     } 

     String authority = searchable.getSuggestAuthority(); 
     if (authority == null) { 
      return null; 
     } 

     Uri.Builder uriBuilder = new Uri.Builder() 
       .scheme(ContentResolver.SCHEME_CONTENT) 
       .authority(authority) 
       .query("") 
       .fragment(""); 

     // if content path provided, insert it now 
     final String contentPath = searchable.getSuggestPath(); 
     if (contentPath != null) { 
      uriBuilder.appendEncodedPath(contentPath); 
     } 

     // append standard suggestion query path 
     uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); 

     // get the query selection, may be null 
     String selection = searchable.getSuggestSelection(); 
     // inject query, either as selection args or inline 
     String[] selArgs = null; 
     if (selection != null) { // use selection if provided 
      selArgs = new String[] { query }; 
     } else {     // no selection, use REST pattern 
      uriBuilder.appendPath(query); 
     } 

     if (limit > 0) { 
      uriBuilder.appendQueryParameter("limit", String.valueOf(limit)); 
     } 

     Uri uri = uriBuilder.build(); 

     // finally, make the query 
     return mContext.getContentResolver().query(uri, null, selection, selArgs, null); 
    } 

} 

Und setzen Sie diesen Adapter in Suche

searchView.setSuggestionsAdapter(new DrugsSearchAdapter(this, searchManager.getSearchableInfo(getComponentName()), searchView)); 
+0

Vielen Dank, dass Sie sich die Zeit genommen haben, diese großartige Antwort zu schreiben :) –

2

Ich bin derjenige, der the github issue für diese geöffnet. Es arbeitet am Dev-Zweig. Die aktuelle Version (4.2) hat den Fix nicht. Es wurde komplett von diesem commit behoben, aber ich würde vorschlagen, nur den Dev-Zweig zu überprüfen und es zu versuchen.

+0

da der Dev-Zweig zur Zeit in Master integriert ist und davor das Fix-Commit ist Master, auch und mit Master sollte funktionieren. –

0

Ich weiß nicht, ob ich hier falsch liege oder ich etwas versehentlich geändert habe, aber die obige Antwort funktioniert nicht und der ActionBarSherlock SuggestionsAdapter funktioniert nicht. Alles, was ich bekomme, sind Nullzeiger in runQueryOnBackgroundThread. Es geht auch nie in bindView etc., aber es gelingt, Suggestionsergebnisse anzuzeigen. Ich denke, android.app.SearchManager ist ABS mit getSuggestions(), aber ich bin mir nicht sicher. Ich probiere immer noch Dinge aus ...