Reputation: 69
I have a big problem with ListView. I have 2 buttons, btPlus and btMinus (and 4 TextViews) in each listView's row. The two buttons increase (btPlus) and decrease (btMinus) the value of the label lblQty. I have created a custom ArrayAdapter setted in this way:
public class ProductsViewAdapter extends ArrayAdapter<HashMap<String, String>>{
private int resource;
private LayoutInflater inflater;
private char tag;
private Context context;
private ArrayList<HashMap<String, String>> prodotti;
private HashMap<String, String> prodotto;
RowHolder holder;
public ProductsViewAdapter(Context context, int resourceId,
ArrayList<HashMap<String, String>> objects, char t) {
super(context, resourceId, objects);
this.resource = resourceId;
this.context = context;
this.prodotti = objects;
this.tag = t;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
holder = null;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(resource, parent, false);
holder = new RowHolder();
holder.tvPid = (TextView) row.findViewById(R.id.pid);
holder.tvNome = (TextView) row.findViewById(R.id.name);
holder.tvDescr = (TextView) row.findViewById(R.id.description);
holder.tvPrezzo = (TextView) row.findViewById(R.id.price);
holder.btPlus = (Button) row.findViewById(R.id.btnPlus);
holder.btMinus = (Button) row.findViewById(R.id.btnMinus);
holder.tvQuantita = (TextView) row.findViewById(R.id.lblQty);
row.setTag(holder);
}
else {
holder = (RowHolder) row.getTag();
}
prodotto = prodotti.get(position);
if (tag == 'p'){
holder.tvPid.setText(prodotto.get("idProdotto"));
}
else {
holder.tvPid.setText(prodotto.get("idBibita"));
}
holder.tvNome.setText(prodotto.get("nome"));
holder.tvDescr.setText(prodotto.get("descrizione"));
holder.tvPrezzo.setText(prodotto.get("prezzo"));
holder.btPlus.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("Plus Button Clicked", "**********");
Toast.makeText(context, "Plus button Clicked",
Toast.LENGTH_LONG).show();
int val = Integer.parseInt(holder.tvQuantita.getText().toString())+1;
holder.tvQuantita.setText(String.valueOf(val));
}
});
holder.btMinus.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("Minus Button Clicked", "**********");
Toast.makeText(context, "Minus button Clicked",
Toast.LENGTH_LONG).show();
int val = Integer.parseInt(holder.tvQuantita.getText().toString());
if (val > 0 ){
val--;
holder.tvQuantita.setText(String.valueOf(val));
}
}
});
return row;
}
static class RowHolder {
TextView tvPid;
TextView tvNome;
TextView tvDescr;
TextView tvPrezzo;
TextView tvQuantita;
Button btPlus;
Button btMinus;
}
}
so I use it in my Activity:
ProductsViewAdapter adapter = new ProductsViewAdapter(
AllProducts_View.this, R.layout.list_item_from_cat, productsList, 'p'
);
/*AllProducts_View.this, productsList,
R.layout.list_item_from_cat, new String[] { TAG_PID,
TAG_NAME, TAG_DESCRIZIONE, TAG_PREZZO},
new int[] { R.id.pid, R.id.name, R.id.description, R.id.price});*/
// updating listview
lv.setItemsCanFocus(false);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
HashMap<String, String> p = (HashMap<String, String>) parent.getItemAtPosition(position);
Toast.makeText(
view.getContext(),
"Click sulla riga " + p.get("nome") + " " + p.get("prezzo"),
Toast.LENGTH_LONG
).show();
}
});
Here there is the xml code for the single row (list_item_from_cat.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- Product id (pid) - will be HIDDEN - used to pass to other activity -->
<TextView
android:id="@+id/pid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<!-- Name Label -->
<TextView
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:paddingTop="6dip"
android:textSize="24dp"
android:textStyle="normal" />
<TextView
android:id="@+id/description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:paddingTop="6dip"
android:textSize="20dp"
android:textStyle="italic" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/price"
android:layout_width="108dp"
android:layout_height="34dp"
android:layout_marginRight="53dp"
android:layout_weight="1.34"
android:text="TextView" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<Button
android:id="@+id/btnPlus"
style="?android:attr/buttonStyleSmall"
android:layout_width="35dp"
android:layout_height="wrap_content"
android:text="+"
android:focusable="false"
android:focusableInTouchMode="false"/>
<TextView
android:id="@+id/lblQty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textAppearance="?android:attr/textAppearanceSmall"
android:width="35dp" />
<Button
android:id="@+id/btnMinus"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"
android:width="35dp"
android:focusable="false"
android:focusableInTouchMode="false" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
My Problem is that when I click on the buttons in each row, they increase or decrease the value of another row. And this happens even when I slide listView with a variable result.
Can anyone help me?
Thanks a lot for the answers
Upvotes: 2
Views: 256
Reputation: 161
This is pretty old, I'm assuming you've found an answer, but just in case... It looks like what you're seeing is the result of the cell recycler in action. You're setting the value of the textview directly, meaning every nth row is being affected by your update. Let's say, for example, that your list view is showing rows 0,1,2 and 3. If I'm understanding what you're saying, you add to row 0, then when you start scrolling, row 4 has also changed. Likewise, if you scroll down to probably 7, it's changed as well, along with every 4th item thereafter.
You can get around this by setting your new quantity value in an object associated with your list then set the textfield from that object. Instead of:
int val = Integer.parseInt(holder.tvQuantita.getText().toString())+1;
holder.tvQuantita.setText(String.valueOf(val));
do:
int val = //get value from list object and increment by 1
object.setValue(val); //put the value back into the object
holder.tvQuantita.setText(String.valueOf(object.getValue());
From the looks of your code, you'll probably need to do a bit of refactoring to get there, but it shouldn't be too bad. You have a HashMap. You could refactor that to
HashMap<String, CompoundObject>
where compound object looks like:
public class Container {
private String currentString;
private int quantity;
//don't forget getters and setters, and maybe equals/hashCode
}
You'd then have a place to set the new values without changing all of quantities. Finally, you'd need to set the value from this object on each getView where you set name, description and price.
holder.tvNome.setText(prodotto.get("nome"));
holder.tvDescr.setText(prodotto.get("descrizione"));
holder.tvPrezzo.setText(prodotto.get("prezzo"));
holder.tvQuantita.setText(/*set quantity here*/);
holder.btPlus.setOnClickListener(new OnClickListener() {
That should make your ListViews not repeat.
Upvotes: 1