栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

解决:SearchView不会在TabLayout的每个子Tab中进行过滤

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

解决:SearchView不会在TabLayout的每个子Tab中进行过滤

您可以 使用Observable / Observer模式
来管理嵌套列表上的筛选器,这将从一个Observable父对象中更新每个嵌套列表。我解决了所有麻烦,现在可以很好地实现正确的行为。

因此,这是我要做的事情:

  1. 使用一个家长
    SearchView
    Activity
  2. (可选)在嵌套列表中创建一个
    Filter
    类( android.widget.Filter
    Adapter
  3. 然后,使用一个
    Observable
    /
    Observer
    图案嵌套
    Fragment
    Activity

背景: 在尝试您的代码时,我遇到了三个问题:

  • 我无法使用ActionBar进行搜索:
    onQueryTextChange
    似乎从未在
    Fragment
    s中调用过。当我点击搜索图标时,在我看来,
    SearchView
    (编辑文本,图标等)未附带搜索小部件(而是附加到活动的小部件)。
  • 我无法运行自定义方法
    filter2
    :我的意思是,当我解决上一点时,该方法不起作用。确实,我必须使用通过
    Filter
    和扩展其两种方法的自定义类:
    performFiltering
    publishResults
    。没有它,当我在搜索栏中点击一个单词时,我将得到一个空白屏幕。但是,这可能只是我的代码,可能
    filter2()
    对您来说效果很好…
  • 我无法在片段之间进行持久搜索:为每个子片段
    SearchView
    创建一个新片段。在我看来,您反复
    SearchView sv = new SearchView(...);
    在嵌套片段中调用此行。因此,每次我切换到下一个片段时,展开的searchview都会删除其先前的文本值。

无论如何,经过一些研究,我在SO上找到了有关实现搜索片段的答案。除了您在父活动和片段中“复制”选项菜单代码外,几乎与您的代码相同。您不应该这样做-
我认为这是我先前提到的第一个问题的原因。
此外,答案链接中使用的模式(在一个片段中进行一次搜索)可能不适合您的模式(在一个片段中进行一次搜索)。您应在所有嵌套的父对象中调用一个。

SearchView``Activity``Fragment



解决方案: 这是我的管理方式:

#1使用父母

SearchView

它将避免重复的功能,并让父级活动监督其所有子级。此外,这将避免菜单中出现重复图标。
这是主要的父

Activity
类:

public class ActivityName extends AppCompatActivity implements SearchView.onQueryTextListener {    @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.menu_main, menu);        MenuItem item = menu.findItem(R.id.action_search);        SearchView searchview = new SearchView(this);        SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);        searchview.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));        ...        MenuItemCompat.setShowAsAction(item,      MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW |      MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);        MenuItemCompat.setActionView(item, searchview);        searchview.setonQueryTextListener(this);        searchview.setIconifiedByDefault(false);        return super.onCreateOptionsMenu(menu);    }    private void changeSearchViewTextColor(View view) { ... }    @Override    public boolean onQueryTextSubmit(String query) { return false; }    @Override    public boolean onQueryTextChange(String newText) {        // update the observer here (aka nested fragments)        return true;    }}

#2(可选)创建

Filter
小部件:

就像我之前说过的那样,我无法使其与一起使用

filter2()
,因此我
Filter
在网络上创建了一个示例作为任何示例。
很快,在嵌套片段的适配器中,如下所示:

private ArrayList<String> originalList; // I used String objects in my testsprivate ArrayList<String> filteredList;private ListFilter filter = new ListFilter();@Overridepublic int getCount() {    return filteredList.size();}public Filter getFilter() {    return filter;}private class ListFilter extends Filter {    @Override    protected FilterResults performFiltering(CharSequence constraint) {        FilterResults results = new FilterResults();        if (constraint != null && constraint.length() > 0) { constraint = constraint.toString().toLowerCase(); final List<String> list = originalList; int count = list.size(); final ArrayList<String> nlist = new ArrayList<>(count); String filterableString; for (int i = 0; i < count; i++) {     filterableString = list.get(i);     if (filterableString.toLowerCase().contains(constraint)) {         nlist.add(filterableString);     } } results.values = nlist; results.count = nlist.size();        } else { synchronized(this) {     results.values = originalList;     results.count = originalList.size(); }        }        return results;    }    @SuppressWarnings("unchecked")    @Override    protected void publishResults(CharSequence constraint, FilterResults results) {        if (results.count == 0) { notifyDataSetInvalidated(); return;        }        filteredList = (ArrayList<String>) results.values;        notifyDataSetChanged();    }}

#3使用

Observable
/
Observer
模式:

活动(带有searchview)是

Observable
对象,嵌套片段是
Observer
s(请参阅Observer模式)。基本上,当
onQueryTextChange
将调用时,它将
update()
在现有的观察者中触发该方法。
这是parent中的声明
Activity

private static ActivityName instance;private FilterManager filterManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {    ...    instance = this;    filterManager = new FilterManager();}public static FilterManager getFilterManager() {    return instance.filterManager; // return the observable class}@Overridepublic boolean onQueryTextChange(String newText) {    filterManager.setQuery(newText); // update the observable value    return true;}

这是

Observable
将侦听和“传递”更新的数据的类:

public class FilterManager extends Observable {    private String query;    public void setQuery(String query) {        this.query = query;        setChanged();        notifyObservers();    }    public String getQuery() {        return query;    }}

为了添加观察者片段以侦听searchview值,我在将它们初始化时进行了操作

FragmentStatePagerAdapter

因此,在父片段中,我通过传递来创建内容选项卡
FilterManager

private ViewPager pager;private ViewPagerAdapter pagerAdapter;@Overridepublic View onCreateView(...) {    ...    pagerAdapter = new ViewPagerAdapter(         getActivity(),         // pass the context,         getChildFragmentManager(),        // the fragment manager         MainActivity.getFilterManager()   // and the filter manager    );}

适配器会将观察者添加到父可观察对象,并在销毁子片段时将其删除。

ViewPagerAdapter
是父片段的:

public class ViewPagerAdapter extends FragmentStatePagerAdapter {    private Context context;    private FilterManager filterManager;    public ViewPagerAdapter(FragmentManager fm) {        super(fm);    }    public ViewPagerAdapter(Context context, FragmentManager fm,     FilterManager filterManager) {        super(fm);        this.context = context;        this.filterManager = filterManager;    }    @Override    public Fragment getItem(int i) {        NestedFragment fragment = new NestedFragment(); // see (*)        filterManager.addObserver(fragment); // add the observer        return fragment;    }    @Override    public int getCount() {        return 10;    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        NestedFragment fragment = (NestedFragment) object; // see (*)        filterManager.deleteObserver(fragment); // remove the observer        super.destroyItem(container, position, object);    }}

最后,使用

filterManager.setQuery()
in调用inactivity时
onQueryTextChange()
,这将在
update()
实现的方法中的嵌套片段中接收
Observer

这是带有
ListView
要过滤的嵌套片段:

public class NestedFragment extends Fragment implements Observer {    private boolean listUpdated = false; // init the update checking value    ...    // setup the listview and the list adapter    ...    // use onResume to filter the list if it's not already done    @Override    public void onResume() {        super.onResume();        // get the filter value        final String query = MainActivity.getFilterManager().getQuery();        if (listview != null && adapter != null&& query != null && !listUpdated) { // update the list with filter value listview.post(new Runnable() {     @Override     public void run() {         listUpdated = true; // set the update checking value         adapter.getFilter().filter(query);     } });        }    }    ...    // automatically triggered when setChanged() and notifyObservers() are called    public void update(Observable obs, Object obj) {        if (obs instanceof FilterManager) { String result = ((FilterManager) obs).getQuery(); // retrieve the search value if (listAdapter != null) {     listUpdated = true; // set the update checking value     listAdapter.getFilter().filter(result); // filter the list (with #2) }        }    }}

#4。结论:

效果很好,所有嵌套片段中的列表仅通过一个searchview即可按预期进行更新。但是,在我上面的代码中有一个不便之处,您应注意:

  • (请参见下面的改进) 我无法调用
    Fragment
    常规对象并将其添加为观察者。实际上,我必须使用特定的片段类(在此处
    NestedFragment
    )进行强制转换和初始化。可能有一个简单的解决方案,但我暂时找不到。

尽管如此,我还是得到了正确的行为,并且-我认为-
通过在活动中保持顶部的一个搜索小部件,这可能是一个很好的模式。因此,使用此解决方案,您可以获得正确的方向线索,以实现所需的目标。希望您会喜欢。


#5改进(编辑):

  • (请参阅*), 可以通过

    Fragment
    在所有嵌套片段上保留全局类扩展来添加观察者。这就是我将片段实例化到的方式
    ViewPager

    @Override

    public Fragment getItem(int index) {
    Fragment frag = null;
    switch (index) {
    case 0:
    frag = new FirstNestedFragment();
    break;
    case 1:
    frag = new SecondFragment();
    break;

    }
    return frag;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
    ObserverFragment fragment =
    (ObserverFragment) super.instantiateItem(container, position);
    filterManager.addObserver(fragment); // add the observer
    return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
    filterManager.deleteObserver((ObserverFragment) object); // delete the observer
    super.destroyItem(container, position, object);
    }

通过

ObserverFragment
如下创建类:

    public class ObserverFragment extends Fragment implements Observer {    public void update(Observable obs, Object obj) {  }}

然后,通过扩展和覆盖

update()
嵌套片段:

    public class FirstNestedFragment extends ObserverFragment {    @Override    public void update(Observable obs, Object obj) { }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/508887.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号