【问题标题】:Updating child item in ExpandableListView更新 ExpandableListView 中的子项
【发布时间】:2015-05-25 09:58:56
【问题描述】:

我有一个 ExpandableListView 样式的购物车。

我正在尝试更新子项的正确可绘制图形。所有子项都开始显示“+”,我希望在单击时将其更改为“-”。

我尝试在适配器中执行此操作,但是当我滚动列表并打开其他组选项卡时,我注意到以前未单击的项目中的项目也被修改了。

我不确定我的适配器中的视图回收是否存在问题,或者是否有其他原因可能导致此问题。这是我的代码:

自定义适配器 getChildView 方法

    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View childView, ViewGroup parent) {

    final View row;
    final FullMenuItemHolder fullMenuItemHolder;

    if (childView == null) {

        LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = inflater.inflate(R.layout.full_menu_child_item, parent, false);
        fullMenuItemHolder = new FullMenuItemHolder(row);
        row.setTag(fullMenuItemHolder);
    }

    else {
        row = childView;
        fullMenuItemHolder = (FullMenuItemHolder) row.getTag();
    }


    // set item name
    fullMenuItemHolder.title.setText(getChild(groupPosition, childPosition).getVenue_item_name());

    row.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            //check to see if item flagged as added to cart and set the respective drawable image
            if (!getChild(groupPosition,childPosition).getAddedToCart()) {
                getChild(groupPosition,childPosition).setAddedToCart(true);
                fullMenuItemHolder.title.setCompoundDrawablesWithIntrinsicBounds(null, null, fragment.getResources().getDrawable(R.drawable.remove), null);


            } else {
                getChild(groupPosition,childPosition).setAddedToCart(false);
                fullMenuItemHolder.title.setCompoundDrawablesWithIntrinsicBounds(null, null, fragment.getResources().getDrawable(R.drawable.add), null);

            }
        }
    });



    return row;
}

在 Fragment 中设置适配器 (服务器下载后从 asyncTask 中的 onPostExecute 调用)

 fullMenuExpListAdapter = new FullMenuExpListAdapter(this.getActivity(), listHeaderNames, listChildItems, this);
 expandableListView.setAdapter(fullMenuExpListAdapter);

【问题讨论】:

    标签: android expandablelistview expandablelistadapter


    【解决方案1】:

    行视图被 ListView 重用,这就是为什么点击似乎会更改多行。如果您再稍微调整一下列表,您还会注意到加号/减号实际上是随机的,之前点击了哪些并不重要。

    在此行之后,您应该手动更新复合可绘制对象,类似于您的 OnClickListener:

    // set item name
    fullMenuItemHolder.title.setText(getChild(groupPosition, childPosition).getVenue_item_name());
    

    这可确保新行和重复使用的行都显示正确的图标。


    (我对您的评论的回复太长了。)

    这个问题实际上没有什么随机的,它只是我解释的捷径。 :)

    这样想:任何完全离开屏幕的行都会在最后一个像素滚动出来的那一刻被扔到回收堆上。它保持原样 - 没有子视图被自动清除或修改。

    当新行进入屏幕时,ListView 首先检查剩余的堆(所需视图类型的)。如果找到,您的适配器将有一次机会使用新数据更新所有内容。如果您忘记更新任何内容,您将留下早期项目的残余 - 就像您原始问题中的可绘制对象。

    但请记住,这不仅适用于视觉状态,还适用于行为

    如果您没有创建新的 OnClickListener 实例(例如,您将代码放在上面的 if 中),groupPositionchildPosition 将永远不会改变初始值,因此单击一行可能更新一个完全不同的模型对象!即使 UI 看起来正常,但模型会不一致。

    将视图更新逻辑从适配器移动到您的 ViewHolder 可能很有用,并给它一个设置标题、侦听器等的单个 bindModel(ChildType child) 方法。更容易阅读和验证所有内容是否已正确设置每次。
    (新的 RecyclerView 工作方式类似,你应该查一下。)


    tl;dr:必须确保在您的适配器实现中更新依赖于行的数据模型的所有内容,否则龙将消耗我们所有人。

    【讨论】:

    • 这似乎成功了!我试图了解为什么会发生这种情况。我想知道为什么点击是随机的?我发现列表视图视图回收有点混乱。
    • 这很棒。非常感谢您花时间为我提供有关该主题的一些背景知识。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 2019-05-23
    • 2022-11-07
    • 2013-11-16
    相关资源
    最近更新 更多