Fancy ListViews, Part Five PDF Print E-mail

In one of our earlier posts in this Fancy ListViews series, Michal asked “could you make also a short tutorial on changing the background image and text color of the selection in ListView?”

Of course, we at AndroidGuys love fan mail! So, let’s talk about changing the way selections look in ListViews. As with many things in Android development, there’s the simple answer, the realization that the simple answer isn’t so simple, and some workarounds.

In theory, changing the selection bar is a matter of setting the android:listSelector property on the ListView widget in the layout XML, or using the equivalent setSelector() methods on the ListView object itself. In practice, well, let’s say there are issues…

Let’s first take a simple case: we want to change the color of the selection bar to something else, such as green. In the layout XML, the change is a single line:

 
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout 
  3.     xmlns:android="http://schemas.android.com/apk/res/android" 
  4.     android:orientation="vertical" 
  5.     android:layout_width="fill_parent" 
  6.     android:layout_height="fill_parent" > 
  7.     <TextView 
  8.         android:id="@+id/selection" 
  9.         android:layout_width="fill_parent" 
  10.         android:layout_height="wrap_content"/> 
  11.     <ListView 
  12.         android:id="@android:id/list" 
  13.         android:layout_width="fill_parent" 
  14.         android:layout_height="fill_parent" 
  15.         android:drawSelectorOnTop="false" 
  16.         android:listSelector="@drawable/green" 
  17.         /> 
  18. </LinearLayout> 

All we did was add android:listSelector="@drawable/green". Of course, we need to define that Drawable. In this case, since we’re settling for a solid color, a PaintDrawable defined in res/values/colors.xml will suffice:

 
  1. <resources> 
  2.     <drawable name="green">#f0f0</drawable> 
  3. </resources> 

That change alone will give us a ListView where the selection bar is green.

That’s nice and all, but suppose we want to do something more elaborate, something more exciting, something that speaks to the way the world is today.

In other words, rather than have list items be solely highlighted with a bar, we want to have them be pointed to by the Flying Fickle Finger of Fate.

(NOTE: any resemblance of this Flying Fickle Finger of Fate to the original is purely coincidental and terribly amusing)

For the Flying Fickle Finger of Fate (or FFFF for short), we’ll use a suitable icon, courtesy of OpenClipArt.org:

Flying Fickle Finger of Fate

The goal is to have the currently-selected list entry be pointed to by the finger. Sounds easy, right?

After all, since android:listSelector takes a reference to a Drawable resource, all we need to do is drop a suitably-sized PNG of FFFF into res/drawable, point to it from android:listSelector, set aside some whitespace on the left of our row layout to accommodate the icon, and it “just works”. Right?

Right?

Well, not exactly.

Android will attempt to stretch whatever PNG drawable you use as the list selector, so it takes up the full width of the ListView. In fact, I suspect it really would like you to use the so-called “Nine Patch” style PNG, where you use an outer border of pixels to provide instructions to Android for how to stretch the PNG.

I tried that and got…unpleasant results. Whether that was the result of my error in coding, my error in understanding how to make PNG-based list selectors work, or a bug in the M5 SDK, is still under investigation.

But the Flying Fickle Finger of Fate will not be denied. So, let’s take a look at how you “manually” adjust the way selected items looks. This also covers Michal’s second request — to see how to adjust other properties of the selected row besides the background image.

Working from the code first demonstrated in a previous post, let’s make a few changes.

First, we add an ImageView to our rows:

 
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="wrap_content" 
  5.     android:orientation="horizontal" 
  6. > 
  7.     <ImageView 
  8.         android:id="@+id/ffff" 
  9.         android:layout_width="81px" 
  10.         android:layout_height="41px" 
  11.     /> 
  12.     <ImageView 
  13.         android:id="@+id/icon" 
  14.         android:layout_width="22px" 
  15.         android:paddingLeft="2px" 
  16.         android:paddingRight="2px" 
  17.         android:paddingTop="2px" 
  18.         android:layout_height="wrap_content" 
  19.         android:src="@drawable/ok" 
  20.     /> 
  21.     <TextView 
  22.         android:id="@+id/label" 
  23.         android:layout_width="fill_parent" 
  24.         android:layout_height="fill_parent" 
  25.         android:layout_gravity="center_vertical" 
  26.         android:textSize="25sp" 
  27.     /> 
  28. </LinearLayout> 

Note how we neglected to provide the android:src attribute in the layout XML. Without a source, the ImageView simply paints nothing, showing the background. But, since we specified a size in pixels, it will take up that amount of space. In this case, we chose a pixel size that matches with an FFFF icon we prepared.

Next, we update our ViewWrapper to give us access to the FFFF:

 
  1. package com.commonsware.android.fancylists.seven; 
  2.  
  3. import android.view.View; 
  4. import android.widget.ImageView; 
  5. import android.widget.TextView; 
  6.  
  7. class ViewWrapper { 
  8.     View base; 
  9.     TextView label=null
  10.     ImageView icon=null
  11.     ImageView ffff=null
  12.  
  13.     ViewWrapper(View base) { 
  14.         this.base=base; 
  15.     } 
  16.  
  17.     TextView getLabel() { 
  18.         if (label==null) { 
  19.             label=(TextView)base.findViewById(R.id.label); 
  20.         } 
  21.  
  22.         return(label); 
  23.     } 
  24.  
  25.     ImageView getIcon() { 
  26.         if (icon==null) { 
  27.             icon=(ImageView)base.findViewById(R.id.icon); 
  28.         } 
  29.  
  30.         return(icon); 
  31.     } 
  32.  
  33.     ImageView getFlyingFickleFingerOfFate() { 
  34.         if (ffff==null) { 
  35.             ffff=(ImageView)base.findViewById(R.id.ffff); 
  36.         } 
  37.  
  38.         return(ffff); 
  39.     } 

Next, we add an OnItemSelectedListener to the ListView. As one might expect, this gets invoked every time an item is selected in the list, or when nothing is selected. There are two separate callback methods: onItemSelected() and onNothingSelected(). Our mission in these callbacks is to draw the FFFF on the selected row and to remove any previous FFFF from the previous selection.

In onItemSelected(), we see if we already have fingered a row (lastFinger!=null); if so, we null out the image Drawable, causing that ImageView to return to its original background-only state. We then get the current row’s ViewWrapper, get our FFFF placeholder, and have it actually draw the FFFF:

 
  1. public void onItemSelected(AdapterView parent, View v, int position, long id) { 
  2.     if (lastFinger!=null) { 
  3.         lastFinger.setImageDrawable(null); 
  4.     } 
  5.  
  6.     ViewWrapper wrapper=(ViewWrapper)v.getTag(); 
  7.  
  8.     lastFinger=wrapper.getFlyingFickleFingerOfFate(); 
  9.     lastFinger.setImageResource(R.drawable.ffff); 

In onNothingSelected(), we simply null out the previous finger (if there was one), both in terms of the image displayed and in terms of the lastFinger variable.

 
  1. public void onNothingSelected(AdapterView parent) { 
  2.     if (lastFinger!=null) { 
  3.         lastFinger.setImageDrawable(null); 
  4.         lastFinger=null
  5.     } 

The result is almost what we were after, complete with the green bar discussed earlier:

Green selection bar with Flying Fickle Finger of Fate

There are two flaws in this implementation as seen in the M5 SDK emulator. First, we get a FFFF icon on the first row when the activity starts, even though the row is not selected. That is because onItemSelected() is inexplicably called without that row being selected. Second, if you click on a row, you will get the green bar without the FFFF. In fact, the FFFF is cleared from the previous selection. Apparently, the current version of Android treats clicks and selections as being different from a callback standpoint, but the same from a display standpoint (i.e., uses android:listSelector). We will revisit all of these issues sometime after the next SDK release and see how the ListView behaves at that time.

While this demo shows activating or deactivating an icon in the row, you could do whatever you want to the View that makes up the row. So, if Michal wanted to change the text color of the selected row, that’s merely a matter of getting one’s hands on the desired TextView (perhaps via a wrapper or holder), and then call setTextColor().

Of course, setTextColor() is remarkably more complicated than one might expect, worthy of a future Building ‘Droids post in its own right.

Next time, in our final episode of the Fancy ListViews series, we will go back to the checklist scenario from before and wrap up the checkable-row logic into a CheckListView widget that one could use as a drop-in replacement for ListView. Until then, always remember: ask not to whom the Flying Fickle Finger of Fate points, it points to thee.

 

Source: http://androidguys.com/2008/07/28/fancy-listviews-part-five/

Comments (11)Add Comment
birkenstock shoes
written by birkenstock , May 29, 2010
When you are on a holiday in some seaside resort where you will hike and walk on cliffs, Birckenstock is one of the brands to which you turn your attention to find some slippers or flip-flops that make a holiday in comfort and without pain in the feet after a romantic walk on the rocks.Birkenstocks is the well-known German footwear brand: Birkenstock shoes, Birkenstock sandals and Birkenstock clogs.Birkenstock Gizeh is a flattering flip-flop style with a leather upper that will look great with shorts, jeans or dresses, at the same time, it has an irresistible air between the tourist and hiking, and you can be sure that the evening will have no pain, given the high quality these shoes.
report abuse
vote down
vote up
Votes: +0
...
written by supra shoes , May 31, 2010
The are popular with both recreation and Supra Shoes
Supra Footwear sportswear are simply matchless in terms of style, comfort and longevity, Now! Free Shipping! NO Tax!
report abuse
vote down
vote up
Votes: +0
air max 2009
written by air max 2009 , May 31, 2010
are you looking for a air max 2009?
here are not only offer the nike free shoes ,but aslo for thenew lebron VII shoes
report abuse
vote down
vote up
Votes: +0
...
written by mbt , June 18, 2010
The are popular with both recreation
report abuse
vote down
vote up
Votes: +0
changing the selection...
written by coach outlet store online , June 19, 2010
changing the selection bar is a matter of setting the android:listSelector property on the ListView widget in the layout XML, or using the equivalent setSelector() methods
report abuse
vote down
vote up
Votes: +0
Cheap San Francisco 49ers Jerseys
written by sexy bikinis , June 24, 2010
It is not the NFL Jerseys critic who counts,not the man who points out how the strong man stumbles,the doer of deeds could have sexy bikinis sale done them better. The credit belongs to the man who is actually in the arens,whose face is marred by dust and sweat and blood.
report abuse
vote down
vote up
Votes: +0
mbt
written by mbt shoes , June 29, 2010
The credit belongs to the man who is actually in the arens,whose face is marred by dust and sweat and blood.
ugg boots
report abuse
vote down
vote up
Votes: +0
...
written by sexy shoes , July 08, 2010
Ai jiangshan,gengai meinv,christian louboutin
christian louboutin shoes ,you can buy here on our shop .
report abuse
vote down
vote up
Votes: +0
Cheap GHDs
written by Cheap GHDs , July 17, 2010
Cheap ghds is is provided purely as an information based service.
Cheap GHDs
We provide information, specification, and price comparisons of ghd products, both promoting them and helping you find the best online prices from reputable retailers bringing you the cheapest ghds online.
GHD Straighteners
We try to ensure that information on this website is as accurate as possible,
GHD Colour Collection
however we accept no responsibility for any errors on this website whatsoever. This website is updated throughout the day,
GHD IV Styler
every day to ensure that the information you see is as accurate as possible.
GHD Precious Gift Set
This site is in no way owned by or affiliated with ghd and is an unofficial ghd price comparison website.
GHD IV Styler Dark
All images, logos and trademarks belong to their respective owners.
GHD Radiance Benefit Set
By using this website you are agreeing to our Privacy policy and Terms & Conditions.
GHD Hair Straightener
GHD on sale
GHD IV Salon Styler
GHD IV Mini Styler
GHD IV Gold Styler
GHD Kiss IV Styler
GHD Pure IV Styler
GHD Purple IV Styler
GHD Black IV Styler
GHD Benefit Styler
GHD Rare Styler
GHD Pink Styler
report abuse
vote down
vote up
Votes: +0
Monster Energy Hats
written by Monster Energy Hats , July 28, 2010
I don’t know what to say except that I have enjoyed
reading.Nice blog,I will keep visiting this blog very often.
report abuse
vote down
vote up
Votes: +0
...
written by Abercrombie and fitch , July 29, 2010
http://whyandroid.com/android/...pters.html
report abuse
vote down
vote up
Votes: +0

Write comment
quote
bold
italicize
underline
strike
url
image
quote
quote
smile
wink
laugh
grin
angry
sad
shocked
cool
tongue
kiss
cry
smaller | bigger

security code
Write the displayed characters


busy
 

 

This domain is for sale! Please contact me via contact page!