0

Here's my getView function in a custom class extending ArrayAdapter.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Get the data item for this position
    Thing p = getItem(position);
    Thing.ThingStatus thingStatus = p.getStatus();

    int thingStatusIcon; // change to thingStatusResource
    switch (thingStatus) {
        case A:
            thingStatusIcon = ICON_A;
            break;
        case B:
            thingStatusIcon = ICON_B;
            break;
        default:
            thingStatusIcon = ICON_C;
            break;

    }

    // Check if an existing view is being reused, otherwise inflate the view
    ThingRowHolder viewHolder; // view lookup cache stored in tag
    if (convertView == null) {
        // If there's no view to re-use, inflate a brand new view for row
        viewHolder = new ThingRowHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.thing_list_item, parent, false);
        // put these on the top like the colors
        viewHolder.thingIcon = (ImageView) convertView.findViewById(R.id.thing_icon);
        viewHolder.thingId = (TextView) convertView.findViewById(R.id.thing_id_item);
        viewHolder.thingStatus = (TextView) convertView.findViewById(R.id.thing_status_item);
        // Cache the viewHolder object inside the fresh view
        convertView.setTag(viewHolder);
    } else {
        // View is being recycled, retrieve the viewHolder object from tag
        viewHolder = (ThingRowHolder) convertView.getTag();
    }

    viewHolder.thingId.setText(p.getLpId());
    viewHolder.thingStatus.setText(thingStatus.toString());
    viewHolder.thingIcon.setImageResource(thingStatusIcon);
    viewHolder.position = position;
    return convertView;
}

I'm trying to add an onClick event listener for each row in my ListView. I tried setting the listener on convertView both inside the if statement and outside the else statement. I got mixed results. Sometimes the onClick wouldn't fire at all. Other times it would report the wrong position. I've scoured SO for examples of this and I'm surprised such a common functionality isn't well documented and/or not working in my case.

Any help would be much appreciated!

edit:

private class ThingRowHolder {
    ImageView thingIcon;
    TextView thingId;
    TextView thingStatus;
}

edit 2:

private void refreshList() {
    ArrayList<Thing> things = mThingContainer.getThings();
    Collections.sort(things);
    mThingListAdapter.refreshThings(things);
}

edit 3:

mThingListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        ThingListAdapter.ThingRowHolder holder =
                (ThingListAdapter.ThingRowHolder) view.getTag();
        Thing p = mThingContainer.getThings().get(holder.position);
    }
});
aaa
  • 363
  • 4
  • 15

2 Answers2

0

Use these inside your getView method

If you want long click

convertView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {}}

if you want normal click

   convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {}}
Shubham Shukla
  • 988
  • 2
  • 13
  • 28
Grzegorz
  • 841
  • 7
  • 9
0

Set position as tag to your view,

convertview.setTag(R.id.thing_icon, position);

Now in your onClick(View v),

int pos = (int)v.getTag(R.id.thing_icon);
Thing p = getItem(pos);

You can now use p as desired.

Edit 1 : Updating data in adapter

In your adapter, add the following method :

public void updateData(List<Thing> data) {
        if (data != null) {
            mData.clear();
            mData.addAll(data);
            notifyDataSetChanged();
        }
    }

Now just call updateData method of adapter whenever you need to update the data.

nipun.birla
  • 719
  • 5
  • 19
  • This works, thanks! One small problem though, if a new item is added to the list, the positions when tapped are all shifted back one. – aaa Jan 31 '17 at 20:50
  • Are you calling notifyDataSetChanged() for your adapter on updating list data? Whenever you update your data list, pass the updated list to your adapter and call notifyDataSetChanged(), this will make the adapter update and redraw views based on your updated list. – nipun.birla Jan 31 '17 at 20:52
  • I'm currently creating a new adapter for every refresh – aaa Jan 31 '17 at 20:55
  • That's not really recommended. I'll edit my ans and include updating data in adapter. – nipun.birla Jan 31 '17 at 20:56
  • Thanks, appreciated – aaa Jan 31 '17 at 20:57
  • Still the same issue. Does it matter where I set the `mListView.onClickListener` ? – aaa Jan 31 '17 at 21:05
  • Can you post how you are updating list data which causes change in position? – nipun.birla Jan 31 '17 at 21:05