EditText in ListView is updated by onTextChanged when scrolling

前端 未结 3 1435
失恋的感觉
失恋的感觉 2021-02-09 09:06

I have been searching for an answer to this, but the solutions don\'t seem to work for me. I have a TextView and an EditText in a list item. I am trying to update the stored v

3条回答
  •  难免孤独
    2021-02-09 09:30

    The problem is related to the fact that you are not removing the previously added text watcher from the EditText widget. Instead, you keep appending new watchers to the list. Once you attempt to edit widget content all text watchers get notified sequentially, resulting in wrong user details being updated.

    EditText/TextView does not provide a way to remove previously added text watchers without having an explicit reference to them. This means you will have to rework your code to keep references to text watchers and to either create/add/remove watchers for every getView method execution or to extend TextWatcher allowing altering user details to update once it gets fired. The latter is implemented below.

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.user_details_list_row, parent,false);
            holder = new ViewHolder();
            holder.mCaptionTextView  = (TextView)convertView.findViewById(id.user_detail_row_caption);
            holder.mWatcher = new MutableWatcher();
            holder.mDetailEditText = (EditText)convertView.findViewById(id.user_detail_row_value);
            holder.mDetailEditText.addTextChangedListener(holder.mWatcher);
            convertView.setTag(holder);
        } else{
            holder = (ViewHolder) convertView.getTag();
        }
    
        holder.mCaptionTextView.setText(mUserCaptions.get(position));
    
        holder.mWatcher.setActive(false);
        holder.mDetailEditText.setText(mUserDetails.get(position),BufferType.EDITABLE);
        holder.mWatcher.setPosition(position);
        holder.mWatcher.setActive(true);
    
        return convertView;
    }
    
    static class ViewHolder{
        public TextView mCaptionTextView;
        public EditText mDetailEditText;
        public MutableWatcher mWatcher;
    }
    
    class MutableWatcher implements TextWatcher {
    
        private int mPosition;
        private boolean mActive;
    
        void setPosition(int position) {
            mPosition = position;
        }
    
        void setActive(boolean active) {
            mActive = active;
        }
    
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
    
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) { }
    
        @Override
        public void afterTextChanged(Editable s) {
            if (mActive) {
                mUserDetails.set(mPosition, s.toString());
            }
        }
    }
    

    Hope this helps.

提交回复
热议问题