Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
669 views
in Technique[技术] by (71.8m points)

android - Custom adapter: get item number of clicked item in inflated listview

I have a custom baseadapter which does some lazy loading of some images, and then inflating the layout so I end up with a listview where I have both image and text in one row.

When the user presses one item of the listview, say for example item 0 (top item), I want to show a dialog box with some specific content. This content depends on the item number - so the content shown for item 0 is not the same as for item 1, and so on.

Here is the getView method of the custom adapter:

public View getView(int position, View convertView, ViewGroup parent)
{
    View vi=convertView;        
    if(convertView==null)
    {
        vi = inflater.inflate(R.layout.facebook_item, null);                        
        vi.setClickable(true);
        vi.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {                   
                String s = "test";
                Toast.makeText(myContext, s, Toast.LENGTH_SHORT).show();
            }
        });
    }        

    TextView text=(TextView)vi.findViewById(R.id.text);
    ImageView image=(ImageView)vi.findViewById(R.id.image);
    text.setText(msg[position]);
    text.getLineCount();
    imageLoader.DisplayImage(data[position], image);
    return vi;
}

What's important here is what's going on in the onClick method. I would like to have an item parameter, but this is not possible for this OnClickListener. It's possible for normal listviews, I know that.

So - how can I determine which item is clicked?

PS: I've tried to think of using some sort of vi.setTag(<<number>>);, but I don't see how this can be done without having the same tag set for all items of the listview.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Why not use onItemClickListener on ListView itself?

Your Adapter should contain a List of one Object type (there is no strict rule, but it helps managing the item much easier). For example

class MsgObject{
    String msg;
    String data

    //TODO Getters/Setters goes here
}

Then your CustomAdapter will only contain

List<MsgObject> objectList;

Then your getView will looks similar to this

    MsgObject m = (MsgObject)getObject(position);
    TextView text=(TextView)vi.findViewById(R.id.text);
    ImageView image=(ImageView)vi.findViewById(R.id.image);
    text.setText(m.getMsg());
    text.getLineCount();
    imageLoader.DisplayImage(m.getData(), image);
    //Tag id is predefined in xml
    vi.setTag(R.id.listItemTag, m);
    return vi;

Now your view will handle this as one object instead of one layout with multiple values.

Then we move all the click action to the Activity which ListView resides in.

listView.setOnItemClickListener(){
    new AdapterView.OnItemClickListener(){

        @override
        public onItemClick(AdapterView<?> parent, View view, int position, long id){
            MsgObject m = (MsgObject)view.getTag(R.id.listItemTag);
            Toast.makeText(context, "Pos[" + position 
                + "] clicked, with msg: " + m.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

};

This is the way I have my ListView with Lazy load ImageView as well. Then you will be able to access the object tied to that view and also the position which is clicked.

If you are so wish to separate msg and data. You can use setTag(id, obj); for both object, etc.

setTag(R.id.listItemMsg, msg[position]);
setTag(R.id.listItemData, data[position]);

UPDATE: Example of my CustomAdapter

/**
 * Adapter for displaying Place selection list.
 * @author Poohdish Rattanavijai
 *
 */    
public class PlaceAdapter extends BaseAdapter {
    private static final String TAG = PlaceAdapter.class.getSimpleName();
    private List<PlaceVO> list; // <-- list of PlaceVOs
    private Context context;
    private int viewResourceId;

    /**
     * 
     * @param context Context
     * @param viewResourceId Layout ID for each item
     * @param list resource list to populate
     */
    public PlaceAdapter(Context context, int viewResourceId, List<PlaceVO> list){
        this.context = context;
        this.viewResourceId = viewResourceId;
        this.list = list;
    }

    /**
     * Number of result in the list plus one (for +add at the last item)
     */
    @Override
    public int getCount() {

        if(null != list){
            return list.size();
        }

        return 1;
    }

    @Override
    public Object getItem(int arg0) {
        if(null != list){
            try {
                return list.get(arg0);
            } catch (IndexOutOfBoundsException e) {
                return null;
            }
        }
        return null;
    }

    @Override
    public long getItemId(int position) {
//      if(null != list){
//          try {
//              return list.get(position).getId();
//          } catch (IndexOutOfBoundsException e) {
//              return 0;
//          }
//      }
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(null == convertView){
            /**
             * View does not exist, populate.
             */
            LayoutInflater inflater = LayoutInflater.from(this.context);
            convertView = inflater.inflate(this.viewResourceId, parent, false);
        }
        ViewHolder holder = (ViewHolder)convertView.getTag(R.id.adpter_view);

        if(null == holder){
            Log.d(TAG, "holder not found, init.");
            /**
             * ViewHolder does not exists for this view; create and assign respective view.
             */
            holder = new ViewHolder();
            holder.title = (TextView) convertView.findViewById(R.id.title);
            holder.details = (TextView) convertView.findViewById(R.id.details);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);
            holder.progress = (ProgressBar) convertView.findViewById(R.id.progress);
        }

        PlaceVO v = (PlaceVO)getItem(position); // <-- GetItem

        if(null != v){
            Log.d(TAG, "Place not null");
            if(HelperUtil.IsNotNullOrEmpty(v.getName())){
                Log.d(TAG, "Name: " + v.getName());
                holder.title.setText(v.getName());
            }

            if(HelperUtil.IsNotNullOrEmpty(v.getVicinity())){
                Log.d(TAG, "details: " + v.getVicinity());
                holder.details.setText(v.getVicinity());
            }

            if(HelperUtil.IsNotNullOrEmpty(v.getIcon())){
                holder.progress.setVisibility(View.VISIBLE);
                holder.icon.setVisibility(View.GONE);
                            //TODO Initialize LazyLoad
            }else{
                holder.progress.setVisibility(View.VISIBLE);
                holder.icon.setVisibility(View.GONE);
            }
        }
            // Two tags, one for holder, another for the VO
        convertView.setTag(R.id.adpter_view, holder);
        convertView.setTag(R.id.adpter_object, v);
        return convertView;
    }

    static class ViewHolder{
        TextView title;
        TextView details;
        ImageView icon;
        ProgressBar progress;
    }
}

Inside Activity I handle item click action with

OnItemClickListener itemClick = new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1,
                    int arg2, long arg3) {
                PlaceVO v = (PlaceVO)arg1.getTag(R.id.adpter_object); // <-- get object using tag.
                switchToPlaceScreen(v);
            }
        };
listView.setOnItemClickListener(itemClick);

Hope this answer your question :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...