• We always make sure that the RatingBar has the proper contents and has a tag (via setTag()) pointing to the position in the adapter the row is displaying.
The row layout is very simple: just a RatingBar and a TextView inside a LinearLayout:
<?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="wrap_content"
android:orientation="horizontal"
>
<RatingBar
android:id="@+id/rate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="3"
android:stepSize="1"
android:rating="2" />
<TextView
android:id="@+id/label"
android:paddingLeft="2px"
android:paddingRight="2px"
android:paddingTop="2px"
android:textSize="40sp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
The ViewWrapper is similarly simple, just extracting the RatingBar and the TextView out of the row View:
class ViewWrapper {
View base;
RatingBar rate = null;
TextView label = null;
ViewWrapper (View base) {
this.base = base;
}
RatingBar getRatingBar() {
if (rate==null) {
rate = (RatingBar)base.findViewById(R.id.rate);
}
return(rate);
}
TextView getLabel() {
if (label==null) {
label = (TextView)base.findViewById(R.id.label);
}
return(label);
}
}
And the result (Figure 9-3) is what you would expect, visually.
Figure 9-3. The RateListDemo application, as initially launched
This includes the toggled checkboxes turning their words into all caps (Figure 9-4).
Figure 9-4. The same application, showing a top-rated word
…And Checking It Twice
The rating list in the previous section works, but implementing it is very tedious. Worse, much of that tedium would not be reusable except in very limited circumstances. We can do better.
What we’d really like is to be able to create a layout like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/selection"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<com.commonsware.android.fancylists.seven.RateListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false"
/>
</LinearLayout>
where, in our code, almost all of the logic that might have referred to a ListView before “just works” with the RateListView we put in the layout:
public class RateListViewDemo extends ListActivity {
TextView selection;
String[] items={"lorem", "ipsum", "dolor", "sit", "amet",
"consectetuer", "adipiscing", "elit", "morbi", "vel",
"ligula", "vitae", "arcu", "aliquet", "mollis",
"etiam", "vel", "erat", "placerat", "ante",
"porttitor", "sodales", "pellentesque", "augue",
"purus"};
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
setListAdapter(new ArrayAdapterString(this,
android.R.layout.simple_list_item_1, items));
selection = (TextView)findViewById(R.id.selection);
}
public void onListItemClick(ListView parent, View v,
int position, long id) {
selection.setText(items[position]);
}
}
Things get a wee bit challenging when you realize that in everything up to this point in this chapter, never were we actually changing the ListView itself. All our work was with the adapters, overriding getView() and inflating our own rows and whatnot.
So if we want RateListView to take in any ordinary ListAdapter and “just work,” putting checkboxes on the rows as needed, we are going to need to do some fancy footwork. Specifically, we are going to need to wrap the “raw” ListAdapter in some other ListAdapter that knows how to put the checkboxes on the rows and track the state of those checkboxes.
First we need to establish the pattern of one ListAdapter augmenting another. Here is the code for AdapterWrapper, which takes a ListAdapter and delegates all of the interface’s methods to the delegate (from the FancyLists/RateListView sample project at http://apress.com/):