简体   繁体   中英

Android listActivity onListItemClick with CheckBox

my question is how to access and change the checkBox mode for any item in a listactivity. I have an XML template file with a checkbox and a textview, and these define a row. Here's what I'm trying so far:

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
        Toast.makeText(this, "You selected: " + Integer.toString(position), Toast.LENGTH_LONG).show();

        CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox); 
        if (checkbox.isChecked() == false) {
            checkbox.setChecked(true); 
        } else {
            checkbox.setChecked(false); 
        }

}

Obviously though using R.id.checkbox only toggles the first checkbox (actually, it does the first checkbox of whatever part of the list I'm looking at on my screen). I'm not sure what function to use to get the checkbox of any row though. The Toast works fine btw, so at least it registers position properly.

Thanks for any help.

EDIT - I'm now trying to subclass the SimpleCursorAdapter to better control the behaviour I want. Here is that subclass:

public class musicPlaylist extends SimpleCursorAdapter {

private Cursor c;
private Context context;
private ArrayList<String> checkList = new ArrayList<String>();
private final static int SELECTED = 1;
private final static int NOT_SELECTED = 0;

public musicPlaylist(Context context, int layout, Cursor c,
        String[] from, int[] to) {
    super(context, layout, c, from, to);
    this.c = c;
    this.context = context;

}

public View getView(int pos, View inView, ViewGroup parent) {
    View v = inView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.song_item, null);
    }

    this.c.moveToPosition(pos);     
    int columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME);
    String song = this.c.getString(columnIndex);

    TextView sTitle = (TextView) v.findViewById(R.id.text1);
    sTitle.setText(song);
    v.setId(NOT_SELECTED);
    v.setTag(song); 
    v.setOnClickListener(new OnClickListener() {



        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub


            if (v.getId() == NOT_SELECTED) {
                v.setId(SELECTED);
                Toast.makeText(context, "Test: " + v.getId(), Toast.LENGTH_SHORT).show();  
                v.setBackgroundColor(Color.parseColor("#FFFFFF"));

            } else {
                v.setId(NOT_SELECTED);
                Toast.makeText(context, "Test: " + v.getId(), Toast.LENGTH_SHORT).show();  
                v.setBackgroundColor(Color.parseColor("#000000"));
            }

        }
    });

    return v; 
}

}

And for reference, here is the XML of the ListActivity I'm making:

<?xml version="1.0" encoding="utf-8"?>

 <ListView android:id="@android:id/list"
           android:layout_width="fill_parent"
           android:layout_height="fill_parent"
           android:layout_weight="1"
           android:drawSelectorOnTop="false"
           android:fastScrollEnabled="true"
           android:cacheColorHint="#00000000"
           />

 <TextView android:id="@android:id/empty"
           android:layout_width="fill_parent"
           android:layout_height="fill_parent"
           android:text="No data"/>

Current behaviour: the list of songs from the SD card is made into a nice scrollable list. I do get somewhat proper responses from getView()'s onClick: The first time I click an item, it Toasts that its tag is "1" and its background goes white, while the second time I toast the same item, I get "0" and the background goes black, which is as expected.

The problem is if I select item1 (making its background white) and then scroll down, I'll notice that item11, item21, item31, ... , etc ALSO have white backgrounds. But when I click on them, their ID attribute goes to "1", meaning they've technically never been clicked before! So basically when the scroll "refreshes" to the next list of 10, it copies the color scheme of the first 10...?

Hope I explained it clearly.

I think this is bit deeper question and not direct answer is needed.

What do you want to achieve? Do you really want to make selected ONLY the checkboxes that you see on screen? Mind that this might be pretty random - list view only holds item views for the checkboxes that are visible on screen and they are reused for other items whenever the item is scrolled outside the screen.

I'd say that almost for sure you need to change state of all the checkboxes in your list (even those not visible) or some subset of them (like section). Which really translates into the proper way it should be done:

  • modify your data model appropriately marking the appropriate flags selected in corresponding data model elements (some boolean values you store per item)
  • call notifyDataSetChanged() on your adapter.

As a result, list view will recreate all the views which are visible on screen. Assuming that your "getView()" in adapter is written correctly, it will read the right model and update checked state on the item appropriately. By notifyDataSetChanged - if you have 10 items visible on screen you will have 10 times getView() called for every item visible.

I recommend using android:choiceMode="multipleChoice" instead of manually manipulating your rows this way. The row widget will need to implement the Checkable interface, which can either be done by using CheckedTextView as the row itself, or creating a subclass of your desired container and implementing Checkable on it .

You use "global" view instead your row view. Try like that:

 @Override
 protected void onListItemClick(ListView l, View v, int position, long id) {
   super.onListItemClick(l, v, position, id);

    CheckBox checkbox = (CheckBox) v.findViewById(R.id.checkbox); 
    if (checkbox.isChecked() == false) {
        checkbox.setChecked(true); 
    } else {
        checkbox.setChecked(false); 
    }
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM