overriding the default getView()
but otherwise allowing the delegated ListAdapter
to do the “real work:”
public class RateableWrapper extends AdapterWrapper {
Context ctxt = null;
float[] rates = null;
public RateableWrapper(Context ctxt, ListAdapter delegate) {
super(delegate);
this.ctxt = ctxt;
this.rates = new float [delegate.getCount()];
for(int i=0; idelegate.getCount(); i++) {
this.rates[i]=2.0f;
}
}
public View getView(int position, View convertView,
ViewGroup parent) {
ViewWrapper wrap = null;
View row = convertView;
if (convertView==null) {
LinearLayout layout = new LinearLayout(ctxt);
RatingBar rate = new RatingBar(ctxt);
rate.setNumStars(3);
rate.setStepSize(1.0f);
View guts = delegate.getView(position, null, parent);
layout.setOrientation(LinearLayout.HORIZONTAL);
rate.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.FILL_PARENT));
guts.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
RatingBar.OnRatingBarChangeListener l =
new RatingBar.OnRatingBarChangeListener() {
public void onRatingChanged(RatingBar ratingBar,
float rating, boolean fromTouch) {
rates[(Integer)ratingBar.getTag()] = rating;
}
};
rate.setOnRatingBarChangeListener(l);
layout.addView(rate);
layout.addView(guts);
wrap = new ViewWrapper(layout);
wrap.setGuts(guts);
layout.setTag(wrap);
rate.setTag(new Integer(position));
rate.setRating(rates[position]);
row = layout;
} else {
wrap = (ViewWrapper)convertView.getTag();
wrap.setGuts(delegate.getView(position, wrap.getGuts(),
parent));
wrap.getRatingBar().setTag(new Integer(position));
wrap.getRatingBar().setRating(rates [position]);
}
return(row);
}
}
The idea is that RateableWrapper
is where most of our rate-list logic resides. It puts the rating bars on the rows and it tracks the rating bars’ states as they are adjusted by the user. For the states, it has a float[]
sized to fit the number of rows that the delegate says are in the list.
RateableWrapper
’s implementation of getView()
is reminiscent of the one from RateListDemo
, except that rather than use LayoutInflater
, we need to manually construct a LinearLayout
to hold our RatingBar
and the “guts” (that is, whatever view the delegate created that we are decorating with the checkbox). LayoutInflater
is designed to construct a View
from raw widgets; in our case, we don’t know in advance what the rows will look like, other than that we need to add a checkbox to them. However, the rest is similar to what we saw in RateListDemo
:
class ViewWrapper {
ViewGroup base;
View guts = null;
RatingBar rate = null;
ViewWrapper(ViewGroup base) {
this.base = base;
}
RatingBar getRatingBar() {
if (rate==null) {
rate = (RatingBar)base.getChildAt(0);
}
return(rate);