Search code examples
androidlistviewandroid-listviewlistviewitemonscrolllistener

Android LiistView item update


I've a listview with 30 to 40 items. Each item has one image view and many other views. When the user clicks on the image view(sunrise image), it should be toggled with another image view(sunset image).

When I tap the sunrise image in one item, many other items are also toggling. I want to know how other item's image view are updating and how I can handle to toggle only the item exactly where the user taps?

My adapter - MyAdapter extends BaseAdapter implements AbsListView.OnScrollListener.

Please let me know if any other info is required from my side.

EDIT: Adding my getView() method.

public View getView(int position, View view, ViewGroup parent) {
            if (position < this.data.size()) {
                if (view == null) {
                    view = createView(position, parent);
                }
                //some other data fill
                view.findViewById(R.id.sunrise).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(final View view) {
                            ((ImageView)view.findViewById(R.id.sunrise)).setImageResource(R.drawable.sunset);
                        }
        });
            } else {
                if (view == null) {
                    LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    view = vi.inflate(R.layout.waiting, null);
                }
            }
            return view;
    }

Solution

  • The views are being recycled. This DevBytes video on ListView animation explains exactly what your problem is. It describes how to notify the framework that you don't want a particular view recycled. This is accomplished by calling setHasTransientState() on the View in question.

    For a better solution, check out the StableArrayAdapter from this DevBytes video on animating ListView deletion (particularly the first three minutes). The StableArrayAdapter overrides hasStableIds() to return true, which has the same effect as setHasTransientState().

    /*
     * Copyright (C) 2013 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.example.android.listviewremovalanimation;
    
    import java.util.HashMap;
    import java.util.List;
    
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    
    public class StableArrayAdapter extends ArrayAdapter<String> {
    
        HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
        View.OnTouchListener mTouchListener;
    
        public StableArrayAdapter(Context context, int textViewResourceId,
                List<String> objects, View.OnTouchListener listener) {
            super(context, textViewResourceId, objects);
            mTouchListener = listener;
            for (int i = 0; i < objects.size(); ++i) {
                mIdMap.put(objects.get(i), i);
            }
        }
    
        @Override
        public long getItemId(int position) {
            String item = getItem(position);
            return mIdMap.get(item);
        }
    
        @Override
        public boolean hasStableIds() {
            return true;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = super.getView(position, convertView, parent);
            if (view != convertView) {
                // Add touch listener to every new view to track swipe motion
                view.setOnTouchListener(mTouchListener);
            }
            return view;
        }
    
    }