在Fragment中添加SearchView

23

尝试在操作栏中包含一个搜索视图。为此,我已经完成了以下步骤:

在菜单文件夹中创建了名为MenuSearch.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:actionViewClass="Android.Support.V7.Widget.SearchView"
    android:icon="@android:drawable/ic_menu_search"
    android:showAsAction="always"
    android:title="Search"/>

</menu>

在片段中包含了OnCreateOptionsMenu方法:

public override void OnCreateOptionsMenu(IMenu menu, MenuInflater inflater)
    {
        inflater.Inflate(Resource.Menu.MenuSearch, menu);
        base.OnCreateOptionsMenu(menu, inflater);
        var searchManager = (SearchManager) this.Activity.GetSystemService(Context.SearchService);
        searchView = (SearchView) (menu.FindItem(Resource.Id.action_search).ActionView);
        searchView.SetSearchableInfo(searchManager.GetSearchableInfo(Activity.ComponentName));

    }

我在片段的onCreate中设置了HasOptionsMenu = true;

使用上述代码,我在searchView.SetSearchableInfo...这一行中得到了一个空指针异常。虽然所有东西似乎都正确并且位置正确,但我不确定为什么会出现这种情况。

根据解决类似问题的一些建议,我还尝试了下面的搜索视图选项。

        var item = menu.FindItem (Resource.Id.action_search);
        var searchItem = MenuItemCompat.GetActionView(item);
        searchView = searchItem.JavaCast<Android.Support.V7.Widget.SearchView>();
        searchView.SetSearchableInfo(searchManager.GetSearchableInfo(Activity.ComponentName));

但是,我再次得到了null的searchView。

现在我已经尝试了可能的选项,对于为什么搜索视图变为null,我感到茫然无措。

非常感谢任何帮助。

7个回答

40

将您的MenuSearch.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"
            android:title="@string/app_name"
            android:icon="@drawable/ic_action_search"
            app:showAsAction="collapseActionView|ifRoom"
             />
    </menu>

在你的代码片段中,添加 searchView.setOnQueryTextListener

    @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            super.onCreateOptionsMenu(menu, inflater);
            menu.clear();
            inflater.inflate(R.menu.search_option_menu, menu);
            MenuItem item = menu.findItem(R.id.action_search);
            SearchView searchView = new SearchView(((MainActivity) mContext).getSupportActionBar().getThemedContext());
           // MenuItemCompat.setShowAsAction(item, //MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | //MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
           //  MenuItemCompat.setActionView(item, searchView);
           // These lines are deprecated in API 26 use instead
 item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM);
        item.setActionView(searchView);
            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    return false;
                }
                @Override
                public boolean onQueryTextChange(String newText) {
                    return false;
                }
            });
            searchView.setOnClickListener(new View.OnClickListener() {
                                              @Override
                                              public void onClick(View v) {

                                              }
                                          }
            );
        }

1
在以下代码中出现了 nullPointerException: SearchView searchView = new SearchView(((MainActivity) mContext).getSupportActionBar().getThemedContext()); - Dinesh
你的应用程序样式可能不支持操作栏。请检查一下你的样式是否支持它。 - Tiago Dávila
1
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItemCompat.setActionView(item, searchView); 这两行代码已经过时,请更新答案...... - Gowthaman M
问题已解决。谢谢。 - Pooja

10

回答已更新至2018年。如果您使用的是Java,请忽略Kotlin。

您的xml菜单资源(例如search_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"
        android:title="@string/app_name"
        android:icon="@drawable/ic_search"
        app:showAsAction="collapseActionView|ifRoom"
        />
</menu>

构建代码:

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater?) {
    super.onCreateOptionsMenu(menu, inflater)
    menu.clear()
    inflater?.inflate(R.menu.search_menu, menu)
    val searchView = SearchView((context as MainActivity).supportActionBar?.themedContext ?: context)
    menu.findItem(R.id.action_search).apply {
        setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW or MenuItem.SHOW_AS_ACTION_IF_ROOM)
        actionView = searchView
    }

    searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
        override fun onQueryTextSubmit(query: String): Boolean {
            return false
        }

        override fun onQueryTextChange(newText: String): Boolean {
            return false
        }
    })
    searchView.setOnClickListener {view ->  }
}

你可能还需要在onCreate()中加入这行代码(对我的Fragment有效),以便让所有内容都显示出来:

setHasOptionsMenu(true)

3

针对2018年底及api版本>= 26兼容性(弃用警告)和格式正确的答案:

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"
        android:title="Search_change_me_with_proper_id"
        android:icon="@drawable/ic_action_search"
        app:showAsAction="collapseActionView|ifRoom"/>
</menu>

ActivityFragment中的Java代码:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    setHasOptionsMenu(true); // Add this!
    return inflater.inflate(R.layout.fragment_add_app, container, false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    menu.clear();

    inflater.inflate(R.menu.menu_add_app, menu);
    MenuItem item = menu.findItem(R.id.action_search_menu_add_app);
    item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM);

    SearchView searchView = (SearchView) item.getActionView();
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {

        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            // Here is where we are going to implement the filter logic
            return true;
        }

    });
}

作为第二个选项,您可以让ActivityFragment实现SearchView.OnQueryTextListener,然后使用菜单搜索:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    setHasOptionsMenu(true); // Add this! (as above)
    return inflater.inflate(R.layout.fragment_add_app, container, false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    menu.clear();
    inflater.inflate(R.menu.menu_add_app, menu);
    MenuItem item = menu.findItem(R.id.action_search_menu_add_app);
    item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM);

    SearchView searchView = (SearchView) item.getActionView();
    searchView.setOnQueryTextListener(this); // Fragment implements SearchView.OnQueryTextListener
}

@Override
public boolean onQueryTextChange(String query) {
    // Here is where we are going to implement the filter logic
    return false;
}

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

1
您的 search_options_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"
        android:title="@string/app_name"
        android:icon="@drawable/ic_action_search"
        app:showAsAction="collapseActionView|ifRoom"
         />
</menu>

在您的片段中覆盖 onCreateOptionMenu 方法,setHasOptionsMenu(true); 在您的片段的 onCreate() 中。
@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
       menu.clear();
        inflater.inflate(R.menu.search_option_menu, menu);
        MenuItem item = menu.findItem(R.id.action_search);
                SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem);
        MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
        MenuItemCompat.setActionView(item, searchView);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }
            @Override
            public boolean onQueryTextChange(String newText) {
                    //Do search code here
                return true;
            }
        });

    }

1

我解决了这个问题,想要分享我的答案来解决搜索视图的空指针异常。

我们需要从主活动中删除以下方法。

      public boolean onOptionsItemSelected(MenuItem item) {
          int id = item.getItemId();  
          return true;

在 OnActivityCreated 方法中使用代码片段 setHasOptionsMenu(true),并覆盖方法。

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         inflater.inflate(R.menu.menu, menu);
    }

    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
       // handle item selection
        switch (item.getItemId()) {
            case R.id.action_search:

     //       onCall();   //your logic

            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

0
search_view.setOnQueryTextListener(object: SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String?): Boolean {
                return false
            }

            override fun onQueryTextChange(query: String?): Boolean {
                adapter.filter.filter(query)
                return true
            }
        })

不要在清单文件中为您的活动添加意图过滤器。

-1
在我的Fragment的onCreateOptionsMenu方法中,这段代码
SearchManager searchManager =
        (SearchManager)getActivity().getSystemService(Context.SEARCH_SERVICE);
SearchableInfo searchableInfo =
        searchManager.getSearchableInfo(getActivity().getComponentName());
searchItem = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setSearchableInfo( searchableInfo);

产生以下错误信息: java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'void android.support.v7.widget.SearchView.setSearchableInfo(android.app.SearchableInfo)'。

当我将menu.xml中的android:actionViewClass更改为app:actionViewClass后,问题就不再出现了。 menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  tools:context="...">
<item
android:id="@+id/menu_search"
android:title="@string/menu_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom">


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接