我一直在寻找答案,但解决方案似乎对我不起作用。我在列表项中有一个TextView和一个EditText。我正在尝试在用户编辑时更新EditTexts的存储值。
@Override
public View getView(int index, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final int pos = index;
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.mDetailEditText = (EditText)convertView.findViewById(id.user_detail_row_value);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.mDetailEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
mUserDetails.set(pos, s.toString());
}
});
holder.mCaptionTextView.setText(mUserCaptions.get(index));
holder.mDetailEditText.setText(mUserDetails.get(index),BufferType.EDITABLE);
return convertView;
}
public static class ViewHolder{
public TextView mCaptionTextView;
public EditText mDetailEditText;
}
当我这样做时,滚动会触发TextWatcher并更新值,并使用其他EditTexts中的一个重复文本覆盖正确的文本。
我还试过这段代码而不是TextWatcher:
holder.mDetailEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
EditText et = (EditText)v.findViewById(id.user_detail_row_value);
mUserDetails.set(index, et.getText().toString().trim());
}
}
});
它还会更新错误的EditTexts。我在这里缺少什么?
编辑:还试过这个:
final ViewHolder testHolder = holder;
holder.mDetailEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
EditText et = (EditText)v.findViewById(id.user_detail_row_value);
mUserDetails.set(testHolder.ref, et.getText().toString().trim());
}
}
});
它纠正了我看到的滚动更改问题,但现在在编辑其中一个EditTexts后,它也改变了其他一些。
答案 0 :(得分:35)
问题与您没有从EditText小部件中删除以前添加的文本观察程序这一事实有关。相反,您会继续将新的观察者添加到列表中。一旦您尝试编辑窗口小部件内容,所有文本观察者将按顺序获得通知,从而导致更新错误的用户详细信息。
EditText / TextView没有提供删除以前添加的文本观察者的方法,而没有explicit reference。这意味着您必须重新编写代码以保持对文本观察者的引用,并为每个getView方法执行创建/添加/删除观察者,或者扩展TextWatcher,允许在触发后更改用户详细信息以进行更新。后者在下面实现。
@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());
}
}
}
希望这有帮助。
答案 1 :(得分:2)
检查您的索引值是否与您正在处理的行位置匹配。如果使用支架图案,则该值可能不会从0变为7-8,具体取决于您的屏幕尺寸。这样的事情发生在我身上,我想我通过实施getCount
方法解决了这个问题。这样,行50给出了位置50而不是7(例如)。
答案 2 :(得分:0)
我遇到了同样的问题,当我将滚动条移到列表的上/下时,editText的文本值已更改,那么我的解决方案是在EditText中添加一个setOnFocusChangeListener,并在其中添加一个addTextChangedListener,但关联相同editText的其他实例。
EditText etSumScans;
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
view = convertView;
if (view == null)
view = LayoutInflater.from(myContextItem).inflate(resourceLayoutItem, null);
shipmentLinesDTO = myListItem.get(position);
etSumScans = view.findViewById(R.id.etSumScans);
etSumScans.setText(shipmentLinesDTO.getAttribute1() );
etSumScans.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
EditText secondInstanceEditText= v.findViewById(R.id.etSumScans);
secondInstanceEditText.addTextChangedListener(new TextWatcher() {
@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) {
getItem(position).setAttribute1(s.toString());
}
});
}
}
});
}
以此解决了我的问题。 希望对您有帮助。