Zell B.
Zell B.

Reputation: 10286

Android set view visibility inside ListAdapter

I have listview with arrayadapter. I want when clicking a button inside list item a specific view in that item (and not in other items) be visibile or invisible.

Heres the code what I'm doing in adapters getView() method:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {

        convertView = vi.inflate(layoutResourceId, null, false);
        holder = new Holder();
        holder.setShare((ImageView) convertView.findViewById(R.id.share));
        holder.setShareButtons((LinearLayout)convertView.findViewById(R.id.shareButtons));
        convertView.setTag(holder);


    }
    holder = (Holder) convertView.getTag();


    holder.getShare().setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            if(holder.getShareButtons().getVisibility()==View.GONE){
                holder.getShareButtons().setVisibility(View.VISIBLE);

            }
            else{
                holder.getShareButtons().setVisibility(View.GONE);

            }


        }
    });

    return convertView;
}

But all I'm getting is strange behavior. The onClickListener and setVisibilty methods are called correctly but my view sometimes get visible and sometimes not, and this depend on list scroll positon .

What I'm doing wrong and how should I solve this ?

Upvotes: 3

Views: 3806

Answers (3)

DroidBender
DroidBender

Reputation: 7892

Here is a snippet of my custom Adapter which will give you an example on how to react to an item click within the adapter itself:

Functionality: Every row represents a object which can be seen or not seen. Whether it is seen or not, the image is different. Clicking on an item toggles the image on/off.

public class Exampledapter extends ArrayAdapter<CustomObject> {

    private Context mContext;
    private int mLayoutResourceId;
    private ArrayList<CustomObject> mData = null;

    public ExampleAdapter(Context context, int layoutResourceId, ArrayList<CustomObject> data, DataSource datasource) {
        super(context, layoutResourceId, data);
        this.mLayoutResourceId = layoutResourceId;
        this.mContext = context;
        this.mData = data;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View lRow = convertView;
        ViewHolder holder = null;

        if (lRow == null) {
            LayoutInflater lInflater = ((Activity) mContext).getLayoutInflater();
            lRow = lInflater.inflate(mLayoutResourceId, parent, false);

            holder = new ViewHolder();
            holder.txtTitle = (TextView) lRow.findViewById(R.id.text_);
            holder.imageSeen = (ImageView) lRow.findViewById(R.id.image_toggle);

            lRow.setTag(holder);
        } else {
            holder = (ViewHolder) lRow.getTag();
        }

        holder.imageSeen.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                onListItemClick(position);
            }
        });

        if (mData.get(position).getSeen() == 1) {
            holder.imageSeen.setImageBitmap(mImageSeen);
        } else {
            holder.imageSeen.setImageBitmap(mImageUnseen);
        }

        holder.txtTitle.setText(mData.get(position).getTitle());
        return lRow;
    }

    protected void onListItemClick(int position) {
        if (mData.get(position).isSeen()) {       
            mData.get(position).setSeen(0);
        } else {  
            mData.get(position).setSeen(1);
        }
        notifyDataSetChanged();
    }

    class ViewHolder {
        TextView txtTitle;
        ImageView imageSeen;
    }
}

Upvotes: 1

Gabe Sechan
Gabe Sechan

Reputation: 93561

WHen a list view is scrolled, the child views are reused and reassigned to new positions. This is for efficiency, as creating new views is expensive. However, it puts the burden on the programmer- on every getView call you must completely reset every value of the view. So if pressing a button in the child changes the visibility of one of its members, you need to remember what the visibility should be for each numeric position, and in getView you must set the appropriate visibility for every element.

Upvotes: 4

Shade
Shade

Reputation: 10001

The holder is meant to keep references to the inner views for performance reasons. It is not related to the data that gets presented in your list - only to the "cells" in your list. You should determine whether stuff is visible or not based on your data.

Upvotes: 1

Related Questions