Search code examples
androidandroid-listviewsimplecursoradapterandroid-viewbinder

ListView with conditional formatting doesn't work properly(using a ViewBinder)


Auxiliary Problem

Hi, could anyone please help me understand the behavior of SimpleCursorAdapter.ViewBinder.setViewValue?

It seems that it is called more than once for each row in the ListView. Does the number of calls depend on the number of rows in the ListView? Or number of items in the cursor of SimpleCursorAdapter? Also, what are the significance of the parameters passed to the function?

Main Problem

I'm having this strange problem while trying to create a simple ListView of CheckedTextViews. I wanted to reduce the opacity of the rows which are checked. The code I wrote worked, except that it will always reduce the opacity of one extra row.

Making the layout_height of the ListView to match_parent solved the issue for some cases. But the problem still persists when I open the keyboard for editing and the ListView somehow gets required.


Please find the codes here

Code to fill the items in ListActivity:

private void fillDataToList() {
    Cursor all_taskCursorCursor = mDbHelper.fetchAllTask();
    startManagingCursor(all_taskCursorCursor);

    String[] from = new String[]{TaskDbAdapter.KEY_TITLE};
    int[] to = new int[]{R.id.task_title};

    SimpleCursorAdapter tasks = new SimpleCursorAdapter(this, R.layout.task_row, all_taskCursorCursor, from, to);

    tasks.setViewBinder(new ViewBinder() {

        public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
            if(columnIndex == 1) {
                CheckedTextView ctv = (CheckedTextView) view;

                String text = cursor.getString(cursor.getColumnIndexOrThrow(TaskDbAdapter.KEY_TITLE));
                boolean checked = cursor.getInt(cursor.getColumnIndexOrThrow(TaskDbAdapter.KEY_COMPLETED)) == 1 ? true : false; 

                ctv.setText(text);
                ctv.setChecked(checked); 

                if (checked == true) {
                    AlphaAnimation animation = new AlphaAnimation(1, 0.25f);
                    animation.setFillAfter(true);
                    ctv.setAnimation(animation); 

                    ctv.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG);
                }

                return true;
            }

            return false;
        }
    });

    setListAdapter(tasks);
}

The layout of ListView -

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

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</ListView>

<TextView
    android:id="@android:id/empty"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:text="@string/no_task"
    android:padding="10dp"
    android:gravity="center_vertical|center_horizontal"
    android:textAppearance="?android:attr/textAppearanceMedium" />

</LinearLayout>

Layout for each row -

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

<CheckedTextView
    android:id="@+id/task_title"
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    android:padding="10dp"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:checkMark="?android:attr/listChoiceIndicatorMultiple" />

</LinearLayout>

Solution

  • The problem was solved by adding one else condition to if (checked == true) part.

    The final code looks like this -

    if (checked == true) {
        AlphaAnimation animation = new AlphaAnimation(1, 0.25f);
        animation.setFillAfter(true);
        ctv.setAnimation(animation); 
    
        ctv.setPaintFlags(ctv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
    } else {
        ctv.setPaintFlags(ctv.getPaintFlags() & (~ Paint.STRIKE_THRU_TEXT_FLAG));
    }