Je viens de mettre en œuvre le v7 AppCompat
bibliothèque de support mais le MenuItemCompat.getActionView
retourne toujours null dans chaque Android que j'ai testée (4.2.2, 2.3.4 ....)
Le SearchView
est affiché dans la barre d’action, mais il ne répond pas aux actions tactiles et ne se développe pas pour afficher son EditText
et se présente 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>
Finalement j'ai trouvé la solution.
Changer l’espace de noms de actionViewClass
de Android:actionViewClass
à app:actionViewClass
Implémentation Android.support.v7.widget.SearchView.OnQueryTextListener
interface pour l'activité en cours.
Utilisez 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);
}
Dans mon cas, c'était un fichier ProGuard. Vous devez ajouter cette ligne:
-keep class Android.support.v7.widget.SearchView { *; }
Pour moi, une importation d'espace de nom menu.xml
Incorrecte a été à l'origine de ce problème.
Mon original menu.xml
:
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/tools">
<item Android:id="@+id/action_search"
Android:title="@string/map_option_search"
Android:icon="@drawable/ic_action_search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="Android.support.v7.widget.SearchView"/>
</menu>
Il semble que le xmlns:app="http://schemas.Android.com/tools"
Ait amené MenuItemCompat.getActionView()
à renvoyer null
. Changer cette importation en xmlns:app="http://schemas.Android.com/apk/res-auto"
A résolu le problème.
Nouveau travail menu.xml
:
<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"
Android:title="@string/map_option_search"
Android:icon="@drawable/ic_action_search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="Android.support.v7.widget.SearchView"/>
</menu>
Je pense que le problème est que vous utilisez SearchView à partir du package Support V7 et peut-être que votre niveau d'API est défini sur ..... 22 ??.
Changer votre code à la suivante pour résoudre le problème:
menu.xml
<?xml version="1.0" encoding="UTF-8" ?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<item
Android:id="@+id/action_search"
Android:icon="@drawable/actionbar_button_search"
Android:title="Search"
Android:showAsAction="always"
Android:actionViewClass="Android.widget.SearchView" />
</menu>
J'étais avec la même erreur, ma méthode getActionView()
retournait toujours null. Donc, j'ai 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 messages que les gens utilisent app: ou yourapp, mais j'ai utilisé normalement Android:ActionVewClass
.
Sur ma méthode onCreateOptionsMenu
:
@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 la méthode onCreate
:
// 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é "extension" pour FragmentActivity
et ActionBarActivity
.
La réponse de Mohsen Afshin ci-dessus était mon point de départ et j'ai fait quelques ajustements pour le faire fonctionner 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>
J'ai eu le même code, mais au lieu d'utiliser l'importation Android.support.v7.widget.SearchView;
J'utilisais import Android.widget.SearchView;
. Cela a résolu mon problème avec la valeur null
. Il suffit donc de modifier ce code dans votre activité de recherche et cela fonctionnera, ainsi que de modifier l’espace de noms au format XML.
J'ai eu un problème très similaire avec la différence que je tentais d'utiliser une classe qui a étendu Android.widget.ImageView
Si vous utilisez ProGuard, vous devez spécifier d'autoriser les méthodes impliquées dans cette classe.
-keep public class * extends Android.widget.ImageView{
public <init>(Android.content.Context);
public <init>(Android.content.Context, Android.util.AttributeSet);
public <init>(Android.content.Context, Android.util.AttributeSet, int);
public void set*(...);
}
http://proguard.sourceforge.net/manual/examples.html
Cela dit, "Autoriser tous les constructeurs nécessaires pouvant être appelés à partir du xml et autoriser tous les configurateurs personnalisés utilisés (ajouter davantage si nécessaire)"
Voici un extrait de la procédure à suivre pour gérer searchView à partir 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 plus, 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*