web-dev-qa-db-ja.com

MenuItemCompat.getActionViewは常にnullを返します

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>
141
Mohsen Afshin

最後に解決策を見つけました。

  1. actionViewClassの名前空間をAndroid:actionViewClassからapp:actionViewClassに変更しています

  2. 現在のアクティビティにAndroid.support.v7.widget.SearchView.OnQueryTextListenerインターフェイスを実装します。

  3. 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);
    }
    
296
Mohsen Afshin

私の場合、それはProGuardファイルでした。次の行を追加する必要があります。

-keep class Android.support.v7.widget.SearchView { *; }
85
Ivan Vazhnov

私にとって、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>
42
Sean Barbeau

問題は、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> 
5

同じエラーが発生しました。私のメソッド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の「拡張」アクティビティで非常にうまく機能します。

4
Franzé Jr.

上記の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>
2
kasiahayden

私は同じコードを持っていましたが、インポートAndroid.support.v7.widget.SearchView;を使用する代わりにimport Android.widget.SearchView;を使用していました。これにより、null値の問題が修正されました。したがって、検索アクティビティでこのコードを変更するだけで機能し、xmlファイルのネームスペースも変更されます。

1
marcelocolombo

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から呼び出される可能性のあるすべての必要なコンストラクターを許可し、使用するカスタムセッターも許可します(必要に応じて追加します)」

0
ElliotM

サポートライブラリ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*
0