【问题标题】:Android: Custom Adapter with ViewHolder, OnCheckedChangedListener and TextChangedListenerAndroid:带有 ViewHolder、OnCheckedChangedListener 和 TextChangedListener 的自定义适配器
【发布时间】:2014-02-24 22:12:35
【问题描述】:

我是 Android 和 Java 编程的新手,最近遇到了一个问题。我一直在寻找答案几个小时,但我没有成功。 我有一个自定义 ListView 和一个自定义适配器,其中一行包含一个 CheckBox 和一个 EditText。每次第一次显示时都可以,但是当我向下滚动时,它开始更改 CheckBox 和 EditText 的值。

这是我的 row_edit.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <EditText
        android:id="@+id/bonus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:inputType="numberSigned"
        android:gravity="right"
        android:selectAllOnFocus="true"
        android:textSize="16sp" />

    <CheckBox
        android:id="@+id/checkBox_person"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@id/bonus"
        android:textSize="16sp" />

</RelativeLayout>

Item_edit(适配器项):

public class Item_edit {
    private String meno;
    private boolean ucast;
    private int bonus;

    public Item_edit(String meno, boolean ucast, int bonus) {
        super();
        this.meno = meno;
        this.ucast = ucast;
        this.bonus = bonus;
    }

    public String getMeno() {
        return meno;
    }

    public boolean getUcast() {
        return ucast;
    }

    public int getBonus() {
        return bonus;
    }

    public void setMeno(String meno) {
        this.meno = meno;
    }

    public void setUcast(boolean ucast) {
        this.ucast = ucast;
    }

    public void setBonus(int bonus) {
        this.bonus = bonus;
    }
}

当我滚动时,ListView 不流畅,这就是我决定使用 ViewHolder 的原因。 适配器编辑:

public class Adapter_edit extends ArrayAdapter<Item_edit> {
    private final Context context;
    private final ArrayList<Item_edit> itemsArrayList;
    private final Edit edit;

    public Adapter_edit(Context context, ArrayList<Item_edit> itemsArrayList, Edit edit) {

        super(context, R.layout.row_edit, itemsArrayList);
        this.edit = edit;
        this.context = context;
        this.itemsArrayList = itemsArrayList;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.row_edit, parent, false);
            holder = new ViewHolder();
            //Log.e("NewHolder", "position = " + position);
            holder.checkBox = (CheckBox) convertView
                    .findViewById(R.id.checkBox_person);
            holder.bonus = (EditText) convertView.findViewById(R.id.bonus);
            convertView.setTag(holder);

            holder.checkBox.setText(itemsArrayList.get(position).getMeno());
            holder.checkBox.setChecked(itemsArrayList.get(position).getUcast());
            holder.bonus.setText(Integer.toString(itemsArrayList.get(position)
                    .getBonus()));

            holder.checkBox
                    .setOnCheckedChangeListener(new OnCheckedChangeListener() {

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

                            itemsArrayList.get(position).setUcast(isChecked);
                        }
                    });

            holder.bonus.addTextChangedListener(new TextWatcher() {

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    try {

                        if (itemsArrayList.get(position).getBonus() != Integer
                                .parseInt(s.toString()) && !edit
                                .getUcast(position)) {
                            itemsArrayList.get(position).setBonus(
                                    Integer.parseInt(s.toString()));
                            itemsArrayList.get(position).setUcast(true);
                        }
                    }
                    catch (NumberFormatException e) {
                        itemsArrayList.get(position).setBonus(0);
                    }

                }

                @Override
                public void afterTextChanged(Editable s) {
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }
            });

        }

        else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.checkBox.setText(itemsArrayList.get(position).getMeno());
        holder.checkBox.setChecked(itemsArrayList.get(position).getUcast());
        holder.bonus.setText(Integer.toString(itemsArrayList.get(position)
                .getBonus()));

        return convertView;
    }

    static class ViewHolder {
        CheckBox checkBox;
        EditText bonus;
    }
}

使用 LogCat 调试后,我知道只生成了 8 个持有者(因为有 (0-7) 个项目适合我的屏幕)。当我向下滚动时,这些正在被重用。没有为位置大于 7 的项目创建 OnCheckedChangeListeners 和 TextChangedListeners。

我不知道该怎么做。有人可以帮我吗?

【问题讨论】:

    标签: java android android-listview custom-adapter


    【解决方案1】:

    我终于得到了答案。

    我扩展了 EditText,创建了我自己的 UpgEditText 类,它能够使用 setOnTextChangedListener 方法,这意味着删除现有的 TextWatcher 并添加一个新的。

    UpgEditText

    public class UpgEditText extends EditText {
        public UpgEditText(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public UpgEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public UpgEditText(Context context) {
            super(context);
        }
    
        TextWatcher watcher = null;
    
        public void setOnTextChangedListener(final int position, final Adapter_edit adapter) {
            if (watcher != null) {
                this.removeTextChangedListener(watcher);
            }
    
            watcher = new TextWatcher() {
    
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }
    
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }
    
                @Override
                public void afterTextChanged(Editable s) {
                    try {
                        adapter.itemsArrayList.get(position).setBonus(
                                Integer.parseInt(s.toString()));
                    }
                    catch (Exception e) {
                    }
                }
            };
            this.addTextChangedListener(watcher);
        }
    }
    

    我也正常使用了ViewHolder:

    public class ViewHolder {
        CheckBox chBoxUcast;
        UpgEditText edTBonus;
    }
    

    CustomAdapter getView() 方法:

    public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
    
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) context
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.row_edit, parent, false);
    
                holder = new ViewHolder();
                holder.chBoxUcast = (CheckBox) convertView
                        .findViewById(R.id.checkBox_person);
                holder.edTBonus = (UpgEditText) convertView
                        .findViewById(R.id.bonus);
                convertView.setTag(holder);
            }
            else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            holder.edTBonus.setOnTextChangedListener(position, this);
            holder.chBoxUcast
                    .setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
                        @Override
                        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                            // TODO Auto-generated method stub
                            itemsArrayList.get(position).setUcast(isChecked);
                        }
                    });
    
            holder.chBoxUcast.setText(itemsArrayList.get(position).getMeno());
            holder.chBoxUcast.setChecked(itemsArrayList.get(position).getUcast());
            holder.edTBonus.setText(Integer.toString(itemsArrayList.get(position)
                    .getBonus()));
    
            return convertView;
    
        }
    

    现在一切正常。每次回收一个convertView,我只改变监听器,效果很好。

    【讨论】:

      猜你喜欢
      • 2015-08-22
      • 2013-10-07
      • 2012-09-22
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多