在自定义列表视图中编辑文本在滚动上丢失值

时间:2014-05-29 19:03:52

标签: android android-listview android-edittext android-custom-view

我知道这是重复的问题,但我找不到合适的答案。 在我的自定义列表视图中有两个textview和一个Editext,当我在编辑文本中插入一个值并滚动时,我丢失了编辑文本的值。 当我通过列表适配器传递适配器的字符串值时,它将显示空白的编辑文本。

这是我的适配器代码:

class CreateAdapter extends ArrayAdapter<String> {
        String[] strItecode=null;
        String[] strItem;
        String[] strQuantity,text;
        Context context;
        int temp;
        CreateAdapter(Context context, String[] strItemcode, String[] strItem,
                String[] strQauntity) {
            super(context, R.layout.create_list_item, R.id.txtItemcode, strItemcode);
            this.context = context;
            this.strItecode = strItemcode;
            this.strItem = strItem;
            this.strQuantity = strQauntity;
            text= new String[strItem.length];
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            temp=position;
            LayoutInflater mInflater = (LayoutInflater) context
                    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            if (convertView == null) {

                holder = new ViewHolder();
                convertView = mInflater
                        .inflate(R.layout.create_list_item, parent, false);

                holder.txtItecode = (TextView) convertView
                        .findViewById(R.id.txtItemcode);
                holder.txtItem = (TextView) convertView
                        .findViewById(R.id.txtItem);
                holder.editQuantity = (EditText) convertView
                        .findViewById(R.id.editcreateQuantity);
                holder.editQuantity.setTag(position);

                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
          holder.editQuantity.addTextChangedListener(new TextWatcher() {

              @Override
              public void onTextChanged(CharSequence s, int start,
                      int before, int count) {
                  text[temp] = s.toString();
              }

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

              }

              @Override
              public void afterTextChanged(Editable s) {

              }
          });
            holder.txtItecode.setText(strItecode[position]);
            holder.txtItem.setText(strItem[position]);
            holder.editQuantity.setText(text[temp]);

            return convertView;
        }

        class ViewHolder {
            TextView txtItecode;
            TextView txtItem;
            EditText editQuantity;
        }
    }

我正在研究过去3天,我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

除了一些关于可能使用ScrollView的评论之外,您的代码的真正问题是ListView的适配器如何将Views与TextWatcher一起重用。

每次需要显示一行时,都会调用该位置的getView()方法。适配器可以并且将重复使用您在先前遍历中膨胀的实际视图来节省内存。

这通常是一件好事,但当您使用EditTexts和TextWatchers时会产生影响。

首先,holder.editQuantity.addTextChangeListener()将继续在每个布局传递上添加新的TextWatcher。这很糟糕,对你的问题负有部分责任。

其次,一旦重复使用某个视图,您在设置TextWatcher之后实际上会更改其中的文本,这将触发旧的(如果有的话)和新的TextWatchers&#39; onTextChanged()方法并更改您的存储值,这反过来会弄乱您的视图。

如果你想使用这个去ListView / Adapter路由,你的解决方案是拥有一个全局TextWatcher变量,在getView()中设置文本之前从View中删除TextWatcher(这样它就没有了)当你不想要它时发射它的事件,然后在你设置文本后重新添加它。但是,由于您无法继续创建新的TextWatchers(因为这会阻止您删除旧的TextWatchers以及遇到混乱值的相同问题),您还需要一种方法来链接到文本[]中的适当位置,因为您无法从getView()方法指向它。但是,您可以设置EditText的FocusChangeListener以确定视图何时具有焦点(即正在编辑它)并从中设置适当的编辑位置

E.g。

private int editingPosition = 0;
private TextWatcher watcher = new TextWatcher() {
          public void onTextChanged(CharSequence s, int start, int before, int count) {
              text[editingPosition] = s.toString();
          }
          public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
          public void afterTextChanged(Editable s) { }
      };

public View getView(int position, View convertView, ViewGroup parent) {

       // Before this is fine

      holder.editQuantity.removeTextChangedListener(watcher);

      holder.editQuantity.setText(text[temp]);

      holder.editQuantity.setOnFocusChangeListener(new OnFocusChangeListener() {       
          public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus) editingPosition = position;
          }
      });

      holder.editQuantity.addTextChangedListener(watcher);

      // The rest is good, just make sure to remove the call to setting the EditText's text at the end

      return convertView;
}