ListView 中 EditTexts 的值是随机重复的
Posted
技术标签:
【中文标题】ListView 中 EditTexts 的值是随机重复的【英文标题】:values of EditTexts in ListView are duplicated randomly 【发布时间】:2016-07-23 20:31:52 【问题描述】:我的列表视图在每一行都有一个 Edittext 和 Button。当我在第一行的 Edittext 中插入值然后我向下滚动列表时,我发现 ListView 中的其他一些 EditText 填充了相同的值。我怎样才能防止这种情况。请帮帮我。
这是我的代码
public class ItemsAdapter extends ArrayAdapter<Items>
Double Price;
Double Quantity;
String _Quantity;
private int resource;
private LayoutInflater inflater;
private Context context;
Items items;
List<Items> objects;
private ArrayList<String> externalArray = new ArrayList<String>();
public ItemsAdapter(Context ctx, int resourceId, List<Items> objects)
super( ctx, resourceId, objects );
resource = resourceId;
inflater = LayoutInflater.from( ctx );
context=ctx;
this.objects=objects;
for(int i =0; i< objects.size();i ++ )
externalArray.add(i,"");
@Override
public int getCount()
return objects.size();
@Override
public Items getItem(int position)
return objects.get(position);
@Override
public long getItemId(int position)
return 0;
@Override
public View getView (final int position, View convertView, ViewGroup parent )
final ItemViewHolder viewHolder;
items = getItem( position );
if (convertView == null)
convertView=( RelativeLayout ) inflater.inflate( resource,null);
viewHolder=new ItemViewHolder();
// LayoutInflater.from(context).inflate(R.layout.list_items, parent, false);
viewHolder.btnAddToCart=(Button)convertView.findViewById(R.id.btnAddToCart);
viewHolder.lblItemsName=(TextView) convertView.findViewById(R.id.lblItemName);
viewHolder.lblPrice = (TextView) convertView.findViewById(R.id.lblPrice);
viewHolder.btnPlus=(ImageButton)convertView.findViewById(R.id.btnPlus);
viewHolder.btnMinus=(ImageButton)convertView.findViewById(R.id.btnMinus);
viewHolder.txtQuantity =(EditText)convertView.findViewById(R.id.txtQuantity);
convertView.setTag(viewHolder);
else
viewHolder = (ItemViewHolder) convertView.getTag();
viewHolder.txtQuantity.addTextChangedListener(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)
externalArray.set(position,viewHolder.txtQuantity.getText().toString());
);
viewHolder.btnAddToCart.setTag(convertView);
viewHolder.btnPlus.setTag(convertView);
viewHolder.btnMinus.setTag(convertView);
viewHolder.lblItemsName.setText(items.getItemName());
String p=items.getPrice().toString();
viewHolder.lblPrice.setText(p+" $" );
if (externalArray.get(position) == "")
viewHolder.txtQuantity.setText("");
else
viewHolder.txtQuantity.setText(externalArray.get(position));
viewHolder.btnAddToCart.setOnClickListener(new View.OnClickListener()
public void onClick(View v)
_Quantity=viewHolder.txtQuantity.getText().toString();
Quantity = new Double(Double.parseDouble(_Quantity));
Double Total =Price*Quantity;
);
return convertView;
public class ItemViewHolder
public EditText txtQuantity ;
public Button btnAddToCart ;
public TextView lblItemsName;
public TextView lblPrice;
【问题讨论】:
LayoutInflater.from(context).inflate(R.layout.your_layout, parent, false);
CALL convertView = null;
then if if (convertView == null)
正确遵循 ViewHolder 模式
【参考方案1】:
你可以看看我的回答here。尽管问题不一样,但是是的,这是您在这里遇到的类似情况。
因此,在您的情况下,您可以通过多种方式解决问题。不过我可以给你推荐一个。您可能会保留一个外部数组,该数组最初将包含所有空字符串。数组大小需要等于RecyclerView
的大小。在getView()
中添加TextWatcher
和EditText
。因此,想法是当您在EditText
字段中添加一些文本时,将文本存储在外部数组中。将文本放在数组的特定索引中,以跟踪列表中的哪个项目被修改。
现在在您的 getView()
方法中
if(externalArray[pos].equals(""))
txtQuantity.setText("");
else
txtQuantity.setText(externalArray[pos]);
是的,在您初始化列表项的其他视图的onClickListener
之外声明EditText
。
所以根据您更新的代码,我可以建议您进行一些修改
// Declare an String array
private String[] externalArray = new String[objects.size()];
现在你的TextChangedListener
应该是这样的
viewHolder.txtQuantity.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
externalArray[position] = viewHolder.txtQuantity.getText().toString();
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
// Do nothing
@Override
public void afterTextChanged(Editable s)
// Do nothing
);
现在像这样设置txtQuantity
//if (externalArray.get(position).equals(""))
// viewHolder.txtQuantity.setText("");
//else
// viewHolder.txtQuantity.setText(externalArray.get(position));
// OR you can put a single line. I added the else part
// to make you understand the scenario actually.
viewHolder.txtQuantity.setText(externalArray.get(position));
【讨论】:
请查看更新后的代码。使用equals()
匹配字符串。【参考方案2】:
这条线正在制造麻烦
EditText txtQuantity=(EditText)((View)v.getTag()).findViewById(R.id.txtQuantity);
您需要直接从查看器中获取 EditText。 只需使用:
viewHolder.txtQuantity.getText().toString()
并且您需要初始化txtQuantity
以及其他viewholder 视图。
【讨论】:
即使我按照你说的做了,也解决不了问题。【参考方案3】:这完全是因为您的 List 项目正在被回收,如果 convertView
不是 null
那么它会被 convertView.getTag();
回收。
为了防止这种情况,您可以通过删除来防止回收convertView
代码
if (convertView == null)
还有匹配的 else 子句。
但是在那之后你可能会遇到滚动滞后问题,所以我可以建议尝试优化你的列表项,这意味着尝试减少列表项的数量,因为它会导致 CPU 消耗高。
【讨论】:
这给我带来了另一个问题,每次我向下滚动列表时,EditText 的值都会变为空。 哪个 EditText ?您是在说您在上面输入了一些文本的 editText 吗? 是的,我在谈论 txtQuantity 删除((View)v.getTag())
并使用 convertView.findViewById
。
ok 那么你的意思是说,你在顶部的edittext中输入了一些东西,然后你滚动到底部或底部,当你再次回滚到顶部时,你发现edittext在你已经输入的地方是空的。是怎么回事吗?以上是关于ListView 中 EditTexts 的值是随机重复的的主要内容,如果未能解决你的问题,请参考以下文章
ListView 从第 5 行开始重复 EditTexts 中的相同项目
Android - ListView 中的 EditTexts 绑定到自定义 ArrayAdapter - 跟踪更改
在每个子项中添加带有EditTexts的ListView - Android Studio