Jahury
Jahury

Reputation: 83

values of EditTexts in ListView are duplicated randomly

I have listview that has a an Edittext and Button in every row.When i insert the value in the Edittext in first row then i scroll down the list , I find some other EditText in the ListView filled with the same value. How can I prevent that. Please help me.

This my code

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;

    }
}

Upvotes: 1

Views: 1751

Answers (3)

Reaz Murshed
Reaz Murshed

Reputation: 24211

You can have a look at my answer here. Though the problem is not the same but yes this is a similar case you've got here.

So in your case you can solve the problem in many ways. I can suggest you one though. You might keep an external array which will contain all empty strings initially. The array size need to be equal to the size of the RecyclerView. Add a TextWatcher with your EditText inside getView(). Hence the idea is to store the text in the external array when you add some text in an EditText field. Place the text in the specific index of the array to keep track which item in the list is modified.

Now in your getView() method

if(externalArray[pos].equals("")) 
    txtQuantity.setText("");
else 
    txtQuantity.setText(externalArray[pos]);

And yes, declare the EditText outside the onClickListener where you initialized other views of the list item.

So from your updated code, I can suggest you some modification

// Declare an String array
private String[] externalArray = new String[objects.size()];

Now your TextChangedListener should look like this

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
  }
});

Now set the txtQuantity like this

//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));

Upvotes: 1

Shree Krishna
Shree Krishna

Reputation: 8562

It's all because your List items are being recycled and if convertView is not null then it's recycling the same by convertView.getTag();.

To prevent this you can just prevent recycling convertView codes by removing

  if (convertView == null) {

and matching else clause as well.

But after that you may get scroll lagging issue, So that what I can suggest is try to optimize your list items that means try to reduce the number of list items because It causes the high CPU consumption.

Upvotes: 0

Devanshu Dwivedi
Devanshu Dwivedi

Reputation: 693

This line is creating trouble

EditText   txtQuantity=(EditText)((View)v.getTag()).findViewById(R.id.txtQuantity);

You need to take EditText directly from viewholder. Just use:

viewHolder.txtQuantity.getText().toString()

And you need to initialize txtQuantity along with other views of viewholder.

Upvotes: 0

Related Questions