2012-12-10 2 views
5

Il y a un mois, j'ai lancé ActionBarSherlock 4.2 dans mon projet. J'ai tout eu au travail, sauf les suggestions de recherche pour mon SearchView. La façon dont je créais les suggestions de recherche utilisait the method in the Android documentation.ActionBarSherlock 4.2 prend-il en charge les suggestions de recherche pour un SearchView?

ActionBarSherlock prend-il en charge les suggestions de recherche? J'ai essayé de creuser la liste the issue sur la page Github mais le problème semble fermé mais je n'arrive pas à suivre la discussion et à comprendre si c'est vraiment résolu ou non. Je pensais que certains d'entre vous qui utilisiez ActionBarSherlock pourraient mieux savoir.

Répondre

12

Ce n'est pas le cas. Mais j'ai trouvé un moyen de le faire interroger votre ContentProvider. J'ai regardé dans la source de SuggestionsAdapter de l'API 17 où la requête s'exécute et a eu une idée de remplacer cette méthode. J'ai également trouvé que SuggestionsAdapter d'ActionbarSherlock n'utilise pas votre SearchableInfo.

Modifier com.actionbarsherlock.widget.SuggestionsAdapter dans votre projet ActionBarSherlock:

Ajouter une ligne

private SearchableInfo searchable; 

dans le constructeur, ajoutez

this.searchable = mSearchable; 

Remplacer méthode getSuggestions avec celui-ci:

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

Maintenant, il interroge mon ContentProvider, mais se bloque avec l'adaptateur par défaut en disant que layout_height ne charge pas certains fichiers xml de la bibliothèque de support. Vous devez donc utiliser SuggestionsAdapter personnalisé. C'est ce qui a fonctionné pour moi:

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

} 

Et mis cet adaptateur dans SearchView

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

Un grand merci d'avoir pris le temps d'écrire cette bonne réponse :) –

2

Je suis celui qui a ouvert the github issue pour cela. Il travaille sur la branche dev. La version actuelle (4.2) n'a pas le correctif. Il a été complètement corrigé par ce commit, mais je suggérerais de vérifier la branche dev et de l'essayer.

+0

comme la dev-branche semble actuellement être fusionnée en master et en avance, le fix-commit est en maître, aussi et en utilisant le maître devrait fonctionner. –

0

Je ne sais pas si je me trompe ici ou j'ai changé quelque chose sur accident, mais la réponse ci-dessus ne fonctionne pas et le SuggestionsAdapter ActionBarSherlock ne fonctionne pas. Tout ce que je reçois sont des pointeurs NULL dans runQueryOnBackgroundThread. Il ne va jamais non plus dans bindView etc., mais il parvient à afficher les résultats de la suggestion. Je pense que android.app.SearchManager est en quelque sorte en train de surcharger ABS avec getSuggestions() mais je ne suis pas sûr. Je suis encore en train d'essayer les choses ...

Questions connexes