views:

9312

answers:

5

I'm trying to bind data from my SQLiteDatabase to a ListView. I'm currently using a SimpleCursorAdapter to fill in my ListView. Unfortunately this doesn't seem to work with setting a CheckBox's checked attribute.

This is how I do it now; instead of changing the CheckBox's checked status the adapter is filling in the value to the text argument, so the value is displayed right of the CheckBox as text.

Java:

setListAdapter( new SimpleCursorAdapter( this,
      R.layout.mylist,
      data,
      new String[] { Datenbank.DB_STATE, Datenbank.DB_NAME },
      new int[] { R.id.list_checkbox, R.id.list_text }
    ) );

mylist.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>

<CheckBox android:text=""
 android:id="@+id/list_checkbox"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:checked="false"
 ></CheckBox>

<TextView android:text=""
 android:id="@+id/list_text"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 ></TextView>

</LinearLayout>

Edit: The field in the database is of course of type boolean and I've also tried to assign an id to the checked field to fill the value in.

+5  A: 

I'm not sure how you would do this aside from creating a custom Adapter that overrode newView/bindView or getView, depending on what you override (ResourceCursorAdapter is a good one).

Ok, so here's an example. I didn't test to see if it would compile because I'm at work, but this should definitely point you in the right direction:

public class MyActivity extends ListActivity {

    MyAdapter mListAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Cursor myCur = null;

        myCur = do_stuff_here_to_obtain_a_cursor_of_query_results();

        mListAdapter = new MyAdapter(MyActivity.this, myCur);
        setListAdapter(mListAdapter);
    }


    private class MyAdapter extends ResourceCursorAdapter {

        public MyAdapter(Context context, Cursor cur) {
            super(context, R.layout.mylist, cur);
        }

        @Override
        public View newView(Context context, Cursor cur, ViewGroup parent) {
            LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            return li.inflate(R.layout.mylist, parent, false);
        }

        @Override
        public void bindView(View view, Context context, Cursor cur) {
            TextView tvListText = (TextView)view.findViewById(R.id.list_text);
            CheckBox cbListCheck = (CheckBox)view.findViewById(R.id.list_checkbox);

            tvListText.setText(cur.getString(cur.getColumnIndex(Datenbank.DB_NAME)));
            cbListCheck.setChecked((cur.getInt(cur.getColumnIndex(Datenbank.DB_STATE))==0? false:true))));
        }
    }
}
MattC
Could you give me an example, because I'm really new into android programming and haven't seen something like this yet?
svens
Sure thing, lemme dig something up and I'll post it.
MattC
Thanks !!It worked. There seems to be no getBoolean() function ;-).. I'm now usingcbListCheck.setChecked( (cur.getInt(cur.getColumnIndex(Datenbank.DB_STATE))==0? false:true) );which does the trick.
svens
An optimization would be moving the do_stuff_here_to_obtain_a_cursor_of_query_results(); out of onCreate and into a background thread so long-running operations don't lock the UI thread. Look into the AsyncTask class to get you started there. Of course if it's going to be fast every time you run that query, it's not necessary.
MattC
Thanks for the tip, I'll have a look on that.You really saved my life, my todo app looks really cool now.
svens
I'm also going to update my example to use your code since getBoolean is a syntax error.
MattC
Could you also shortly explain why you use MyActivity.this as Context? I've only used this and it works too.
svens
It's just habit. Android loves to use anonymous inner classes when declaring click handlers and other things of that nature. When you need to reference the context in those situations, I generally use MyPublicClassName.this
MattC
Because once you're in an anonymous inner class, "this" references that inner class, not the public class that also doubles as a reference to the context. Does that make sense?
MattC
+8  A: 

You could set a custom SimpleCursorAdapter.ViewBinder:

SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(/* ur stuff */);
cursorAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
    public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
     if(columnIndex == 1) {
      CheckBox cb = (CheckBox) view;
      cb.setChecked(cursor.getInt(1) > 0);
      return true;
     }
     return false;
    }
});

The setViewValue method is invoked for every column you specify in the SimpleCursorAdapter constructor and gives you a good place to manipulate some (or all) of the views.

Josef
Only problem is that this is not available in api level 3 (Android 1.5). This is available from api level 5.
Samik R.
A: 

You can solve that problem by creating a custom CheckBox widget like so:

package com.example.CustomCheckBox;    
public class CustomCheckBox extends CheckBox {
     public CustomCheckBox(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
     }
     public CustomCheckBox(Context context, AttributeSet attrs) {
      super(context, attrs);
     }
     public CustomCheckBox(Context context) {
      super(context);
     }
     protected void onTextChanged(CharSequence text, int start, int before, int after) {
      if (text.toString().compareTo("") != 0) {
       setChecked(text.toString().compareTo("1") == 0 ? true : false);
       setText("");
      }
     }
    }

The onTextChanged function will be called when the ListView binds the data to the CheckBox (ie. Adding either "0" or "1"). This will catch that change and add in your boolean processing. The 1st "if" statement is needed so as to not create infinite recursion.

Then provide your custom class in to the layout file as such:

<com.example.CustomCheckBox
 android:id="@+id/rowCheckBox"
 android:layout_height="fill_parent"
 android:layout_width="wrap_content" />

That should do it!

Nick
A: 

Hi,

I have simple list to be filled in from the database along with a checkbox. I need a handle to all the checkboxes selected. Whn the CLEAR button is pressed at that point I need the row ids of all the selected check boxes to delete them. To do this : My list.xml file looks like this :

<ListView 
          android:id="@id/android:list"
      android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_weight="1"
          />

and my data_entry.xml looks like this:

Now: I have list.java file where I am populating the list as follows:

private void populateList() {
     Cursor c = db1.getAllList();
      String[] fields = new String[]{db1.get_data()};

       SimpleCursorAdapter cursorAdapter = new 

  ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.data_entry, c,
          fields, new int[] {R.id.EntryText});

// Bind to our new adapter. setListAdapter(adapter); }

Now where do i give the handle to the heckbox cause anywhere else it would give me a null exception as the data_entry contains the checkboxes. Plus I need a listener to handle the checkbox status? I am just stuck at this point with no clue..

Prerna
A: 

You find the answer from the following link

http://saigeethamn.blogspot.com/2009/10/android-developer-tutorial-part-12.html

Krishna