v7 AppCompat
サポートライブラリを実装しましたが、MenuItemCompat.getActionView
は、テストしたすべてのAndroidバージョンで常にnullを返します(4.2.2、2.3.4 ....)
SearchView
はアクションバーに表示されますが、タッチアクションに応答せず、EditText
を表示するように展開されず、単なるアイコンのようです。
@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>
最後に解決策を見つけました。
actionViewClass
の名前空間をAndroid:actionViewClass
からapp:actionViewClass
に変更しています
現在のアクティビティにAndroid.support.v7.widget.SearchView.OnQueryTextListener
インターフェイスを実装します。
SearchViewCompat.setOnQueryTextListener
の代わりに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);
}
私の場合、それはProGuardファイルでした。次の行を追加する必要があります。
-keep class Android.support.v7.widget.SearchView { *; }
私にとって、menu.xml
名前空間のインポートが正しくないためにこの問題が発生しました。
私の元の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>
xmlns:app="http://schemas.Android.com/tools"
によりMenuItemCompat.getActionView()
がnull
を返すように見えます。このインポートをxmlns:app="http://schemas.Android.com/apk/res-auto"
に変更すると、問題が修正されました。
新しい作業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>
問題は、Support V7パッケージのSearchViewを使用していることと、APIレベルが22に設定されていることだと思います。
問題を修正するために、コードを次のように変更します。
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>
同じエラーが発生しました。私のメソッドgetActionView()
は常にnullを返していました。だから、私は次のものを作りました:
<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"/>
私はいくつかの投稿で人々がapp:またはyourappを使用していることを見ましたが、私は通常Android:ActionVewClass
を使用しました。
私の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;
}
そして、onCreate
メソッドを入れることを忘れないでください:
// enabling action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
これは、FragmentActivity
およびActionBarActivity
の「拡張」アクティビティで非常にうまく機能します。
上記のMohsen Afshinの答えは私の出発点であり、セットアップで動作するようにいくつかの調整を行いました:
@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>
私は同じコードを持っていましたが、インポートAndroid.support.v7.widget.SearchView;
を使用する代わりにimport Android.widget.SearchView;
を使用していました。これにより、null
値の問題が修正されました。したがって、検索アクティビティでこのコードを変更するだけで機能し、xmlファイルのネームスペースも変更されます。
Android.widget.ImageView
を拡張したクラスを使用しようとしていたという違いがあり、非常に類似した問題がありました。
ProGuardを使用している場合、このクラスに関連するメソッドを許可するように指定する必要があります。
-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
これは、「xmlから呼び出される可能性のあるすべての必要なコンストラクターを許可し、使用するカスタムセッターも許可します(必要に応じて追加します)」
サポートライブラリv7のsearchViewを処理する方法のスニペットを次に示します。
@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;
}
また、Proguardを使用する場合は、これを構成に追加します。
-keep class Android.support.v4.app.** { *; }
-keep interface Android.support.v4.app.** { *; }
-keep class Android.support.v7.widget.SearchView { *; }
-keepattributes *Annotation*