Пользовательский адаптер: получить номер элемента, по которому щелкнули, в раздутом виде списка - PullRequest
1 голос
/ 05 февраля 2012

У меня есть собственный baseadapter, который выполняет некоторую ленивую загрузку некоторых изображений, а затем раздувает макет, поэтому я получаю в виде списка, где у меня есть и изображение, и текст в одной строке.

Когда пользователь нажимаетодин элемент списка, скажем, например, элемент 0 (верхний элемент), я хочу показать диалоговое окно с определенным содержанием.Это содержимое зависит от номера элемента - поэтому содержимое, отображаемое для элемента 0, отличается от элемента 1 и т. Д.

Вот метод getView пользовательского адаптера:

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;
}

Здесь важно то, что происходит в методе onClick.Я хотел бы иметь параметр элемента, но это невозможно для этого OnClickListener.Это возможно для обычных списков, я знаю это.

Итак - как я могу определить, по какому элементу щелкают?

PS: я пытался подумать об использовании какого-то вида vi.setTag(<<number>>);,но я не вижу, как это можно сделать, не устанавливая одинаковый тег для всех элементов списка.

Ответы [ 2 ]

5 голосов
/ 05 февраля 2012

Почему бы не использовать onItemClickListener для самого ListView?

Ваш Адаптер должен содержать Список одного типа Объекта (строгого правила нет, но это значительно упрощает управление элементом). Например

class MsgObject{
    String msg;
    String data

    //TODO Getters/Setters goes here
}

Тогда ваш CustomAdapter будет содержать только

List<MsgObject> objectList;

Тогда ваш getView будет выглядеть примерно так

    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;

Теперь ваш вид будет обрабатывать это как один объект вместо одного макета с несколькими значениями.

Затем мы перемещаем все действие click в Activity, в которой находится ListView.

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();
        }
    }

};

Вот так у меня есть ListView с отложенной загрузкой ImageView. После этого вы сможете получить доступ к объекту, связанному с этим видом, а также к позиции, по которой вы щелкнули.

Если вы хотите разделить сообщения и данные. Вы можете использовать setTag (id, obj); для обоих объектов и т. д.

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

ОБНОВЛЕНИЕ: Пример моего 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;
    }
}

Внутри действия Я обрабатываю действие щелчка элемента с помощью

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);

Надеюсь, что это ответ на ваш вопрос:)

1 голос
/ 05 февраля 2012
text.setText(msg[position]);
text.getLineCount();
imageLoader.DisplayImage(data[position], image);

По мере продвижения к созданию пользовательского адаптера вы хотите как можно больше ссылаться на свои элементы, используя getItem (int position).Избегайте ссылок на него, используя фактические массивы, которые вы передаете в конструкторе адаптера.

Попробуйте переопределить getItem(int position) и getItemId(int position) на вашем адаптере и используйте его вместо самих массивов внутри getView.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...