Updating more than one rows in listview - android

I have a listview which consists of name, text and imageview. If an user named "John" clicks the imageview in the row with user named "Bob", all the rows with name "Bob" inclusive of the currently clicked row should have their imageview changed into another image. I am trying to do this in the following code:
private class MyListAdapter extends ArrayAdapter<CommentInfo> {
public MyListAdapter()
{
super(getActivity(), R.layout.listview_xml, myComments);
}
#Override
public View getView(final int position, final View convertView, final ViewGroup parent)
{
itemView = convertView;
Bundle bundle = new Bundle();
if(itemView == null)
{
itemView = layoutInflater.inflate(R.layout.listview_xml, parent, false);
}
final CommentInfo currentComment = myComments.get(position);
List<View> viewList;
if(!ht.containsKey(currentComment.userName)){
viewList = new ArrayList<View>();
viewList.add(itemView);
Log.d("username", currentComment.userName);
Log.d("position", Integer.toString(position));
ht.put(currentComment.userName, viewList);
}
else{
((List<View>)ht.get(currentComment.userName)).add(itemView);
Log.d("username", currentComment.userName);
Log.d("position", Integer.toString(position));
}
final ImageView follows = (ImageView) itemView.findViewById(R.id.followUserBtn);
follows.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(follows_flag == 0){
follows_flag = 1;
followed_person = currentComment.userName;
follows.setImageResource(R.drawable.followusersuccesssbtn);
List<View> viewList1 = (List<View>) ht.get(currentComment.userName);
for(View view : viewList1){
ImageView follows_other = (ImageView)view.findViewById(R.id.followUserBtn);
follows_other.setImageResource(R.drawable.followusersuccesssbtn);
}
new StoreFollowed().execute();
}
else{
follows_flag = 0;
followed_person = currentComment.userName;
follows.setImageResource(R.drawable.followusericon);
List<View> viewList1 = (List<View>) ht.get(currentComment.userName);
for(View view : viewList1){
ImageView follows_other = (ImageView)view.findViewById(R.id.followUserBtn);
follows_other.setImageResource(R.drawable.followusericon);
}
new DeleteFollowed().execute();
}
}
});
return itemView;
}
}
In the above code, I store in hashtable, for each name, list of views. My issue is when John clicks on the imageview in the row with name Bob, all the rows with imageview gets its image changed rather than the rows with only Bob's name. What is the wrong I am doing here? How to resolve the issue?

First don't keep an association between your data and your view. Android ListView reuses view which means that you will have some views associated each with multiple names. I'm pretty sure your problem comes form this.
You should alway try to only modify your Model Objet and let the list view update the UI.
In you case You could have All your CommentInfo objet referencing a User with different CommentInfo from same user refrencing the User object. You can then store you image in this User and when you wan't in on click update the user's image and call notifyDataSetChanged(); so that your list update it's UI.
PS : you might wan't to take a look at ViewHolder. It has nothing to do with you problem but it's a good practice and would increase the smoothness of your list's scrolling.

Related

Set visibility for an image within a ListView row

Overview:
I have a ListView with a custom adapter/layout, every time a user adds a new row (which contains a number), I check if that number is the smallest in the list. If so, an image within that row must be set as visible while setting all other row's images as invisible.
Problem:
My ListView does not set any row's image as visible, even though I have the index of the smallest element.
How I'm doing it:
//In MainActivity
private void addProduct(float price) { //User adds product
priceList.add(price); //Add to Float list
adapter.notifyDataSetChanged();
updateView(findMinIndex(priceList)); //Find smallest val indx
}
private void updateView(int index){
View v = listView.getChildAt(index -
listView.getFirstVisiblePosition());
if(v == null)
return;
ImageView checkMark = (ImageView) v.findViewById(R.id.check_mark);
checkMark.setVisibility(View.VISIBLE); //Initially set Invisible
}
Edit, CustomAdapter:
public CustomList(Activity context,
ArrayList<Float> priceList) {
super(context, R.layout.list_single, priceList);
this.context = context;
priceList = priceList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.list_single, null, true);
TextView price = (TextView) rowView.findViewById(R.id.new_price);
ImageView cheapest = (ImageView) rowView.findViewById(R.id.check_mark);
price.setText(priceList.get(position) + "");
return rowView;
}
Thank you
It is your priceList binded with the adapter?
First of all i would put a breakpoint to see if you are getting the right view in the updateView method.
try this way;
Create a Pojo class with imageview and it's state(Visibility) initially set all to invisible
Add your items to the ArrayList of Pojo Class type.
when user enters a new row based on your requirement set visibility state to true or false(visible or invisible) and call notifyDataSetChanged() to the adapter.
Doing this way you can have a easy track of the items.
I got it working :).
Problem is that adapter.notifyDataSetChanged(); is async, so while it's doing that, updateView(findMinIndex(priceList)); runs but doesn't find the new row as it should. Therefore, I add a runnable to the ListView object as so:
adapter.notifyDataSetChanged();
listView.post( new Runnable() {
#Override
public void run() {
updateView(findMinIdx(priceList));
}
});
Now it works perfectly!

CustomListAdapter list items imitate each other

I have read and tried several of the solutions to similar problems here on stack overflow, but none of them solved my problem. Here is the thing.
I have a listview which uses CustomListAdapter, each list item has a progress bar, a download button, title text and so on. When the download button is clicked a download operation is performed, and based on the result of the download(whether success or failure) the list item concerned is update(UI changes, such as if complete hide download button, update progress of the progress bar during download)
The listview displays four items at every given time
The problem is that whenever a UI change is made to an item say item 1(with index 0) the item 5 will also have the same changes, likewise if a change is made to item 3, the item 7 takes up those changes. In summary the item N+4 always imitates item N.
A look at my getView() will tell that I have checked all the known boxes.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder holder;
if (convertView == null) {
view = inflater.inflate(R.layout.item_mylibrarylist, null);
holder = new ViewHolder();
holder.name = (TextView)view.findViewById(R.id.name);
holder.name.setTypeface(MainActivity.font_bahamas);
holder.author = (TextView)view.findViewById(R.id.author);
holder.author.setTypeface(MainActivity.font_bahamas);
holder.worktype = (TextView)view.findViewById(R.id.worktype);
holder.worktype.setTypeface(MainActivity.font_bahamas);
holder.coverPic = (TextView)view.findViewById(R.id.coverPic);
holder.downloadBt = (TextView)view.findViewById(R.id.downloadBt);
holder.progressBar = (ProgressBar)view.findViewById(R.id.progressBar2);
holder.menuBt = (ImageView)view.findViewById(R.id.menuBt);
holder.position = position;
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
if(holder.position == position) {
setValuesForListItemViews(holder, position, view);
}
return view;
}
The method to set each of the list items..
private void setValuesForListItemViews(ViewHolder holder, int position, View view) {
if (!data.isEmpty()) {
// set the list item elements here
final CreativeWork creativeWork = data.get(position);
holder.name.setText(creativeWork.getName().toLowerCase());
holder.author.setText("by " + creativeWork.getOriginal_authors().toLowerCase());
holder.worktype.setText(creativeWork.getWork_type().toLowerCase());
Drawable draw = res.getDrawable(R.drawable.custom_progressbar2);
holder.progressBar.setProgressDrawable(draw);
holder.progressBar.setMax(100);
holder.progressBar.setVisibility(View.INVISIBLE);
holder.menuBt.setOnClickListener(new OnItemClickedListener(view, position, 1, creativeWork, holder.progressBar, holder.downloadBt));
holder.menuBt.setOnCreateContextMenuListener(new MContextMenuListener(creativeWork, holder.progressBar, holder.downloadBt, false));
//load image url
ImageLoader2 imgLoader12 = new ImageLoader2(activity);
imgLoader12.DisplayImage(creativeWork.getName(), R.drawable.downloads, holder.downloadBt);
ImageLoader imgLoader = new ImageLoader(activity);
imgLoader.DisplayImage(SLService.END_POINT + creativeWork.getImage_url(), R.drawable.soul_lounge, holder.coverPic);
//check if file already exist and switch off download button
DBHelper helper = new DBHelper(activity);
CreativeWork cw = helper.getCreativeWork(creativeWork);
if (cw != null) {
File file = new File(cw.getFilePath());
if (file.exists()) {
holder.menuBt.setOnCreateContextMenuListener(new MContextMenuListener(creativeWork, holder.progressBar, holder.downloadBt, true));
//check if the file download was complete
if (cw != null) {
if (cw.getFileSize() > file.length()) {
holder.progressBar.setProgressDrawable(activity.getResources().getDrawable(R.drawable.custom_progressbar3));
ImageLoader2 imgLoader2 = new ImageLoader2(activity);
imgLoader2.DisplayImage(cw.getName(), R.drawable.restart, holder.downloadBt);
holder.progressBar.setProgress((int) ((file.length() * 100) / cw.getFileSize()));
holder.progressBar.setVisibility(View.VISIBLE);
} else {
holder.downloadBt.setVisibility(View.INVISIBLE);
}
}
}
}
holder.downloadBt.setOnClickListener(new OnItemClickedListener(view, position, creativeWork, holder.progressBar, holder.downloadBt, 0));
}
}
Easiest way to solve this is adding some extra fields to your model class whose list you are passing to your adapter.
like
boolean showDownloadButton; //default is true
int progress;// default is 0
So when user clicks on download button (or any other desired event) change the boolean value of showDownloadButton to false for model object at the given position and call adapter.notifyDatasetChanged() and manage the button visibility accordingly in your adapter.
and do make sure to add both visible and gone condition for the view aswell
if(modelList.get(position).getShowDownloadButton())
{
btnDownload.setVisibility(View.VISIBLE)
}
else
{
btnDownload.setVisibility(View.GONE)
}
Nitesh's answer is right apart from that there is another way to do if you don't want to create Model class
Use setId and getId with position to identify unique row and assign that id to progressbar for the solution

How to set gridview within listview item and click on each grid item with uniq posion and click evant

I want to foll list view with image grid date wise.First get Date list of image and then after get image path list of particular date wise image list.and finally I fill list and grid of particular date wise image(No of images and date not fixed),have a look screen shot.
Date wise images display in Grid View
And now my problem is, When I set click listener on image and add check mark image on click then image add in two position, Why I don't know.and second is when I scroll down list view then check mark visible gone.
I want to select multiple image and add check mark image and perform operation like "Delete image" and "Share image"
Like this
I call grid adapter of each list item , look my code tell me what's wrong
Custom List View adapter : get View method
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
ViewHolder viewHolder = new ViewHolder();
DateSortedImageItem item = getItem(position);
if (row == null) {
row = mInflator.inflate(R.layout.row_date_sorted_image_list, parent, false);
viewHolder.tv_date = (TextView) row.findViewById(R.id.tv_row_date);
viewHolder.rowGridView = (GridView) row.findViewById(R.id.gv_row_item);
viewHolder.tv_date.setText(item.getDate());
row.setTag(viewHolder);
gridAdapter = new GridAdapter(context, R.layout.row_sorted_image_gridview_item,
item.getDateSortedImageList(), position);
viewHolder.rowGridView.setAdapter(gridAdapter);
} else {
row.getTag();
}
return row;
}
private class ViewHolder {
TextView tv_date;
GridView rowGridView;
}
and my grid adapter code is :
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = ((Activity) getContext()).getLayoutInflater();
convertView = mInflater.inflate(R.layout.row_sorted_image_gridview_item, parent, false);
}
view = convertView;
final SquareImageView imageView = (SquareImageView) view.findViewById(R.id.iv_test_row_grid_img);
final ImageView iv_checked = (ImageView) view.findViewById(R.id.iv_checked);
final ImageView iv_unChecked = (ImageView) view.findViewById(R.id.iv_unchecked);
view.setTag(arrList.get(position).toString());
File f = new File(arrList.get(position).toString());
System.out.println("arrList size >>" + arrList.size());
Picasso.with(context).load(Uri.fromFile(f)).resize(100, 100).centerCrop().placeholder(R.drawable.ic_launcher)
.error(R.drawable.ic_close_black).into(imageView);
I just set Grid View image. And now i set imageview click ivent and add check mark then add check mark event two places and scroll down then visible gone also.
What's wrong hear and how to set click event of image view unique.
Finally I want to design Look like Google "Photos" app.
Suggest me any example or library:
First you should create a POJO as below
public class AlbumItem {
private String headerStr;
private List<ChildItem> children;
//getter - setter....
public class ChildItem {
private String childName;
private boolean isSelected;
//getter - setter.....
}
}
Now use this POJO inside your main adapter.
and in the second adapter handle the selection logic means if isSelected is true then show iv_checked otherwise show iv_unchecked.
Please let me know if you need further explanation.
Hope it will help you.

android - ViewHolder single onClick affects multiple list items

I am using a Custom List Adapter with ViewHolder pattern to inflate views into my List that shows an image (width = match_parent), some text on the left (below the image) and a button on the right(also below the image).
Here is the code for the adapter class -
public class DishItemListAdapter extends ArrayAdapter<DishItem> {
//declare fonts - BOLD and LIGHT
final Typeface tf_light = Typeface.createFromAsset(getContext().getAssets(),
"fonts/Roboto-Thin.ttf");
final Typeface tf_bold = Typeface.createFromAsset(getContext().getAssets(),
"fonts/Roboto-Regular.ttf");
//get item count
CartItemCount cartItemCount;
//count for dish at particular position
ArrayList<Integer> dishCountList = new ArrayList<>();
//for matching key string in SharedPrefs
String existingKeyString;
Typeface font_light, font_bold;
/* List of DishItem Objects shown on the Dashboard */
private List<DishItem> DishItemList = new ArrayList<DishItem>();
public DishItemListAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.font_bold = tf_bold;
this.font_light = tf_light;
}
/* Add a New DishItem Item (object) to the list of DishItems on the Dashboard i.e. DishItemList */
#Override
public void add(DishItem object) {
DishItemList.add(object);
super.add(object);
}
#Override
public int getCount() {
return this.DishItemList.size();
}
#Override
public DishItem getItem(int index) {
return this.DishItemList.get(index);
}
#Override
public View getView(final int position, final View convertView, ViewGroup parent) {
Log.e("getView() at " + position, "");
View row = convertView;
final DishItemViewHolder viewHolder;
// A ViewHolder keeps references to children views to
// avoid unnecessary (and expensive) calls to findViewById() on each row.
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_dish, parent, false);
//instantiate DishItem View Holder
viewHolder = new DishItemViewHolder();
//get BUTTON for Adding Dish to Cart
viewHolder.addToCart = (Button) row.findViewById(R.id.add_to_cart_button);
//BUTTONS for + and - (adding and removing items from cart)
viewHolder.addItemButton = (Button) row.findViewById(R.id.increase_item_count);
viewHolder.removeItemButton = (Button) row.findViewById(R.id.decrease_item_count);
//DISH NAME, CHEF NAME, DISH PRICE and DISH IMAGE
viewHolder.dishName = (TextView) row.findViewById(R.id.dish_name_textview);
viewHolder.chefName = (TextView) row.findViewById(R.id.chef_name_textview);
viewHolder.dishPrice = (TextView) row.findViewById(R.id.dish_price_textview);
viewHolder.dishImage = (ImageView) row.findViewById(R.id.dish_imageview);
//image absolute path
viewHolder.imageStorePath = new String();
//image for depicting whether image is VEG or NON VEG
viewHolder.veg_nonveg_indicator = (ImageView) row.findViewById(R.id.veg_nonveg_indicator);
//viewSwitcher for switching between BUTTON and - + button
viewHolder.viewSwitcher = (ViewSwitcher) row.findViewById(R.id.viewswitcher);
//indicator for item added to Cart
viewHolder.addedToCartIndicator = (TextView) row.findViewById(R.id.added_to_cart_text_indicator);
viewHolder.addedToCartIndicator.setVisibility(View.INVISIBLE);
//counter for number of items selected for a particular dish
viewHolder.dishQuantity = (TextView) row.findViewById(R.id.dish_quantity);
//set tag for the ViewHolder
row.setTag(viewHolder);
} else {
/* Get the ViewHolder back to get fast access to the DishItem UI widgets (views) */
viewHolder = (DishItemViewHolder) row.getTag();
}
//create object of Item Count Class
cartItemCount = new CartItemCount();
/* fetch DishItem View at current position (="position") */
final DishItem dishItem = getItem(position);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("clicked"+position,"");
viewHolder.dishName.setText("CLICKED");
}
});
return row;
}
static class DishItemViewHolder {
TextView dishName;
TextView chefName;
TextView dishPrice;
TextView dishQuantity;
String imageStorePath;
boolean isDishItemSelected;
Button addToCart, addItemButton, removeItemButton;
ImageView veg_nonveg_indicator;
ImageView dishImage;
ViewSwitcher viewSwitcher;
TextView addedToCartIndicator;
}
}
PROBLEM
Suppose I add 6 DishItem beans (model) to the list. Then, when I perform onClick on the 1st item in the list, the 1st item's text changes to CLICKED as it should. Also, in the Log, in says clicked:0 (as 1st list item's index is 0).
But the text for 4th list item also changes to CLICKED, which it shouldn't.
Now I read this post explaining the recycling mechanism of ListView.
However, I DO NOT want it to work that way since I want to update only those items I click.
What am I doing wrong here?
Is there any workaround this recycling mechanism to update only the particular item that I click?
UPDATE
Problem solved. I followed BlackBelt's approach and have thus accepted his answer, but I'd like to thank all of you for your inputs !! :)
Here is the updated getView() method.
 /**
*
* #param position The position of the item within the adapter's data set of the item whose view we want.
* #param convertView The old view to reuse, if possible.
* Note: You should check that this view is non-null and of an appropriate type before using.
* If it is not possible to convert this view to display the correct data, this method
* can create a new view. Heterogeneous lists can specify their number of view types,
* so that this View is always of the right type (see getViewTypeCount() and getItemViewType(int)).
* #param parent The parent that this view will eventually be attached to
* #return A View corresponding to the data at the specified position.
*/
    #Override
    public View getView(final int position, final View convertView, ViewGroup parent) {
        View row = convertView;
        final DishItemViewHolder viewHolder;
        // A ViewHolder keeps references to children views to
        // avoid unnecessary (and expensive) calls to findViewById() on each row.
        if (row == null) {
            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.list_item_dish, parent, false);
            //instantiate DishItem View Holder
            viewHolder = new DishItemViewHolder();
            //get BUTTON for Adding Dish to Cart
            //viewHolder.addToCart = (Button) row.findViewById(R.id.add_to_cart_button);
            viewHolder.addItemButton = (Button) row.findViewById(R.id.add_to_cart_secondary_button);
            viewHolder.removeItemButton = (Button) row.findViewById(R.id.remove_from_cart_button);
            //DISH NAME, CHEF NAME, DISH PRICE and DISH IMAGE
            viewHolder.dishName = (TextView) row.findViewById(R.id.dish_name_textview);
            viewHolder.chefName = (TextView) row.findViewById(R.id.chef_name_textview);
            viewHolder.dishPrice = (TextView) row.findViewById(R.id.dish_price_textview);
            viewHolder.dishImage = (ImageView) row.findViewById(R.id.dish_imageview);
            //image absolute path
            viewHolder.imageStorePath = new String();
            //image for depicting whether image is VEG or NON VEG
            viewHolder.veg_nonveg_indicator = (ImageView) row.findViewById(R.id.veg_nonveg_indicator);
            //indicator for item added to Cart
            viewHolder.addedToCartIndicator = (TextView) row.findViewById(R.id.added_to_cart_text_indicator);
            viewHolder.addedToCartIndicator.setVisibility(View.INVISIBLE);
            //set tag for the ViewHolder
            row.setTag(viewHolder);
        } else {
            /* Get the ViewHolder back to get fast access to the DishItem UI widgets (views) */
            viewHolder = (DishItemViewHolder) row.getTag();
        }
        //get object for CART ITEM COUNT class
        final CartItemCount cartItemCount = new CartItemCount();
        //get current dish item (MODEL from Bean class)
        final DishItem dishItem = getItem(position);
        //disable any highlighting unless dish is selected (verified from SharedPreferences)
        viewHolder.dishImage.setColorFilter(null);
        //hide ITEM COUNT indicator over the image unless dish is selected (again, verified from SharedPreferences)
        viewHolder.addedToCartIndicator.setVisibility(View.INVISIBLE);
        //show the + and - buttons on the right and left (respectively) side on the Dish ImageView
        viewHolder.addItemButton.setVisibility(View.VISIBLE);
        viewHolder.removeItemButton.setVisibility(View.VISIBLE);
        //get data from Preferences (to see which dish is selected)
        SharedPreferences pref = getContext().getSharedPreferences("DishDetails", Context.MODE_PRIVATE);
        Map<String, ?> allEntries = pref.getAll();
        for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
            Log.d("KEY = " + entry.getKey(), " VALUE = " + entry.getValue().toString());
        }
        //get Count for each dish in the list and set Quantity in the Model (DishItem.java)
        if (pref != null) {
            int currentDishCount = pref.getInt("dishCount" + position, 0);
            Log.e("Current DishCount", String.valueOf(currentDishCount));
            if (currentDishCount > 0) {
                getItem(position).setisDishItemSelected(true);
                dishItem.setDishQuantity(currentDishCount);
                Log.d("dish item" + position," selected");
            }
        }
        //update Views for selected DishItems
        if (dishItem.isDishItemSelected()) {
            viewHolder.dishImage.setColorFilter(Color.parseColor("#80E0E0E0"));
            viewHolder.addedToCartIndicator.setVisibility(View.VISIBLE);
            viewHolder.addedToCartIndicator.setText(dishItem.getDishQuantity() + " items in cart");
        }
        viewHolder.addItemButton.setOnClickListener(new View.OnClickListener() {
            #Override
            public void onClick(View v) {
                dishItem.setisDishItemSelected(true);
                dishItem.setDishQuantity(dishItem.getDishQuantity() + 1);
                //save data to preferences
                SharedPreferences pref = getContext().getSharedPreferences("DishDetails", Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = pref.edit();
                editor.putInt("dishCount" + position, dishItem.getDishQuantity());
                editor.commit();
                //increment Total Number of Items in Cart
                int itemCount = cartItemCount.getitemCount();
                cartItemCount.setitemCount(itemCount + 1);
                Log.d("itemCount =", String.valueOf(itemCount));
                //broadcast the value of itemCount to MainMenuActivity
                Intent intent = new Intent("NEW_CART_ITEM");
                intent.putExtra("value", cartItemCount.getitemCount());
                getContext().sendBroadcast(intent);
                Log.d("broadcast", "sent");
                //notify adapter of change in underlying data (i.e. update View to show Changes in Model)
                notifyDataSetChanged();
            }
        });
        viewHolder.removeItemButton.setOnClickListener(new View.OnClickListener() {
            #Override
            public void onClick(View v) {
                Log.d("Old Dish Qty. ", String.valueOf(dishItem.getDishQuantity()));
                //if dishCount has reached ZERO, set Dish as NOT SELECTED for buying
                if (dishItem.getDishQuantity() == 0) {
                    dishItem.setisDishItemSelected(false);
                } else {
                    dishItem.setisDishItemSelected(true);
                    dishItem.setDishQuantity(dishItem.getDishQuantity() - 1);
                    Log.d("New Dish Qty.", String.valueOf(dishItem.getDishQuantity()));
                    //decrement TOTAL number of items in Cart
                    int itemCount = cartItemCount.getitemCount();
                    cartItemCount.setitemCount(itemCount - 1);
                    Log.d("itemCount =", String.valueOf(itemCount));
                    //broadcast the value of itemCount to MainMenuActivity
                    Intent intent = new Intent("NEW_CART_ITEM");
                    intent.putExtra("value", cartItemCount.getitemCount());
                    getContext().sendBroadcast(intent);
                    Log.d("broadcast", "sent");
                    //recheck -> if dish Count has reached ZERO, set Dish as NOT SELECTED for buying
                    if (dishItem.getDishQuantity() == 0) {
                        dishItem.setisDishItemSelected(false);
                    }
                }
                //save Current Quantity of Dish Selected to SharedPreferences
                SharedPreferences pref = getContext().getSharedPreferences("DishDetails", Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = pref.edit();
                editor.putInt("dishCount" + position, dishItem.getDishQuantity());
                editor.commit();
                //notify adapter of change in underlying data (i.e. update View to show Changes in Model)
                notifyDataSetChanged();
            }
        });
        return row;
    }
The idea was simple (I didn't know it before) -
In the onClick Listener for the buttons, change the Model i.e. Data i.e. DishItem using the setters and getters defined in the bean class.
call
notifyDataSetChanged()
to tell the adapter about changes in data so that Views can be adjusted accordingly.
In the getView() method, set views bases on those data values.
Is there any workaround this recycling mechanism to update only the
particular item that I click?
No workaround here. You have to change the dataset (at position - the item you clicked), and ask the Adapter to redraw the ListView's children. I would strongly suggest you to use the OnItemClickListener too.
To change something, you must know the position of your item:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Code here
}
});
this will give you the correct position you've touch it. Other way, inside your getView (in the Adapter):
DishItemList = dishCountList.get(position);
That way you'll have the position of your item. To touch only the one you want:
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// here you can DishItemList.get("and get the key you need");
}
});
You should reset the view's state to the default one in the getView and apply the item's data after this. It works like this:
Get the row's view (either the convertView or inflate a new one)
Create and attach a view holder
Get the current item's data and state
Apply ALL the state params and data (so write "Clicked" if the current item is clicked or clear the TextView's text otherwise - do not assume that it contains the correct text already)
You'd need to store the item's state somewhere - currently you use the TextView's text to do this and it breaks due to the recycling behaviour. The correct way is to add a field to the DishItem or just create a new class to contain the state of each item (selected, focused and so on - all the states you'd like to support). In the onClickListener change the state's value and then change the views' contents or just call notifyDataSetChanged on the adapter.

How to change list item data when clicked on a sub view

holder.voteUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final int position = myList.getPositionForView((View) v
.getParent());
final ListItem li = values.get(position);
li.voteUp_value = true;
//In getView(), I set different image to holder.voteUp ImageView depending on this value.
//Hence I call notifyDataSetChanged(); which takes care of it.
notifyDataSetChanged();
}
});
But the problem is, Since the whole list is notified, it flickers every time I vote.
I cannot changed the Image of the holder.voteUp directly, because there is a holder.voteDown which has to be changed too, depending on the li.voteUp_value. So, I went with notifyDataSetChanged(); which takes care of all this.
Is there a way I can get the Views from parent View and set the Images, instead of notifyDataSetChanged();?
like:
ViewParent vp = v.getParent();
ImageView im = vp.findViewById(R.id.voteUp);
im.setImageResource.....
But there is nothing like findViewById for ViewParent
You should be able to use the view passed to you from the onClick() listener. Just changing the image should be enough to make it redraw, but if not you can still tell it to manually.
#Override
public void onClick(View v) {
final int position = myList.getPositionForView((View) v
.getParent());
final ListItem li = values.get(position);
li.voteUp_value = true;
ImageView im = vp.findViewById(R.id.voteUp);
if ( im != null ) {
//Update the view here
}
}

Categories

Resources