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() 中添加TextWatcherEditText。因此,想法是当您在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

ListView 与 EditText 键盘问题

从 List Adapter Android 中的按钮单击编辑 EditText

滚动时ListView位置问题