Android:过滤自定义适配器的结果未反射(reflect)在 UI 中

标签 android android-listview filtering

在我的应用程序中,我从网络服务器获取数据并在 ListView 中显示数据。我的 ListView 的适配器包含图像和文本。现在,我想过滤 ListView 。为此,我在自定义适配器中实现了 Filterable 接口(interface)。但是,它没有给出任何结果。我搜索了很多但找不到任何结果。这是我的代码:

主 Activity

Runnable r = new Runnable() 
        {
            @Override
            public void run() 
            { 
                listMainMenu.setAdapter(mMenuAdapter);
                listMainMenu.setTextFilterEnabled(true);
                mMenuAdapter.notifyDataSetChanged();
                pd.dismiss();
                updateUI = false;
            }//run
        };

文本观察器类

_txtAutoSearch.addTextChangedListener(filterTextWatcher);

private TextWatcher filterTextWatcher = new TextWatcher() {
    public void afterTextChanged(Editable s) {
        Log.v(TAG+" filtertextwatcher", "afterTextChanged");
    }//afterTextChanged

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        Log.v(TAG+" filtertextwatcher", "beforeTextChanged");
    }//beforeTextChanged

    public void onTextChanged(CharSequence s, int start, int before, int count) {
        Log.v(TAG+" filtertextwatcher", "onTextChanged");
        ((Filterable) listMainMenu.getAdapter()).getFilter().filter(s.toString());
    }//onTextChanged
};

我的自定义适配器:

    public class MainMenuAdapter extends BaseAdapter implements Filterable {
    Context ctx;
    ArrayList<MainCategoryDAO> mainCatDAOList;
    public static final String TAG = "MainMenuAdapter";
    ArrayList<MainCategoryDAO> arrayList;

    public MainMenuAdapter(Context ctx, ArrayList<MainCategoryDAO> mainCatDAOList) {
        this.ctx = ctx;
        this.mainCatDAOList = mainCatDAOList;
    }//Constructor

    public int getCount() {
        return mainCatDAOList.size();
    }//getCount

    public Object getItem(int position) {
        return mainCatDAOList.get(position);
    }//getItem

    public long getItemId(int position) {
        return 0;
    }//getItemId

    class ViewHolder {
        ImageView imgCategoryIcon;
        TextView txtCategoryName;
    }//ViewHolder

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if(convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_menu_adapter, null);
            holder = new ViewHolder();
            holder.imgCategoryIcon = (ImageView)convertView.findViewById(R.id.imgCategoryIcon);
            holder.txtCategoryName = (TextView)convertView.findViewById(R.id.txtCategoryName);
            convertView.setTag(holder);
        }//if
        else {
            holder = (ViewHolder) convertView.getTag();
        }//else
        Typeface cat_nameTF = Typeface.createFromAsset(ctx.getAssets(), "fonts/arial.ttf");
        Log.v(TAG, "category name "+ mainCatDAOList.get(position).getCategory_name());
        Log.v(TAG, "category icon "+ mainCatDAOList.get(position).getCategory_icon());
        BitmapManager.INSTANCE.loadBitmap(mainCatDAOList.get(position).getCategory_icon(), holder.imgCategoryIcon, 50, 50);
        holder.txtCategoryName.setTypeface(cat_nameTF);
        holder.txtCategoryName.setText(mainCatDAOList.get(position).getCategory_name());
        Log.v(TAG, "text view category name "+ holder.txtCategoryName.getText());
        return convertView;
    }//getView

    @Override
public Filter getFilter() 
{
    Filter mFilter = new Filter() 
    {

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint,
                FilterResults results) 
        {
            Log.v(TAG+" getFilter", "publishResults called");
            arrayList = (ArrayList<MainCategoryDAO>) results.values;
            Log.v(TAG+" getFilter", "publishResults arrayList size "+arrayList.size());
            for(int i = 0; i < arrayList.size(); i++)
            {
                Log.v(TAG+" getFilter filtered name", " "+arrayList.get(i).getCategory_name());
            }//for
            notifyDataSetChanged();
        }//publishResults

        @Override
        protected FilterResults performFiltering(CharSequence constraint) 
        {
            Log.v(TAG+" getFilter", "performFiltering called");
            FilterResults results = new FilterResults();
            ArrayList<MainCategoryDAO> FilteredArrList = new ArrayList<MainCategoryDAO>();

            if (constraint == null || constraint.length() == 0) 
            {
                Log.v(TAG+" getFilter", "if, constraint.length null or 0");
                results.count = mainCatDAOList.size();
                results.values = mainCatDAOList;
            }//if 
            else 
            {
                Log.v(TAG+" getFilter", "else, constraint.length not 0");
                constraint = constraint.toString();
                Log.v(TAG+" getFilter", "else, constraint = "+constraint);
                for (int i = 0; i < mainCatDAOList.size(); i++) 
                {
                    Log.v(TAG+" getFilter", "for loop, constraint.length not null or 0");
                    String data = mainCatDAOList.get(i).getCategory_name();
                    Log.v(TAG+" getFilter", "else, data to check "+data);
                    if (data.toLowerCase().startsWith(constraint.toString()))   
                    {
                        Log.v(TAG+" getFilter", "if in for loop, constraint.length not null or 0");
                        FilteredArrList.add(mainCatDAOList.get(i));
                    }//if
                }//for
                results.count = FilteredArrList.size();
                results.values = FilteredArrList;
            }//else
            return results;
        }//performFiltering
    };
    return mFilter;
}//getFilter
}//MainMenuAdapter

经过测试,我发现它正在过滤结果,但是 ListView 中没有反射(reflect)出变化。我什至尝试将 listview.setTextFilterEnabled() 设置为 true,但它也没有用。在我的 logcat 上,我可以看到过滤后的值。但不明白为什么相同的内容没有反射(reflect)在 UI 中。

最佳答案

您没有看到任何 UI 更改是正常的,因为您没有在过滤后更新正确的数据列表。您的 MainMenuAdapter 基于 mainCatDAOList 数据列表,但是在应该刷新适配器数据的 publishResults 方法中,您可以:

arrayList = (ArrayList<MainCategoryDAO>) results.values;
notifyDataSetChanged();

如您所见,您正在使用过滤后的值而不是 mainCatDAOList 更新 arrayList,因此适配器看不到任何更改。所以你的代码应该是:

protected void publishResults(CharSequence constraint,
            FilterResults results) {
        Log.v(TAG+" getFilter", "publishResults called");
        mainCatDAOList = (ArrayList<MainCategoryDAO>) results.values;
        Log.v(TAG+" getFilter", "publishResults arrayList size "+arrayList.size());
        for(int i = 0; i < arrayList.size(); i++)
        {
            Log.v(TAG+" getFilter filtered name", " "+arrayList.get(i).getCategory_name());
        }//for
        notifyDataSetChanged();
    }

此外,您还应该有一份用于过滤的初始数据列表的副本,否则您将无法返回完整的值集。

关于Android:过滤自定义适配器的结果未反射(reflect)在 UI 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14020646/

相关文章:

android - 如何在 android 中使用基本适配器时过滤列表项?

android - 将 Nfca 用于 Android 应用程序的 TagLostException

java - 运营商 !参数类型 Object 未定义?

没有自签名证书的 javax.net.ssl.SSLPeerUnverifiedException : Hostname XXX not verified,

android - 在 Android 中搜索 ListView 项后,始终打开 ListView 的第一项(问题)

php - 如何从 ListView 中删除选中的数据

android - 以编程方式设置背景覆盖可绘制

android - 从 fragment 到 Activity 的 onAttach 回调

基于 if else 语句的 iOS Realm 多重过滤器

powershell - 在 PowerShell 中,如何通过对象的嵌套属性键/值对象过滤对象?