【问题标题】:Android: Results of filtering custom adapter are not reflecting in the UIAndroid:过滤自定义适配器的结果未反映在 UI 中
【发布时间】:2012-12-10 20:01:42
【问题描述】:

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

主活动

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.setTextFilterEnabled() 设置为 true,但也没有用。在我的 logcat 上,我可以看到过滤后的值。但不明白为什么 UI 中没有反映相同的内容。

【问题讨论】:

    标签: android android-listview filtering


    【解决方案1】:

    您看不到任何 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();
        }
    

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

    【讨论】:

    • 感谢您的回复。我已经修好了。归功于您在以下链接中发布的答案stackoverflow.com/questions/14002421/…
    • 对不起,由于我的无知,适配器如何知道 mainCatDAOList 是它的基本列表?
    • @user3019105 这是保存数据的列表(因此数据中的任何更改都会触发ListView 的行中的更改)并且其大小也用于getCount() 的方法适配器(告诉适配器其中有多少项)。
    • @user3019105 调用super() 不会做任何事情(grepcode.com/file/repository.grepcode.com/java/ext/…)。顾名思义,BaseAdapter 是基类,是所有其他适配器所基于的ListAdapter 接口的基本实现。对于已经有实现的其他适配器(如ArrayAdapter),调用超级构造函数是有意义的,通过扩展BaseAdapter,您必须自己提供一个实现。
    • @user3019105 刷新过程不直接绑定到数据列表。如果您点击该链接,您将看到调用 notifyDataSetChanged() 会触发在适配器中注册的某些侦听器中的调用。该侦听器由使用适配器的小部件注册(在本例中为ListView)。在监听器通知之后,小部件会触发一些检查并自行更新(通过测量和布局)以显示新数据。
    【解决方案2】:

    你加了吗

    Adapter.notifyDataSetChanged();

    在您的代码中?你能显示你的主要活动代码吗?我会帮助我们的。

    【讨论】:

    • 请添加,listMainMenu.setTextFilterEnabled(true);在运行方法中。比如, Runnable r = new Runnable() { @Override public void run() { listMainMenu.setAdapter(mMenuAdapter); listMainMenu.setTextFilterEnabled(true); mMenuAdapter.notifyDataSetChanged(); pd.dismiss();更新UI =假; }//跑步 };请告诉我结果是什么。
    • 什么是updateUI?它是一个布尔值吗?你能在 run 方法中改变它吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    相关资源
    最近更新 更多