MenuItemCompat.getActionView始终返回null


142

我刚刚实现了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>

Answers:


296

终于我找到了解决方案。

  1. 将名称空间actionViewClass从更改android:actionViewClassapp: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
如果这解决了您的问题,您可能应该接受您的回答。我还想指出所有其他有类似问题的人,一个讨论类似问题的线程:stackoverflow.com/q/18407171/1108032。如果当前线程不能解决您的问题,请考虑研究那里的解决方案。
鲍里斯·斯特兰杰夫

4
好答案!也许还需要澄清一下,app:actionViewClass中的“ app”还需要为“ app”命名空间附加一个xmlns声明。
jklp

3
需要说的是,android.support.v7.widget.SearchView该类不应与“ android.support.v4.widget.SearchViewCompat”类混淆(使用ActionBarCompat库时这是常见错误)
Alex Semeniuk 2013年

1
@jklp我尝试添加xmlns声明<menu xmlns:app="http://schemas.android.com/apk/res/android" >但出现错误Attribute is missing the Android namespace prefix。您知道了,如何解决?
anticafe 2014年

5
还要注意,android:showAsAction也需要更改为app:showAsAction。还要确保活动的主题(不仅仅是应用程序)正在引用appcompat主题。最后一件事,应用程序声明为“ schemas.android.com/apk/res-auto
Kalel Wade 2014年

85

就我而言,它是ProGuard文件。您需要添加以下行:

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

2
哇,这是为什么呢?这是唯一对我有用的东西。
克劳德,2015年

2
+1。很明显,但是我仍然要提到-如果您将SearchView扩展到另一个类,请在proguard中保留该类的路径!
user2520215 '16

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
您能否解释一下您提供的代码示例解决了该问题的原因?(我想是的。)
Edgar 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

莫森·阿夫申(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>

1

我有相同的代码,但是android.support.v7.widget.SearchView;我没有使用import import android.widget.SearchView;。这解决了我的null价值问题。因此,只需在您的搜索活动中更改此代码,它就可以工作,并且还可以更改xml文件中的名称空间。


这是我们的问题,我们在Activity中混用了android.widget.SearchView,但在menu_main.xml文件中部分使用了v7。只要确保.xml文件也使用了app:actionViewClass =“ android.support.v7.widget.SearchView”。
gmcc051

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
他为什么要这样做?请详细解释您的答案。
罗宾·埃勒克曼

当我扩展ActionBarActivity时,它总是返回null。但我仅扩展活动,它可以正常工作
Hieu

使用ActionBarActivity时需要使用自己的名称空间,因为它是支持库的一部分。由于您在xml中使用android:showAsAction,因此它可以与Activity(不是来自支持库)一起使用,也不能与ActionBarActivity一起使用
Dennis K,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.