3

I'm developing an alarm clock app for android and I want to have displayed list of alarms on the main screen. Each row of this ListView is defined in xml file. And I want to have separate TextViews for each day of week. Program will check in sqlite db if for eg. value for monday is = 1 and then change color of this TextView to red. I have written this code, but that doesn't work. What's wrong?

private void fillData() {

    // Get all of the notes from the database and create the item list
    Cursor c = db.fetchAllAlarms();
    startManagingCursor(c);

    String[] from = new String[] { db.KEY_TIME, db.KEY_NAME };
    int[] to = new int[] { R.id.time, R.id.alarmName };

    // Now create an array adapter and set it to display using our row
    SimpleCursorAdapter alarms =
        new SimpleCursorAdapter(this, R.layout.alarm_row, c, from, to);
        alarms.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
        public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
            int dayOfWeekIndex = cursor.getColumnIndex("mon");
            if (dayOfWeekIndex == columnIndex) {
                int color = cursor.getInt(dayOfWeekIndex);
                switch(color) {
                case 0: ((TextView) view).setTextColor(Color.RED); break;
                case 1: ((TextView) view).setTextColor(Color.GRAY); break;
                }
                return true;
            }
            return false;
        }
    });
Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
bluepawel
  • 75
  • 1
  • 8

2 Answers2

7

From the Android documentation on SimpleCursorAdapter.ViewBinder:

Binds the Cursor column defined by the specified index to the specified view. When binding is handled by this ViewBinder, this method must return true. If this method returns false, SimpleCursorAdapter will attempts to handle the binding on its own.

In other words, your implementation of setViewValue should not be specific to any one View, as SimpleCursorAdapter will make changes to each View (according to your implementation) when it populates the ListView. setViewValue is basically your chance to do whatever you wish with the data in your Cursor, including setting the color of your views. Try something like this,

public boolean setViewValue(View view, Cursor cursor, int columnIndex){    
    // if this holds true, then you know that you are currently binding text to
    // the TextView with id "R.id.alarmName"
    if (view.getId() == R.id.alarmName) {
        final int dayOfWeekIndex = cursor.getColumnIndex("day_of_week");
        final int color = cursor.getInt(dayOfWeekIndex);

        switch(color) {
        case 0: ((TextView) view).setTextColor(Color.RED); break;
        case 1: /* ... */ break;
        case 2: /* ... */ break;
        /* etc. */
        }
        return true;
    }
    return false;
}

Note that the above code assumes a column named "day_of_week" which holds an int value 0-6 (to specify the specific day of the week).

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
  • Honestly now is worse then before, because it crashes. at the begening it executes alarmNameIndex = cursorgetColumnIndex(db.KEY_NAME.toString()); and it becomes 1, then columnIndex becomes 1 after 2 iterations, and then suddenly columnIndex becomes -1 – bluepawel Mar 12 '12 at 20:23
  • oh, sorry. It was my fault. I didn't changed yours "day_of_week_ to my "mon". But now the problem is the same. columnIndex is 1 or 2 during executing that function, but dayOfWeekIndex is 3, so it isn't working. – bluepawel Mar 12 '12 at 20:33
  • by the way, what exactly is "mon"...? does it simply hold "0" if the alarm is not set for monday, and 1 if it is set for monday? – Alex Lockwood Mar 12 '12 at 20:37
  • also, i don't know why you think "dayOfWeekIndex" being equal to 3 is indicating that the code doesn't work... dayOfWeekIndex is never going to be equal to columnIndex because you never told the `SimpleCursorAdapter` to bind from the "mon" column – Alex Lockwood Mar 12 '12 at 20:38
  • Yes "mon" hold "0" if alarm isn't set for monday and "1" if it is set for monday. So if mon is set for monday i want to change the color of TextView for monday. Main screen looks like this: http://img23.imageshack.us/img23/8468/snapshot1me.png – bluepawel Mar 12 '12 at 20:52
  • now I've changed to: String[] from = new String[] { db.KEY_TIME, db.KEY_NAME, db.KEY_MON }; but still column isn't 3 – bluepawel Mar 12 '12 at 21:05
  • ohhhhhh, ok i've been thinking you had a different layout all this time. could you post your XML layout (the custom list row one?) – Alex Lockwood Mar 12 '12 at 21:10
  • what is "R.id.alarmName"...? i see no 3rd textview in your screenshot – Alex Lockwood Mar 12 '12 at 21:12
  • OK! It worked! There was a problem with SimpleCursorAdapter, as you said I didn't bind it correctly so column was never == 3. Now it's ok with the code you provided. Thanks a lot for your patience and your time! in xml i have simply 9 text boxes set in relative layout, for time, alarmName, and 7 days. R.id.alarmName is the name of alarm. It should be above these days of week, but it was empty. – bluepawel Mar 12 '12 at 21:18
  • ahh... i see. adapters can be tough sometimes :). glad to hear you got it working – Alex Lockwood Mar 12 '12 at 21:37
2

From the Android documentation on SimpleCursorAdapter.ViewBinder:

Binds the Cursor column defined by the specified index to the specified view. When binding is handled by this ViewBinder, this method must return true. If this method returns false, SimpleCursorAdapter will attempts to handle the binding on its own.

In other words, your implementation of setViewValue should not be specific to any one View, as SimpleCursorAdapter will make changes to each View (according to your implementation) when it populates the ListView. Your implementation should look something like this,

notes.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
    public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
        int dayOfWeekIndex = cursor.getColumnIndex("day_of_week");
        if (dayOfWeekIndex == columnIndex) {
            int color = cursor.getInt(dayOfWeekIndex);
            switch(color) {
            case 0: ((TextView) view).setTextColor(Color.RED); break;
            case 1: /* ... */ break;
            case 2: /* ... */ break;
            /* etc. */
            }
            return true;
        }
        return false;
    }
});

Note that the above code assumes a column named "day_of_week" which holds an int value 0-6 (to specify the specific day of the week).

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
  • Thanks a lot, this was helpful, but I don't want to change each View, I only want to change one textview associated with specific day. And the second thing is that columnIndex has values of 1 and 2, but I have 10 columns in my cursor.. – bluepawel Mar 12 '12 at 16:08
  • i'm not 100% sure what it is that is going wrong, but you should re-consider hard-coding int values in your code. for example, saying `if (columnIndex == 5)` is not good practice, because this code will break if you ever alter your database in the future. see my code for an example on how to change this (this also might be the reason why things aren't working for you...) – Alex Lockwood Mar 12 '12 at 16:17
  • Yeah, I've done that as you have written, so I don't have hard-coded int values, but statement in 'if' condition is never true, because it checks only two first columns and I don't know why. – bluepawel Mar 12 '12 at 16:24
  • so wait, let me understand correctly... you want to update a _specific_ `View`s color IF one of the alarm's is set for a specific day of the week? – Alex Lockwood Mar 12 '12 at 16:32
  • also, I don't understand where the `TextView`s are being displayed. if the `ListView` is being displayed on the main screen, then where are these seven `TextView`s you are talking about? – Alex Lockwood Mar 12 '12 at 16:37
  • Yes. I have row layout defined in xml file in which I have textview for time, name of alarm, and 7 days of the week. And I have database in which I have for each alarm 7 columns for days (+ colums for time and name of course). Now I want to check in which days this alarm is active and change the color of these textview's to red for example. – bluepawel Mar 12 '12 at 16:40
  • All of views are in the ListView in each row. – bluepawel Mar 12 '12 at 17:57
  • is the code you posted updated... or have you changed it since you posted the question? – Alex Lockwood Mar 12 '12 at 18:29
  • what does the column `db.KEY_MON` hold... from what I can understand from your code, it should hold each alarm's name, correct? – Alex Lockwood Mar 12 '12 at 18:35
  • @ Alex Now it's updated. db.KEY_MON holds int value if monday is selected for alarm. It was there temporarily only to check if it reads value correctly – bluepawel Mar 12 '12 at 18:38