Reputation: 83
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
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
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
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