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


142

私はv7 AppCompatサポートライブラリを実装したばかりですが、MenuItemCompat.getActionViewテストしたすべてのAndroidバージョン(4.2.2、2.3.4 ...)では常にnullを返します。

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>

回答:


296

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

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

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

  3. setOnQueryTextListener代わりに直接使用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
これで問題が解決した場合は、おそらく回答を受け入れる必要があります。また、同様の問題を抱えている他のすべての人に、同様の問題を論じているもう1つのスレッド(stackoverflow.com/q/18407171/1108032)を紹介したいと思います。現在のスレッドで問題が解決しない場合は、そこで解決策を検討することを検討してください。
Boris Strandjev 2013

4
正解です。app:actionViewClassの "app"にも "app"名前空間の追加のxmlns宣言が必要であることを明確にすることも支払うかもしれません。
jklp 2013年

3
それ言う必要があるandroid.support.v7.widget.SearchViewクラスが(ActionBarCompatライブラリを使用する際によくある間違いとして知られている)「android.support.v4.widget.SearchViewCompat」クラスと混同してはならない
アレックスSemeniuk

1
@jklp xmlns宣言を追加しようとすると<menu xmlns:app="http://schemas.android.com/apk/res/android" >エラーが発生しますAttribute is missing the Android namespace prefix。あなたはそれを手に入れましたか、そしてどのようにそれを修正しますか?
アンチカフェ2014

5
また、android:showAsActionもapp:showAsActionに変更する必要があることに注意してください。また、アクティビティのテーマ(アプリケーションだけでなく)がappcompatテーマを参照していることも確認してください。最後には、アプリのdeclartion「ですschemas.android.com/apk/res-auto
Kalelウェイド

85

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

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

2
わあ、これはなぜですか。これは私のために働いた唯一のものでした。
Claud

2
+1。かなり自明ですが、ここでも触れます-SearchViewを別のクラスに拡張した場合は、そのクラスへのパスを守ってください!
user2520215

42

私にとって、不正な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>

5

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

1
あなたが提供したコードサンプルが問題を解決する理由を説明できますか?(そうだと思います。)
エドガーN

4

同じエラーが発生しました。私のメソッド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


2

上記のモーセンアフシンの答えは私の出発点であり、私はそれを私のセットアップで動作させるためにいくつかの微調整を行いました:

@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>

1

同じコードがありましたが、インポートandroid.support.v7.widget.SearchView;を使用する代わりにを使用していましたimport android.widget.SearchView;。これでnull値の問題が解決しました。したがって、検索アクティビティでこのコードを変更するだけで機能し、xmlファイルの名前空間も変更されます。


これは私たちの問題でした。アクティビティにandroid.widget.SearchViewが混在していますが、menu_main.xmlファイルでv7の一部が使用されていました。.xmlファイルでもapp:actionViewClass = "android.support.v7.widget.SearchView"も使用していることを確認してください。
gmcc051 2017年

0

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

コードをフォーマットしたい人にとって、これは「WhiteSmith」と呼ばれる非常によく知られているフォーマットです。これは好みの問題であるため、別の形式に変更しても、改善されるわけではありません。
Android開発者

@JJDはい。正しい。他の人ほど一般的ではありませんが、私は非常に長い間使用してきました。必要に応じて、Eclipseで設定できます。
Android開発者

共有いただきありがとうございます。チームメンバーまたは貢献者との多くの不要な議論を回避するため、私はデフォルトのままにします。
JJD 2014年

@JJDそれも本当です。オフィスでは、デフォルトのスタイルとは少し異なるスタイルで作業しています。とにかく、優れた開発者はすべての一般的な書式設定スタイルを処理できる必要があります。「目が痛い」場合は、いつでもコードをコピーして、さまざまな書式設定ツール(オンラインまたはIDE)で書式設定できます。
Android開発者

0

拡張されたクラスを使用しようとしていたという違いで非常に類似した問題がありました 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

私はこれを手動でJavaコードに設定して行いました:

<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/user_info"
        android:title="@string/user_name_title"
        app:actionLayout="@layout/menu_item_username"
        android:showAsAction="always" />
</menu>

レイアウトファイル:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/usr_name_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:contentDescription="@string/user_info_image_des"
        android:padding="5dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:text="@string/user_name_title"
        android:textStyle="bold"
        android:visibility="visible" />
</LinearLayout>

次にJavaコードで:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.connect_menu, menu);
        // show user name on the top of menu
        Log.e("menu", "Size: " + menu.size());
        MenuItem item = menu.getItem(0);
        item.setActionView(R.layout.menu_item_username);
        View v = item.getActionView();
        if (null == v) {
            Log.e("NULL POINTER EX", "NULL MENU VIEW");
        } else {
            TextView usrNameTitle = v.findViewById(R.id.usr_name_title);
            if (null != usrName && usrName.length() > 0) {
                usrNameTitle.setText(usrName);
            }
        }
        return true;
    }

ここに画像の説明を入力してください


-1

コードの削除:パブリッククラスDemoActivityはActionBarActivityを拡張します

置換:パブリッククラスDemoActivityがActivityを拡張する


2
なぜ彼はそうしなければならないのですか?あなたの答えをもう少し詳しく説明してください。
Robin Ellerkmann、2015年

ActionBarActivityを拡張すると、常にnullが返されます。しかし、私はアクティビティのみを拡張し、それは正常に動作します
Hieu

ActionBarActivityはサポートライブラリの一部なので、独自の名前空間を使用する必要があります。あなたはxmlでandroid:showAsActionを使用しているため、アクティビティ(サポートライブラリからのものではありません)で動作し、ActionBarActivityでは動作しません
Dennis K
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.