Fancy ListViews Redux: 0.9 SDK and RatingBar

You may remember way back when (e.g., July 2008) when Building ‘Droids featured a six-post series on creating fancy ListView implementations, culminating in a CheckListView widget that could be used as a drop-in replacement for ListView.

They’re ba-ack!

Specifically, today, let’s take a look at the 0.9 SDK’s impact on the Fancy ListView series, and update one of the examples to take advantage of a new widget: the RatingBar.

In many respects, the code and techniques introduced in the Fancy ListViews series are still valid and relevant in the world of the 0.9 SDK. Perhaps the biggest change is that ViewInflate became LayoutInflater, requiring some search-and-replace edits of your older M5 source code. But the concepts of supplying custom views, of recycling views using the ViewHolder/ViewWrapper pattern, and the like are still very useful, even after the 0.9 SDK.

Of course, as promised, the 0.9 SDK has its own take on having checkable ListView widgets; this will be covered in a future blog post.

For now, though, let’s revisit the last sample from the Fancy ListViews series and update it to eschew the checkbox, switching to the new RatingBar.

RatingBar is a widget designed to users to provide a rating to something, such as rating a music track or a blog post or an Android development book up on Amazon.com (*cough*). A rating is a float, from 0 to a specified maximum (android:numStars). You can specify what the granularity of the rating is (android:stepSize) and whether it is merely an indicator (android:isIndicator) or if it is a user-input element to allow users to set the rating by sliding their finger across the stars.

As with just about any moderately-sized widget, the RatingBar can be used as part of a row in a ListView. In fact, replacing the CheckBox in CheckListView with a RatingBar is fairly straight-forward:

[sourcecode language=’java’]
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;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);
}
}
[/sourcecode]

  • Create and configure the RatingBar when it is lazy-instantiated in getView()
  • Hook in a RatingBar.OnRatingBarChangeListener to update a float[] of ratings, rather than a boolean[] of checkbox states
  • Update the rating in the RatingBar when it is recycled
  • Rename all the classes to something more logical (e.g., CheckableWrapper becomes RateableWrapper)

Unfortunately, the stock style for RatingBar is a bit big for lists:

A sample ListView using a RatingBar in each row

You can use a ratingBarStyleSmall style to shrink the size, but then the RatingBar becomes read-only, meaning you would need some other means to let people specify the rating itself.

About author

AndroidGuys
AndroidGuys 4625 posts

Founded on November 5, 2007, we've enjoyed bringing you the latest in Android news and rumors. Updated daily, we strive to deliver reviews, opinions, and updates on all things related to Android.

You might also like

News and Rumors

Firefox 4 Beta Lands on Android

Mozilla’s popular web client Firefox has come to Android in beta form. Formerly known as Fennec, the browser has been through a ton of updates and fixes over the last few weeks. If you’re looking to replace the stock internet app on your Android phone, you might enjoy Firefox 4 Beta .

Reviews

App Review: FrameGrabber for Android

I have to admit, I don’t use my phone’s video camera that often. Sure, I take lots of pictures, but not too many videos. But I’ve faced a problem in the past: taking still images from videos. Sure, you can do that with PhotoShop or another online tool, but there’s never really been a good way to do it from your Android device. Until now! FrameGrabber does exactly as the title suggests: it “grabs” frames from a video.

News and Rumors

Android security warning: SoundHound transmitting user location and Google account information

We’ve just gotten a tip about a potential privacy issue with the SoundHound app, a popular music service that users can download from the Market. Apparently, the app transmits a