列表视图滚动时复选框自动调用onCheckedChange?

Posted

技术标签:

【中文标题】列表视图滚动时复选框自动调用onCheckedChange?【英文标题】:Checkbox auto call onCheckedChange when listview scroll? 【发布时间】:2011-08-31 07:50:50 【问题描述】:

我对包含复选框的列表视图有疑问。当我选中一个框并滚动列表时,复选框有时会自动调用 oncheckedchange 并且复选框的值会更改!

或者,当我的列表有超过 9 或 10 项时,当我在第 1 项检查时,第 8 项或第 9 项被选中???

谁能告诉我如何解决这个错误?

提前致谢!

list_item.xml

<ImageView
    android:layout_alignParentLeft="true"
    android:layout_
    android:layout_
    android:layout_centerVertical="true"
    android:scaleType="fitCenter"
    android:id="@+id/image_view"
    android:src="@drawable/icon" />

<TextView android:layout_toRightOf="@id/image_view"
    android:layout_
    android:layout_
    android:paddingLeft="5dip"
    android:id="@+id/text_view"
    android:lines="1"
    android:textSize="20sp"
    android:textColor="@color/white" />

<TextView android:layout_toRightOf="@id/image_view"
    android:layout_below="@id/text_view"
    android:layout_
    android:layout_
    android:paddingLeft="5dip"
    android:id="@+id/text_view2"
    android:textSize="14sp"
    android:lines="1"
    android:textColor="@color/white" />          

这是适配器视图:

    public View getView(int position, View convertView, ViewGroup parent) 
        Log.e(TAG, "getView");
        ViewHolder mViewHolder;
        if (convertView == null) 
            Log.e(TAG, "Inflater is inflating...");
            convertView = mInflater.inflate(R.layout.custom_list_app, null);
            mViewHolder = new ViewHolder();
            mViewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);
            mViewHolder.remove = convertView.findViewById(R.id.music_info);
            convertView.setTag(mViewHolder);
         else 
            mViewHolder = (ViewHolder) convertView.getTag();
            Log.e(TAG, "Position: " + position + " CheckBox: " + mViewHolder.checkbox.isChecked());
           
        mViewHolder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() 

            @Override
            public void onCheckedChanged(CompoundButton cb, boolean flag) 
                // TODO Auto-generated method stub
                if (flag) 
                    Log.d(TAG, "Checkbox checked");
                 else 
                    Log.d(TAG, "Checkbox un-checked");
                
            
        );


        return convertView;
    

【问题讨论】:

【参考方案1】:

ListView 回收视图类:您需要明确设置是否在 getView 类中选中 CheckBox。所以添加一个像

/**
*    Ensure no other setOnCheckedChangeListener is attached before you manually
*    change its state.
*/
mViewHolder.checkbox.setOnCheckedChangeListener(null);
if(shouldBeChecked) mViewHolder.checkbox.setChecked(true);
else mViewHolder.checkbox.setChecked(false);

在您致电setOnCheckedChangeListener之前。

【讨论】:

所以我认为解决方案是这样的。当复选框被选中时,我使用一个数组来存储位置,并在调用 setOnCheckedChangeListener 之前检查位置被选中的位置。但是当我滚动列表(不检查)时,检查的位置发生了变化!我不明白为什么会这样 好吧,你应该总是打电话给setOnCheckedChangeListener,但是你应该使用position参数来告诉getView是否应该选中复选框并每次都适当地更改它getView被调用。 让我重复一遍:如果您要覆盖 getView,则每次调用 getView 时都必须调用 setChecked(true)setChecked(false) 费米,说得对。我错过了将 onchangelistner 设置为 null 的调用,并且更改的检查会自动触发。在设置值之前取消设置监听器是至关重要的。 我已经有一个星期的问题了!你救了我的命,先生。在执行 setChecked 以拥有重载方法或是否调用 onCheckChange 回调时有一个选项会很棒。只是说。【参考方案2】:
holder.cBox.setOnCheckedChangeListener(null);
holder.cBox.setChecked(list.get(position).isChecked());
holder.tvName.setText(item.getName());

holder.cBox.setOnCheckedChangeListener(new OnCheckedChangeListener()

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    
        if (isChecked)
        
            list.get(position).setChecked(true);
        
        else
        
            list.get(position).setChecked(false);
        
    
);

在列表中,item 有一个属性来设置item 是否被选中。您可以使用它来设置您的项目是否选中,首先您应该设置

cBox.setOnCheckedChangeListener(null);
cBox.setChecked(list.get(position).isChecked());

然后设置真正的new OnCheckedChangeListener()

我希望我的回答对您和那些查看此页面或在处理带有项目复选框的列表视图时遇到问题的人有用。

【讨论】:

【参考方案3】:

我不确定这是否是一种简洁的方式。但是下面的代码解决了我的问题。即使在下面的代码中,在滚动列表时也会调用 setOnCheckChangeListener()(读取错误触发)。任务是维护用户选择的项目列表。因此,当有触发器时,我首先引用我的列表,并且仅在列表中不存在该项目时才添加该项目,否则我将忽略回调。

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


    MenuViewHolder menuViewHolder = null;
    MenuView item = getItem(position);


    LayoutInflater inflater = ((Activity) context).getLayoutInflater();

    convertView = inflater.inflate(R.layout.food_menu_list_layout, null);

    TextView textView = ((TextView) convertView.findViewById(R.id.menu_item_entry));
    TextView price = (TextView) convertView.findViewById(R.id.price);
    CheckBox ordered = (CheckBox) convertView.findViewById(R.id.checkBox);

    menuViewHolder = new MenuViewHolder(textView, price, ordered);

    menuViewHolder.dishName.setText(menuViewList.get(position).getItemname());
    menuViewHolder.price.setText("$" + menuViewList.get(position).getPrice());
    menuViewHolder.ordered.setChecked(menuViewList.get(position).isSelected());

    menuViewHolder.ordered.setOnCheckedChangeListener(null);


    menuViewHolder.ordered.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 

            MenuView checkedItem = menuViewList.get(position);
            if (buttonView.isChecked()) 

                //add item only if not already added
                if (!checkedItem.isSelected()) 
                    MainActivity.menuViews.add(checkedItem);
                    checkedItem.setSelected(buttonView.isChecked());
                       


             else 

                //remove only if already added
                if (checkedItem.isSelected())
                    MainActivity.menuViews.remove(checkedItem);
                    checkedItem.setSelected(buttonView.isChecked());
                                    
            

            ((MainActivity) context).displayCurrentSelectionAmt();
        
    );


return convertView;


【讨论】:

【参考方案4】:

其中大多数都过于复杂(但它们确实有效)。如果正在加载视图并设置检查状态,您要做的就是停止触发 .setChecked 事件。所以,设置一个局部类变量isLoading,在getView开始时设置为true,在getView结束时设置为false。然后在点击监听中,勾选isLoading

boolean isLoading;
public View getView(int position, View convertView, ViewGroup parent)
    isLoading = true;

    ...do your initialization here

    isLoading = false;
    return convertView;

checkview.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 
        @Override
        public void onCheckedChanged(CompoundButton pckView, boolean pisChecked) 
            if(! isLoading) 
                ...do your things when the check is actually clicked
            
        
    );

【讨论】:

【参考方案5】:

OnClickListener 为我解决了同样的问题,我可以将数据发送到另一个活动

holder.cks.setOnClickListener(new View.OnClickListener()

            @Override
            public void onClick(View v) 
                final boolean isChecked = holder.cks.isChecked();
                if (isChecked) 
                    System.out.println(position + "Checked");
                    holder.cks.setChecked(true);
                    positionArray.set(position, true);
                    DATA2="1";



                 else 
                    System.out.println(position + "unChecked");
                    holder.cks.setChecked(false);
                    positionArray.set(position, false);

                    DATA2 = "0";

                
                DATA1=String.valueOf(position+1);

                DATA3=map.get(COL5);
                DATA4=map.get(COL6);
                DATA5=map.get(COL7);



                Intent intent = new Intent(activity, updatelicaldata.class);
                intent.putExtra("message1", DATA1);
                intent.putExtra("message2", DATA2);
                intent.putExtra("message3", DATA3);
                intent.putExtra("message4", DATA4);
                intent.putExtra("message5", DATA5);
                System.out.println("ACTIVITY IS START");

                activity.startActivity(intent);

            
            );

【讨论】:

以上是关于列表视图滚动时复选框自动调用onCheckedChange?的主要内容,如果未能解决你的问题,请参考以下文章

当我在 Android 上滚动列表视图时复选框未选中

在回收站视图中滚动时,它向选定的复选框列表添加了一些其他值

带有光标适配器滚动问题的android列表视图

滚动自定义 ListView 时,复选框值发生变化

滚动列表视图 BaseAdapter 上的复选框选中/未选中状态更改

选中复选框时 TableView 自动滚动