142 votes

MenuItemCompat.getActionView renvoie toujours null

Je viens d'implémenter le v7 AppCompat mais la bibliothèque de soutien MenuItemCompat.getActionView renvoie toujours null dans toutes les versions d'Android que j'ai testées (4.2.2, 2.3.4 ....)

El SearchView est affiché dans la barre d'action, mais il ne répond pas aux actions tactiles et ne s'étend pas pour montrer son contenu. EditText et est comme une simple icône.

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

    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    if (searchView != null) {
        SearchViewCompat.setOnQueryTextListener(searchView, mOnQueryTextListener);
        searchView.setIconifiedByDefault(false);
        Log.d(TAG,"SearchView not null");
    } else
        Log.d(TAG, "SearchView is null");
    }
    return super.onCreateOptionsMenu(menu);
}

Menu.xml

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

    <item android:id="@+id/action_search"
          app:showAsAction="always|collapseActionView"
          android:icon="@drawable/abc_ic_search"
          android:title="@string/action_bar_search"
          android:actionViewClass="android.support.v7.widget.SearchView"/>

    <item android:id="@+id/action_refresh"
          android:icon="@drawable/refresh"
          android:title="@string/action_bar_refresh"
          app:showAsAction="ifRoom"/>
</menu>

296voto

Mohsen Afshin Points 3643

J'ai enfin trouvé la solution.

  1. Changement de l'espace de nom de actionViewClass de android:actionViewClass a app:actionViewClass

  2. Mise en œuvre de android.support.v7.widget.SearchView.OnQueryTextListener pour l'activité en cours.

  3. Utiliser directement setOnQueryTextListener au lieu de SearchViewCompat.setOnQueryTextListener

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.menu, menu);
    
      MenuItem searchItem = menu.findItem(R.id.action_search);
      SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
      if (searchView != null) {
         searchView.setOnQueryTextListener(this);
      }
    
      return super.onCreateOptionsMenu(menu);
    }

3 votes

Si cela a résolu votre problème, vous devriez probablement accepter votre réponse. J'aimerais également attirer l'attention de toutes les autres personnes ayant des problèmes similaires sur un autre fil de discussion traitant des mêmes questions : stackoverflow.com/q/18407171/1108032 . Si le fil de discussion actuel ne résout pas vos problèmes, envisagez d'examiner les solutions qui s'y trouvent.

4 votes

Excellente réponse ! Il pourrait être utile de préciser également que le "app" dans app:actionViewClass nécessite également une déclaration xmlns supplémentaire pour l'espace de nom "app".

3 votes

Il faut dire que android.support.v7.widget.SearchView ne doit pas être confondue avec la classe "Android.support.v4.widget.SearchViewCompat" (ce qui constitue une erreur fréquente lors de l'utilisation de la bibliothèque ActionBarCompat).

84voto

Ivan Vazhnov Points 26

Dans mon cas, c'était le fichier ProGuard. Vous devez ajouter cette ligne :

-keep class android.support.v7.widget.SearchView { *; }

2 votes

Wow, pourquoi est-ce que ça existe ? C'est la seule chose qui a fonctionné pour moi.

2 votes

+1. Plutôt évident, mais je vais quand même le mentionner - Au cas où vous avez étendu le SearchView à une autre classe, gardez le chemin vers cette classe dans proguard !

4voto

Franzé Jr. Points 91

J'ai eu la même erreur, ma méthode getActionView() retournait toujours null. J'ai donc fait les choses suivantes :

<item android:id="@+id/action_search"
      android:icon="@drawable/abc_ic_search"
      android:title="@string/search_title"
      android:showAsAction="always"
      android:actionViewClass="android.widget.SearchView"/>

J'ai vu dans certains posts que les gens utilisent app : ou yourapp, mais j'ai utilisé normalement android:ActionVewClass .

Sur mon onCreateOptionsMenu méthode :

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

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

    return true;
}

Et n'oubliez pas de mettre dans le onCreate méthode :

// enabling action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);

Cela fonctionne très bien pour mon activité "étendre" pour FragmentActivity y ActionBarActivity .

2voto

kasiahayden Points 6

La réponse de Mohsen Afshin ci-dessus a été mon point de départ et j'ai apporté quelques modifications pour qu'elle fonctionne avec ma configuration :

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    // SearchView searchView = (SearchView) MenuItemCompat
    //    .getActionView(searchItem);
    SearchView searchView = (SearchView) searchItem.getActionView();
    if (searchView != null) {
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                // do something with s, the entered string
                query = s;
                Toast.makeText(getApplicationContext(), 
                    "String entered is " + s, Toast.LENGTH_SHORT).show();
                return true;
            }
            @Override
            public boolean onQueryTextChange(String s) {
                return false;
            }
        });
    }
    return super.onCreateOptionsMenu(menu);
}

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity" >

<item android:id="@+id/action_search"
    android:orderInCategory="5"
    android:title="Search"
    android:icon="@drawable/ic_action_search"
    android:showAsAction="ifRoom|collapseActionView"
    android:actionViewClass="android.widget.SearchView" />
</menu>

0voto

android developer Points 20939

Voici un extrait de la façon de traiter le searchView de la bibliothèque de support v7 :

@Override
public void onCreateOptionsMenu(final Menu menu,final MenuInflater inflater)
  {
  menu.clear();
  getActivity().getMenuInflater().inflate(...,menu);
  _searchView=(SearchView)MenuItemCompat.getActionView(_searchMenuItem);
  _searchView.setQueryHint(...);

  if(VERSION.SDK_INT<VERSION_CODES.HONEYCOMB)
    {
    final EditText searchTextView=(EditText)searchView.findViewById(R.id.search_src_text);
    if(searchTextView!=null)
      {
      searchTextView.setScroller(new Scroller(_context));
      searchTextView.setMaxLines(1);
      searchTextView.setVerticalScrollBarEnabled(true);
      searchTextView.setMovementMethod(new ScrollingMovementMethod());
      searchTextView.setTextColor(_context.getResources().getColor(App.getResIdFromAttribute(_context,android.R.attr.textColorPrimary)));
      }
    }
  _searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener()
    {
    ...
    });
  MenuItemCompat.setActionView(_searchMenuItem,_searchView);
  MenuItemCompat.setOnActionExpandListener(_searchMenuItem,new OnActionExpandListener()
    {
    ...
    });
  super.onCreateOptionsMenu(menu,inflater);
  }

public static int getResIdFromAttribute(final Activity activity,final int attr)
  {
  if(attr==0)
    return 0;
  final TypedValue typedvalueattr=new TypedValue();
  activity.getTheme().resolveAttribute(attr,typedvalueattr,true);
  return typedvalueattr.resourceId;
  }

De même, si vous utilisez Proguard, ajoutez ceci à sa configuration :

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class android.support.v7.widget.SearchView { *; }
-keepattributes *Annotation*

0 votes

Pour celui qui a voulu formater le code, il s'agit d'un formatage très connu appelé "WhiteSmith". Changer pour un autre format ne le rend pas meilleur, car c'est une question de goût.

0 votes

@JJD Oui. Correct. Ce n'est pas aussi courant que d'autres, mais je l'utilise depuis très longtemps. Vous pouvez le définir sur Eclipse si vous le souhaitez.

0 votes

Merci de partager. Je reste avec la valeur par défaut car cela évite beaucoup de discussions non désirées avec les membres de l'équipe ou les contributeurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X