I have created a list view as shown in this image.Link:
Image
Problem: I want that if the user clicks on the button +
or -
the textview which is currently showing 0
is incremented or decremented accordingly. But if I click first item's button the textview is updated in some other row. I don't know how to implement this.
Here's code:
public class HomePage extends Fragment {
String[] listitems;
int[] images = { R.drawable.cadburysilk, R.drawable.cadburys_dairymilk,
R.drawable.perk, R.drawable.kitkat,
R.drawable.nestlemunchchocolate, R.drawable.cadbury_bournville_bar,
R.drawable.snickers };
ListView list;
DBAdapter dbadapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View rootview = inflater.inflate(R.layout.activity_home_page,
container, false);
View view = View.inflate(getActivity(), R.layout.headerview, null);
Resources res = getResources();
listitems = res.getStringArray(R.array.items);
list = (ListView) rootview.findViewById(R.id.itemslist);
list.addHeaderView(view);
AdapterClass adapterClass = new AdapterClass(this.getActivity(),
listitems, images);
list.setAdapter(adapterClass);
return rootview;
}
}
class AdapterClass extends ArrayAdapter<String> {
Context context;
int[] images;
String[] names;
Button add, sub;
TextView number;
Integer count=0;
static class ViewHolder {
public TextView textView;
public ImageView imageView;
}
public AdapterClass(Context c, String[] items, int imgs[]) {
// TODO Auto-generated constructor stub
super(c, R.layout.rowlayout, R.id.quantity, items);
this.context = c;
this.images = imgs;
this.names = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
// reuse views
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.rowlayout, parent, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.imageView = (ImageView) row.findViewById(R.id.img);
viewHolder.textView = (TextView) row.findViewById(R.id.textView1);
add = (Button) row.findViewById(R.id.button1);
add.setTag(position);
sub = (Button) row.findViewById(R.id.button2);
sub.setTag(position);
number = (TextView)row.findViewById(R.id.quantity);
row.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) row.getTag();
holder.imageView.setImageResource(images[position]);
holder.textView.setText(names[position]);
add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
count=count+1;
number.setText(count.toString());
}
});
sub.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
count=count-1;
number.setText(count.toString());
}
});
return row;
}
}
Please help. Also i need help in how to show the items whose textview contains positive number in next activity or fragment.
Follow initial query with answer by user370305.
Please help. Also i need help in how to show the items whose textview contains positive number in next activity or fragment.
Create a data structure, I am taking a HashMap , where key is String.valueOf(position) and Value is count int.
You know the keys since it will be from position "0" to listitem.length. Using the key you can get the count values and check for positive ones.
Why Hashmap: because everytime you change count the new value will be overriden. (Only one unique key is maintained in hashmap).
(position = 0, count = 0) --> - clicked on 0th row--> (position 0 , count = -1) will be overriden on key = 0 cell.
Complete code (with number increment fix and having set of positive value in DataStructure):
public class HomePage extends Fragment {
String[] listitems;
int[] images = { R.drawable.cadburysilk, R.drawable.cadburys_dairymilk,
R.drawable.perk, R.drawable.kitkat,
R.drawable.nestlemunchchocolate, R.drawable.cadbury_bournville_bar,
R.drawable.snickers };
ListView list;
DBAdapter dbadapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View rootview = inflater.inflate(R.layout.activity_home_page,
container, false);
View view = View.inflate(getActivity(), R.layout.headerview, null);
Resources res = getResources();
listitems = res.getStringArray(R.array.items);
list = (ListView) rootview.findViewById(R.id.itemslist);
list.addHeaderView(view);
AdapterClass adapterClass = new AdapterClass(this.getActivity(),
listitems, images);
list.setAdapter(adapterClass);
return rootview;
//You can use adapterClass.getPositiveNumber(); to retrieve all positive rows and the values!
//Unique key will be String : 1,2,3....listitems.length.
}
}
class AdapterClass extends ArrayAdapter<String> {
Context context;
int[] images;
String[] names;
Button add, sub;
ViewHolder holder; // Since will be accessed inside onclick
HashMap<String,Integers> positiveNumbers = new HashMap<String,Integers>;
Integer count=0;
static class ViewHolder {
public TextView textView;
public ImageView imageView;
public TextView number;
public String uniqueKey;
}
public AdapterClass(Context c, String[] items, int imgs[]) {
// TODO Auto-generated constructor stub
super(c, R.layout.rowlayout, R.id.quantity, items);
this.context = c;
this.images = imgs;
this.names = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
// reuse views
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.rowlayout, parent, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.imageView = (ImageView) row.findViewById(R.id.img);
viewHolder.textView = (TextView) row.findViewById(R.id.textView1);
viewHolder.number = (TextView)row.findViewById(R.id.quantity);
viewHolder.uniqueKey = String.valueOf(position);
add = (Button) row.findViewById(R.id.button1);
add.setTag(position);
sub = (Button) row.findViewById(R.id.button2);
sub.setTag(position);
row.setTag(viewHolder);
}
holder = (ViewHolder) row.getTag(); //keeping one global memory
holder.imageView.setImageResource(images[position]);
holder.textView.setText(names[position]);
add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
count=count+1;
holder.number.setText(count.toString());
positiveNumbers.put(holder.uniqueKey,count); //Key -> String.valueOf(position) and Value -> int count
}
});
sub.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
count=count-1;
holder.number.setText(count.toString());
positiveNumbers.put(holder.uniqueKey,count); //Key -> String.valueOf(position) and Value -> int count
}
});
return row;
}
public Map<String,Integer> getPositiveNumbers()
{
return positiveNumbers;
}
}
p.s. I have typed in editor, there might be some compile time error. Also you can store objects of each row against the key so that when you get the positive count, you can get any other reference like the image, which I am guessing you would need to show later!
I wrote a short demo for my answer which you can see here.
Example:
When you're ready, you can then use your data source (not your adapter, not your listview) to find the products that have a quantity > 0.
public List<Product> getBasket() {
List<Product> basket = new ArrayList<>();
for (Product product : productList) {
if (product.quantity > 0) {
basket.add(product);
}
}
return basket;
}
Your adapter has one job: to create/bind Views to data, it does not need to do more.
initial answer without demo:
If you update the item views directly, you won't be able to fetch all the items with a positive number later because these updated values are only stored in the views, and not in some data structure you can iterate over.
This is why you shouldn't update item views directly, but instead use a callback when the plus/minus button is clicked, modify the underlying dataset, and call adapter.notifyDatasetChanged()
to update the ListView/RecyclerView again.
Pass a callback to your adapter:
public interface ItemInteraction {
void onPlusButtonClick(long id);
void onMinusButtonClick(long id);
}
which you can use by setting it as the callback for click listeners on the relevant views. The ID can be anything so long as it can uniquely identify the data item represented by a list view row.
final long id = item.getId();
plusButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick() {
callback.onPlusButtonClick(id);
}
});
An example is given in this similar question where OP wanted to show or hide a star (indicating favourite) for a list of songs here.
Another explanation of how adapter-like views are designed to be used.
I know its very late but i thought this may help other who have similar problem
Problem: I want that if the user clicks on the button + or - the textview which is currently showing 0 is incremented or decremented accordingly. But if I click first item's button the textview is updated in some other row. I don't know how to implement this.
look at your code
ViewHolder holder = (ViewHolder) row.getTag();
holder.imageView.setImageResource(images[position]);
holder.textView.setText(names[position]);
add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
count=count+1;
number.setText(count.toString());
}
});
sub.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
count=count-1;
number.setText(count.toString());
}
});
return row;
in your ViewHolder you have set values for holder.imageview and holder.textview which is for name i think, but you forgot to set value for holder.number and you are only changing its value in onClick method.
so when the adapter creates its view it do not find any specific value that is why it uses the previously used view to inflate the data.
Solution:- just use a separate list to store the number with unique key (use adapter position as key) and check if the list has that key that means you previously changed the value so get the value from list and set it on textview if the key is not present that means you never changed the value so set textview with 0