Android onQueryTextChange 不显示 UI 更改

Posted

技术标签:

【中文标题】Android onQueryTextChange 不显示 UI 更改【英文标题】:Android onQueryTextChange not showing UI changes 【发布时间】:2020-10-21 06:04:23 【问题描述】:

当我开始输入我的android.widget.SearchView 时,我能够找到输入文本的匹配项,并看到我的Filter 来自我的Adapter,它扩展了BaseAdapter,确实找到了结果,但是,我在输入时实际上并没有看到建议的列表。

这是我所拥有的:

@Override
public boolean onCreateOptionsMenu(Menu menu) 
    super.onCreateOptionsMenu(menu);

    MenuItem searchItem = menu.add(Menu.NONE, R.id.search_card, 1, R.string.search_card);
    searchItem.setIcon(R.drawable.search);
    searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);

    LinearLayout searchLayout = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.search_view, null);
    SearchView searchView = searchLayout.findViewById(R.id.searchVieww);
    searchItem.setActionView(searchView);
    
    //this will be a dynamic list in the end, but just wanna get it to work first...
    List<ListViewItem> suggestionList = new ArrayList<>();
    suggestionList.add(new ListViewItem("abc", "123"));
    suggestionList.add(new ListViewItem("apple", "345"));
    ListViewAdapter adapter = new ListViewAdapter(suggestionList);
    ListView listView = searchLayout.findViewById(R.id.searchViewList);
    listView.setAdapter(adapter);

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() 
        @Override
        public boolean onQueryTextSubmit(String word) 
            searchCardsForWord(word.trim());
            searchView.setIconified(true); //first call to clear search bar
            searchView.setIconified(true); //second call to close search bar
            return true;
        

        @Override
        public boolean onQueryTextChange(String word) 
            adapter.getFilter().filter(word);
            Log.d("DEBUG", "query text filter: " + adapter.getCount());// the count of this is NOT zero when I type in 'a'
            return false;
        
    );

    ...adding other MenuItems

    return true;

适配器

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;

import com.boredofnothing.flashcard.databinding.ListViewItemBinding;

import java.util.ArrayList;
import java.util.List;

public class ListViewAdapter extends BaseAdapter implements Filterable 
    private List<ListViewItem> itemList;
    private List<ListViewItem> itemListFull;
    private LayoutInflater inflater;

    ListViewAdapter(List<ListViewItem> itemList) 
        this.itemList = itemList;
        itemListFull = new ArrayList<>(itemList);
    

    @Override
    public int getCount() 
        return itemList.size();
    

    @Override
    public ListViewItem getItem(int position) 
        return itemList.get(position);
    

    @Override
    public long getItemId(int position) 
        return position;
    

    @Override
    public Filter getFilter() 
        return filter;
    

    private Filter filter = new Filter() 
        @Override
        protected FilterResults performFiltering(CharSequence constraint) 
            List<ListViewItem> filteredList = new ArrayList<>();

            if (constraint == null || constraint.length() == 0) 
                filteredList.addAll(itemListFull);
             else 
                String filterPattern = constraint.toString().toLowerCase().trim();

                for (ListViewItem item : itemListFull) 
                    if (item.getText1().toLowerCase().contains(filterPattern)
                        || item.getText2().toLowerCase().contains(filterPattern)) 
                        filteredList.add(item);
                    
                
            

            FilterResults results = new FilterResults();
            results.values = filteredList;

            return results;
        

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) 
            itemList.clear();
            itemList.addAll((List) results.values);
            notifyDataSetChanged();
        
    ;

    @Override
    public View getView(int position, View convertView, final ViewGroup parent) 

        if (inflater == null) 
            inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        

        ListViewItemBinding listViewItemBinding = ListViewItemBinding.inflate(inflater);
        listViewItemBinding.textView1.setText(itemList.get(position).getText1());
        listViewItemBinding.textView2.setText(itemList.get(position).getText2());

        return listViewItemBinding.getRoot();
    

search_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:focusableInTouchMode="true"
    android:orientation="vertical">

    <SearchView
        android:id="@+id/searchVieww"
        android:layout_
        android:layout_
        android:queryHint="Input word to search"></SearchView>

    <ListView
        android:id="@+id/searchViewList"
        android:layout_
        android:layout_
        android:layout_marginTop="16dp"
        android:layout_marginBottom="16dp"
        android:padding="8dp"
        android:scrollbars="none" />

</LinearLayout>

list_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:layout_marginBottom="4dp"
    app:cardCornerRadius="4dp">

    <RelativeLayout
        android:layout_
        android:layout_
        android:layout_margin="4dp">

        <TextView
            android:id="@+id/text_view1"
            android:layout_
            android:layout_
            android:layout_alignParentTop="true"
            android:textColor="@android:color/black"
            android:textSize="20sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/text_view2"
            android:layout_
            android:layout_
            android:layout_below="@+id/text_view1"
            android:layout_marginStart="8dp"
            android:textSize="15sp" />
    </RelativeLayout>

</android.support.v7.widget.CardView>

在选择 SearchView 之前:

选择 SerachView 后:

输入“a”后:

最后,如果输入的单词/字符匹配或包含在我的suggestionList 中,我希望看到Cardviews 中的ListView

【问题讨论】:

你能发布你的 ListViewAdapter 吗?你是如何在你的适配器中实现过滤器的? @Gautam 我更新了我的帖子。过滤器只是检查输入的单词/字符是否存在于现在硬编码的列表中(这最终将是一个动态列表,但我只是想让它先工作) 如何将 search_view 添加到您的活动中?我假设此布局未绑定到您的活动 LinearLayout searchLayout = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.search_view, null);您必须将其添加到您的活动布局中才能显示结果 【参考方案1】:

我只是在我的活动布局中添加 ListView

private SearchView searchView;
private ListView listView;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.search_view);
    searchView = findViewById(R.id.searchVieww);
    listView = findViewById(R.id.searchViewList);

【讨论】:

很抱歉,问了这么一个琐碎的问题,您究竟添加了哪一行来使其正常工作? @mrnoobynoob 我已经用 sn-p 代码更新了上面的答案 在我的情况下,我实际上最终做了: ViewGroup rootLayout = findViewById(android.R.id.content); rootLayout.addView(searchLayout);但是,由于您的原始评论帮助我解决了我的问题,因此我仍会将其标记为我接受的答案。【参考方案2】:

问题在于您发布结果的方式。

itemList.clear();改成

itemList = (List) results.values
        

发生的事情是,一旦您清除,所有对象都具有相同的引用,因此所有数据都丢失了,您看不到任何结果。

【讨论】:

不幸的是,我仍然得到与该更改相同的输出...我在 UI 上没有看到任何建议的列表,但我确实看到它仍然从过滤器中获得正确的结果.. . 我建议您在调用 notifyDataSetChanged 之前调试发布结果中列表的大小。如果您的列表中有项目并且您正在通知,那么您将在 UI 上看到结果

以上是关于Android onQueryTextChange 不显示 UI 更改的主要内容,如果未能解决你的问题,请参考以下文章

去除searchView的黑框去除

无法解析方法 .getFilter()

如何捕获 SearchView 的清除按钮点击?

在ListView中搜索特定描述时,SearchView不会刷新

如何为从 Firestore 填充的 RecyclerView 实现过滤器?

配置AsyncTask以在自动完成搜索中使用的最佳方法