androidlistviewsimplecursoradapterandroid-viewbindercustomizing

Changing Color of ListView Row Item


This is the Alliances Activity on my app: ActAlliances.java

This is the layout for a single row:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alignmentMode="alignBounds"
android:orientation="horizontal"
android:useDefaultMargins="true" >

<TextView
    android:id="@+id/allc_lstRow_textView1"
    android:layout_width="50sp"
    android:layout_height="wrap_content"
    android:gravity="right"
    android:paddingRight="10dp"
    android:text="@string/tallc_id"
    android:textSize="18sp"/>
<TextView
    android:id="@+id/allc_lstRow_textView2"
    android:layout_width="140sp"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/allc_lstRow_textView1"
    android:gravity="left"
    android:text="@string/lst_item_allc_name"
    android:textSize="18sp"/>
<TextView
    android:id="@+id/allc_lstRow_invisible"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/allc_lstRow_textView2"
    android:layout_width="1dip"
    android:gravity="left"
    android:textSize="1sp"/>
<TextView
    android:id="@+id/allc_lstRow_textView3"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/allc_lstRow_invisible"
    android:layout_gravity="right"
    android:gravity="right"
    android:text="@string/lst_item_allc_power"
    android:textSize="18sp"/>
</RelativeLayout>

And this is the SimpleCursorAdapter with ViewBinder to customize the color of the Alliance (Grey for Neutral, Blue for Ally, Green for Vassal and Red for Enemy):

SimpleCursorAdapter dataAdapter = new SimpleCursorAdapter(
      this, 
      R.layout.lst_row_act_allc,
      mCursor,
      cols,
      to,
      0);
    dataAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
        @Override
        public boolean setViewValue(View view, Cursor cursor, int column) {
            if( column == 1 ){ 
                TextView tv = (TextView) view;
                String mPltc = cursor.getString(cursor.getColumnIndex("FPLTC"));
                if (BuildConfig.DEBUG) {
                    Log.i(Constants.TAG_ACTALLIANCES, "loadAllianceData(): Alliance Name: "+cursor.getString(cursor.getColumnIndex("FANAME")));
                    Log.i(Constants.TAG_ACTALLIANCES, "loadAllianceData(): Political Relation: "+mPltc);
                }
                // Set color of item based on Political Relation
                if(mPltc.equals("Ally")){
                    tv.setTextColor(Color.parseColor("#6699ff"));
                    String mAN = cursor.getString(cursor.getColumnIndex("FANAME"));
                    tv.setText(mAN);
                }
                if(mPltc.equals("Vassal")){
                    tv.setTextColor(Color.parseColor("#00ff00"));
                    String mAN = cursor.getString(cursor.getColumnIndex("FANAME"));
                    tv.setText(mAN);
                }
                if(mPltc.equals("Enemy")){
                    tv.setTextColor(Color.parseColor("#ff0000"));
                    String mAN = cursor.getString(cursor.getColumnIndex("FANAME"));
                    tv.setText(mAN);
                }
                if(mPltc.equals("Neutral")){
                    String mAN = cursor.getString(cursor.getColumnIndex("FANAME"));
                    tv.setText(mAN);
                }
                return true;
            }
            return false;
        }
    });

Now according to Logcat the TextView holding the alliance name is matching up with the column from the database table denoting the Political Relation:

03-11 21:48:15.229: I/ActAlliances(7823): loadAllianceData(): Alliance Name: IMMORTALS
03-11 21:48:15.328: I/ActAlliances(7823): loadAllianceData(): Political Relation: Neutral
03-11 21:48:15.497: I/ActAlliances(7823): loadAllianceData(): Alliance Name: Legion of Anarchy
03-11 21:48:15.497: I/ActAlliances(7823): loadAllianceData(): Political Relation: Ally
03-11 21:48:15.590: I/ActAlliances(7823): loadAllianceData(): Alliance Name: TheCulture
03-11 21:48:15.590: I/ActAlliances(7823): loadAllianceData(): Political Relation: Enemy
03-11 21:48:15.608: I/ActAlliances(7823): loadAllianceData(): Alliance Name: Rising Storm
03-11 21:48:15.608: I/ActAlliances(7823): loadAllianceData(): Political Relation: Vassal
03-11 21:48:15.647: I/ActAlliances(7823): loadAllianceData(): Alliance Name: NULL ALLIANCE
03-11 21:48:15.647: I/ActAlliances(7823): loadAllianceData(): Political Relation: Neutral
03-11 21:48:15.677: I/ActAlliances(7823): loadAllianceData(): Alliance Name: OMEGA 27
03-11 21:48:15.677: I/ActAlliances(7823): loadAllianceData(): Political Relation: Neutral

Yet, as it stands, there are two problems here:

  1. setViewValue() runs no less than 4 times when the ListView is displayed and before the user does anything.
  2. The first item in the list (in this case IMMORTALS) is re-colored according to the last color applied (since grey is the default color if the list items, it doesn't really count because the code just displays neutral alliance names without applying a color.

I need to fix these bugs and would appreciate any and all assistance.

NOTE: I didn't use ListActivity because the first two lines (Sector, Number of Alliances) aren't part of the ListView; i'm willing to rethink that decision.


Solution

    1. I don't really see a problem here.
    2. Set the text color to the default value in your last statement:

      if(mPltc.equals("Neutral")){
        tv.setTextColor(Color.parseColor("#444444"));
        String mAN = cursor.getString(cursor.getColumnIndex("FANAME"));
        tv.setText(mAN);
      }
      

    Other than that, I would recommend making the code more readable - you do the same thing in every if statement - either extract it to a private method or move it out of the statement.

    You could also replace if statements with a switch-case and use Enums.