3

I'm pretty sure this is possible, but oddly enough can't find how. So, I have a ListActivity. I want this to be its row element:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <CheckBox
        android:id="@+id/checkbox"
        style="@style/CheckBox" />

    <TextView
        android:id="@+id/text"
        style="@style/Label"
        android:layout_width="fill_parent"
        android:layout_height="50sp"
        android:gravity="center_vertical" />

</LinearLayout>

I can already use this layout, I know how to specify TextView's id when creating ArrayAdapter. The layout is inflated fine, I can tick the checkboxes.

The problem is, I don't understand how to access those checkboxes. I need an inflated row layout to call findViewById on, but it's inflated asynchronously, not immediately when I add items to adapter. How to do this?

Violet Giraffe
  • 29,070
  • 38
  • 172
  • 299
  • This is same as TestView.. what is the problem. explain – Pankaj Kumar Nov 22 '13 at 11:43
  • And what you want to do with them? – Simon Dorociak Nov 22 '13 at 11:44
  • @PankajKumar: it's not the same. I do: `ArrayAdapter list = new ArrayAdapter(this, R.layout.row, R.id.text, items);` and it fills `TextViews` on its own. I don't have to do it manually. `CheckBoxes` I need to access myself, and it's unclear how. – Violet Giraffe Nov 22 '13 at 11:45
  • @Geralt: When a new list row is added, I need to get a reference to its `CheckBox` (possibly asynchronously, I don't care). For example, if I could just get the row view, I would call `findViewById(R.id.checkbox)` on it and be done. – Violet Giraffe Nov 22 '13 at 11:46
  • @PankajKumar All deepends what you want to do with Checkboxes. There are approaches i have now in my mind but don't seem efficient. If you would tell me what you want to achieve, maybe answer will come soon. – Simon Dorociak Nov 22 '13 at 11:49
  • Check my answer here. I had the same question. http://stackoverflow.com/a/16569700/1739882 – Chintan Soni Nov 22 '13 at 11:51
  • @Geralt: When a CheckBox is checked, I need to uncheck all other checkboxes and store the index of a checked one. – Violet Giraffe Nov 22 '13 at 11:55
  • possible duplicate of [delete multiple items in custom listview](http://stackoverflow.com/questions/16009209/delete-multiple-items-in-custom-listview) – Pankaj Kumar Nov 22 '13 at 11:55
  • @VioletGiraffe working on solution, be patient. – Simon Dorociak Nov 22 '13 at 12:07
  • @Geralt: Thank you! I'm looking at the _shree202_'s answer and I think I can make it work for my task, but it's not going to be pretty. – Violet Giraffe Nov 22 '13 at 12:14
  • @VioletGiraffe Check it out man. – Simon Dorociak Nov 22 '13 at 12:25

1 Answers1

2

When a CheckBox is checked, I need to uncheck all other checkboxes and store the index of a checked one

Here is my solution that came into my head right now. I don't now your implementation (implementation of Adapter, source of data etc.) so you will maybe need a little modifications. So now to my solution:

You need onCheckedChangedListener and put in into your ListAdapter class:

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
   // do your stuff
}

Now i don't know your actual scenario but most likely you have some collection of objects you are passing into Adapter and you're using it in getView() method that returns view of row.

Exactly here i suggest to modify your Object (item that represents each row in adapter) and add property:

private boolean isChecked;

that will "represent" your CheckBox.

Now implicitly each CheckBox will be unchecked (it's ok since booleans are implicitly assigned into false).

And now directly into Adapter class. In your class, exactly in your getView() you need to do following:

public View getView(final int position, View convertView, ViewGroup parent) {
   RowHolder holder = null; // RowHolder that holds widgets for each row
   LayoutInflater inflater = LayoutInflater.from(context); // for inflate rows

   // logic for inflating rows, pretty simply
   if (convertView == null) {
      // inflate row
      convertView = inflater.inflate(<yourLayout>, null, false);
      holder = new RowHolder(convertView);
      convertView.setTag(holder);
   }
   else {
      // recycle row
      holder = (RowHolder) convertView.getTag();
   }

   // inicialising row values
   final Item i = collection.get(position); // item from collection

   /** here will be work with CheckBoxes **/

   // here you will set position as CheckBox's tag
   holder.getCheckBox().setTag(position);

   // set CheckBox checked or not due to item in collection
   holder.getCheckBox().setChecked(item.isChecked());

   // and assign listener to CheckBox
   holder.getCheckBox().setOnCheckedChangeListener(this);
}

This is very immportant logic. Here you saved position of CheckBox in Adapter into CheckBox itself. Now CheckBox knows "where is located".

And then your listener will make following:

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
   // buttonView is CheckBox you changed state so we know which CheckBox it is
   int position = (Integer) buttonView.getTag();

   // if CheckBox is checked
   if (isChecked) {

      // iterate collection and assign all items except selected into false
      for (int i = 0; i < collection.size(); i++) {
         if (i != position) {
            collection.get(i).setChecked(false);
         }
      }

      // now call notifyDataSetChanged() that will call getView() method again
      // and it will update your List
      notifyDataSetChanged();
   }  
}

Here listener will make a trick. Also there is something about

I hope it'll help you reach your goal.

Community
  • 1
  • 1
Simon Dorociak
  • 32,775
  • 10
  • 65
  • 104