12

I have a ListView with a custom adapter. The ListView allows multiple select, but somehow it's not recognising when an item is selected.

I've already made the adapter items extend Checkable, but still the getCheckedItemPositions()returns an array of falses.

I guess there's something fundamental I'm doing wrong, but I have been unable so far to find examples of multiple select ListViews where the adapter was not an ArrayAdapter using the default layout for multiple selects.

Any help would be much appreciated.

Code is below:

Main class:

listView = (ListView) findViewById(R.id.cardlist);

tca = new TextCardAdapter(mInflater);
listView.setAdapter(tca);

Adapter:

public class TextCardAdapter extends BaseAdapter {
private int count = 0;
private List<CheckableCard> cardList = new ArrayList<CheckableCard>();
private LayoutInflater mInflater;

public TextCardAdapter(LayoutInflater inflater) {
    this.mInflater = inflater;
}

@Override
public int getCount() {
    return count;
}

@Override
public Object getItem(int position) {
    return cardList.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.textlayout_row, null, false);
        convertView.setClickable(true);

        holder = new ViewHolder();
        holder.text = (TextView) convertView.findViewById(R.id.card_name);
        holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    final CheckableCard card = cardList.get(position);

    holder.text.setText(card.card.toString());
    holder.checkbox.setChecked(card.isChecked());
    holder.checkbox.setOnClickListener(card.checkListener);
    convertView.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            card.checkListener.onClick(v);
            holder.checkbox.setChecked(card.isChecked());
        }
    });

    return convertView;
}

public void add(Card card) {
    cardList.add(new CheckableCard(card));
    count++;
    notifyDataSetChanged();
}

public void addAll(Collection<Card> cardColl) {
    for (Card c : cardColl)
        add(c);
}

public void removeAll() {
    count = 0;
    cardList.clear();
    notifyDataSetChanged();
}

public Card getCard(int position) {
    CheckableCard cc = (CheckableCard) getItem(position);
    if (cc == null) return null;
    return cc.card;
}

public class CheckableCard implements Checkable {
    private boolean checked = false;
    public final Card card;
    public final OnClickListener checkListener;

    public CheckableCard(Card card) {
        this.card = card;
        checkListener = new OnClickListener() {

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

    @Override
    public boolean isChecked() {
        return checked;
    }

    @Override
    public void setChecked(boolean checked) {
        this.checked = checked;
    }

    @Override
    public void toggle() {
        checked = !checked;
    }

}

static class ViewHolder {
    TextView text;
    CheckBox checkbox;
}
}
DonGru
  • 12,863
  • 8
  • 42
  • 55
Pingless
  • 551
  • 1
  • 6
  • 8
  • have you found any solution for this problem? – kmalmur Oct 03 '12 at 11:37
  • I found a generic method to solve your kind of problem in a similar stackoverflow question ( http://stackoverflow.com/questions/2652109/multiple-choice-list-with-custom-view ): http://www.marvinlabs.com/2010/10/custom-listview-ability-check-items/ – ol_v_er Feb 18 '11 at 15:09
  • My solution eventually was to store the list of CheckableCards, and when retrieving all checked cards, iterating through the list and returning the ones which returned isChecked() as true. – Pingless Jan 06 '13 at 12:24
  • @Pingless check out this answer, it may help: http://stackoverflow.com/a/20171191/919216 – Chanakya Vadla Nov 24 '13 at 04:56

3 Answers3

9

Just have a try:

  1. listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

  2. holder.checkbox.setFocusable(false);

  3. I think that is the listView's sub item view shoudld implements the Checkable interface, that means the converted View(convertView) should have all the method of Checkable.

GrIsHu
  • 28,433
  • 10
  • 61
  • 99
Michael
  • 357
  • 5
  • 12
2

I had a problem like this once. It has something to do with the fact that you have a view on the adapter that is selectable causing the parent to ignore it. Removing it allows you to select the row of the listview again. What you've created is basically a button on a button, android does not like that :-(

Alex
  • 628
  • 8
  • 12
0

I had a similar problem. My list item view is a RealativeLayout with a LinearLayout containing a CheckBox and a TextView. No onItem...Listener was called until I did set the CheckBox.focusable to false. Furthermore not the objects in the adapter should be Checkable but the views used as the layout for the list item.

cybergen
  • 2,940
  • 1
  • 19
  • 29