Flex Spark List with custom scroll bar and itemrenderer

I recently had a request for some help on skinning a Flex 4 Spark List with a custom scroll bar and item renderers. Even though the skinning process has gotten much easier with Flex 4 and the Spark components there is still a learning curve and a few things that are either learned through a lot of trial and error or by having someone point it out to you. Hopefully with this post I will be able to save some other Flex developers the "trial and error" route.

This is the comp of the list that needed to get created. Nothing to complicated at first glance, the standard Spark scroll bar needs to get replaced and a custom itemrenderer will be needed for the list.

So how does one go about turning the image above into a functioning Spark List, follow along.

Step 1 – Prep the skin pieces

The scroll bar track and thumb from the comp need to be turned into assets that we can use in the Spark skin. The itemrenderer can be completely done with code. If you are familiar with Photoshop turn off the surrounding layers, select the thumb and track, respectively, and then do a 'copy merged' and paste each as a new image. Save them as transparent PNG's that can be embedded into the Flex swf.

Step 2 – Create the Spark Skins

Three skins will be required for this task, one for the thumb, the track and the vertical scroll bar (right click, view source on the swf at the bottom to view all the source code).

The track and thumb skins simply embed the pngs that we created in step 1.

The track skin:


<s:BitmapImage source="@Embed('assets/scroll-track.png', scaleGridLeft='2', scaleGridTop='5', scaleGridRight='12', scaleGridBottom='275')" 
				   left="0"  top="0" right="0" bottom="0" />
    

And the thumb skin:


<s:BitmapImage source="@Embed('assets/scroll-thumb.png', scaleGridLeft='1', scaleGridTop='5', scaleGridRight='13', scaleGridBottom='97')" 
				   left="0"  top="0" bottom="0" right="0" />

In both cases we use the scale nine attributes to make sure the graphic scales cleanly in the horizontal and vertical directions.

The scroll bar skin sets the skins class for the track and thumb buttons to the new skins we have created.


<s:Button id="track" top="0" bottom="0" right="0"  width="15"
		  focusEnabled="false"
		  skinClass="com.dgrigg.skins.VScrollBarTrackSkin" />

<s:Button id="thumb" width="14"
		  focusEnabled="false" visible.inactive="false"
		  skinClass="com.dgrigg.skins.VScrollBarThumbSkin"   />

That's it for skin creation.

Step 3 – Styling via CSS

Once the skins are created the next step is creating a css file to get the List component to look the way we want. Using css selectors we can tell the List to use the new skin class we have created for the vertical scroll bar on the list. The 'fixedThumbSize' style tells the scroll bar if it should adjust the size of the thumb based on the list length. In this case we want the thumb to always be the same size so it gets set to 'true'. We have also used CSS to turn off the horiztontal scroll bar, sometimes with custom item renderers the horizontal scroll bar will make an appearance when you don't want it to.

s|List 
{
	contentBackgroundAlpha:.5; 
	contentBackgroundColor: #000000;
	borderColor:#000000;
}

s|List #scroller 
{
	horizontalScrollPolicy: off;
}

s|List s|VScrollBar {
	skinClass: ClassReference("com.dgrigg.skins.VScrollBarSkin");
	fixedThumbSize:true;
}

Remember to load the style sheet into the main application class and the new pimped list is ready to go.

Step 4 – ItemRenderer creation

The final step in bring the comp to life is creating the ItemRenderer. Fortunately Flex 4 has made this very easy. Navigate to the package you want to create the renderer in and then right click and select 'New/MXML Item Renderer'. A basic item renderer will be created that you can begin working with. Here is the code for the item renderer we will be using.


<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
			xmlns:s="library://ns.adobe.com/flex/spark" 
			xmlns:mx="library://ns.adobe.com/flex/mx" 
			autoDrawBackground="false" height="85" width="385">
<fx:Script>
	<![CDATA[
		
		override public function set data(value:Object):void 
		{
			super.data = value;
			
			if (value)
			{
				titleLbl.text = data.title;
				contentLbl.text = data.text;
				titleLbl.visible = true;
				contentLbl.visible = true;
				readLbl.visible = true;
			}
			else
			{
				titleLbl.text = "";
				contentLbl.text = "";
				titleLbl.visible = false;
				contentLbl.visible = false;
				readLbl.visible = false;
			}
			
		}
	]]>
</fx:Script>
<s:states>
	<s:State name="normal" />
	<s:State name="hovered" />
	<s:State name="selected" />
</s:states>

<s:Rect left="0" right="0" top="0" bottom="0">
	<s:fill>
		<s:SolidColor color.selected="0x383c40" color.normal="0x23252a" color.hovered="0x383c40"
					  alpha.selected="0.8" alpha.hovered="0.5" alpha.normal="0.8" />
	</s:fill>
</s:Rect>

<s:Label id="titleLbl" 
		 x="15" y="15" 
		 width="370" color="0xffffff"/>

<s:Label id="contentLbl" 
		 x="15" y="30" 
		 width="370" height="30" 
		 color="0xeeeeee" fontSize="11"  />

<s:Label id="readLbl" 
		 x="15" y="65" 
		 color="0x336699" color.selected="0xCCCCCC" 
		 text="READ MORE" fontSize="11"/>

<s:Line left="0" right="0" bottom="0" width="1">
	<s:stroke>
		<s:SolidColorStroke color="0x000000"/>
	</s:stroke>
</s:Line>

</s:ItemRenderer>

A few things to note in the itemrenderer code. First, the 'autoDrawBackground' attribute on the ItemRenderer base class is set to 'false'. This turns off the  selected/rollover/hover background that normally gets drawn and displayed. The s:Rect instance is used with the state selectors on the color attribute to create custom rollover color/alpha combinations. The normal list will allow you to change the color but you can't tweak the alpha so this is your best option. Second, the 'set data' method was overwritten in order to set the values of the various labels. This is a must step for pretty much any custom item renderer. The overwritten method does a small check to see if the incoming value exists, if not the labels get hidden. This is always a good practice to prevent empty rows from appearing in the list.

Wrap up

That's it. A custom scroll bar and item renderer in four steps. No rocket science, just a little Flex know how. You can view the source code here.

And this is the final product, not bad.

 

14 Comments

  1. hsTed

    nice work

  2. Rounded corners on the right had side of the list BG would go a miss, just to get rid of the odd dark pixel at the top and bottom of the ScrollBar.

    Also wherever possible it makes sense to try and use vectors, run them through catalyst, and then copy and paste the output into your skins (with the odd edit here and there).

    This enables much more flexible styling (i.e. you could change the colors, rounded corners etc.

  3. @Tink

    I totally agree however I wanted to match the comp that was provided.

    Vectors do make sense, however I wanted to do this in as few steps as possible and many Flex developers are still unsure/unaware of Catalyst. In a scenario like this you don’t need the flexibility of a vector since the design is completely determined by the designer and then provided to the developer, no requirement for any changes on the fly.

    Hopefully I will do a future post on using Catalyst for going from PSD to skinned Flex component.

  4. Kun

    hi,

    is there a way you make read more label visible if content is large than the area and then when click the read more label all content will be visible.

    thanks

  5. jack

    hey had a question…tried the itemRenderer thing and great example b/c it worked but wanted to know how i set the dataprovider on my list so that the data appears in the itemRenderer…does that make sense?

  6. How would you approach allowing the scroll thumb image to scale using 9 slice given the 4 ridges in it? I am in a situation now where I am tasked with doing that and I am not sure of the best approach to take.

  7. @ryan I would crop down the area where the ridges are and have them be a separate piece of the scroll thumb. They could then center over the whole thumb width/height.

  8. Ryan

    @derrick

    Thanks for the prompt reply! I took your advice…added the separate ridges/grip image as another element (BitmapImage) of the scroll thumb skin and set its verticalCenter to 0 (i had cut the image so the width was the same as the thumb image). Worked like a charm!

  9. greg

    Awesome! The first spark example that has more than how to skin a button. After reading through all the Adobe examples(all buttons) for an hour I got my custom scroll bar working in five minutes with your example. Thank you

  10. gre

    src link is not working…..

  11. Derrick

    @gre link to source is fixed, thanks for catching that.

  12. Nice work really thanks , I am afraid that I would be specific for a component .. What would happen if want to apply it for application .. I want to say I am not sure which component would be using scroll , it would be either mx component or s component , and even control is not specific , it would be tree sometimes it would be panel .. So is there any way to define it globally ??

    Thanks

  13. Beeps

    Nice work. However can we make the background(tree image) scroll up and down, Is there a way to achieve this?

    Thanks.

Leave a comment

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 

Copyright © 2014 DGrigg Development Inc. zzz