06-15-2012 04:07 PM
I'm trying to create a simple two labeled list by creating two label label fields using a class called TwoLabelCell which extends AlternatingCellRenderer and looks like this:
package views
{
import flash.text.TextFormat;
import qnx.fuse.ui.listClasses.AlternatingCellRenderer;
import qnx.fuse.ui.text.Label;
public class TwoLabelCell extends AlternatingCellRenderer {
private var description:Label;
private var labelFormat:TextFormat;
private var text:String;
public function TwoLabelCell(labelText:String) {
this.text = labelText;
}
override protected function init():void {
super.init();
labelFormat = new TextFormat();
labelFormat.color = 0x777777;
labelFormat.size = 17;
description = new Label();
description.x = 17;
description.y = 33;
description.format = labelFormat;
description.text = text;
this.addChild(description);
}
}
}Remember that this one is just a test at the time, so I'm working with only one label (after I figure out this question I'll add the other and use the same logic). The main idea here is that when I call this it will set the text variable which will be used to change the text of the label on the list when it's being created. Now, here the main application file:
package {
import flash.display.Sprite;
import qnx.fuse.ui.events.ListEvent;
import qnx.fuse.ui.listClasses.List;
import qnx.fuse.ui.listClasses.ListSelectionMode;
import qnx.fuse.ui.listClasses.ScrollDirection;
import qnx.ui.data.DataProvider;
import views.TwoLabelCell;
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]
public class PackTrack extends Sprite {
private var packList:List;
public function PackTrack() {
super();
initializeUI();
}
private function initializeUI():void {
packList = new List();
packList.setPosition(0, 0);
packList.width = 310;
packList.height = 400;
packList.rowHeight = 50;
packList.selectionMode = ListSelectionMode.SINGLE;
packList.scrollDirection = ScrollDirection.VERTICAL;
var arrMonth:Array=[];
arrMonth.push({label: "January"});
arrMonth.push({label: "February"});
arrMonth.push({label: "March"});
arrMonth.push({label: "April"});
arrMonth.push({label: "May"});
arrMonth.push({label: "June"});
arrMonth.push({label: "July"});
arrMonth.push({label: "August"});
arrMonth.push({label: "September"});
arrMonth.push({label: "October"});
arrMonth.push({label: "November"});
arrMonth.push({label: "December"});
packList.dataProvider = new DataProvider(arrMonth);
packList.cellRenderer = new TwoLabelCell("Testing Label");
packList.addEventListener(ListEvent.ITEM_CLICKED, onListClick);
this.addChild(packList);
}
private function onListClick(event:ListEvent):void {
trace("Item clicked: " + event.data.label);
trace("Index clicked: " + event.index);
}
}
}When I try to run that I get this error:
Error: skin must be Class or String at qnx.fuse.ui.listClasses::List/set cellRenderer()[E:\hudson\workspace\GR2_0_0_AIR_SDK_API\src\qnxui\src\qnx\fuse\ui\listClasses\List.as :1069] at PackTrack/initializeUI()[/Users/Nathan/Documents/A dobe Flash Builder 4.6/AIRTest/src/PackTrack.as:46] at PackTrack()[/Users/Nathan/Documents/Adobe Flash Builder 4.6/AIRTest/src/PackTrack.as:19]
Any idea on how to solve this (preferably not using MXML)?
PS: I'm learning Flex (coming from Java)
Solved! Go to Solution.
06-15-2012 08:33 PM
Per the API reference it looks like your code should change from:
packList.cellRenderer = new TwoLabelCell("Testing Label");
to:
packList.cellRenderer = TwoLabelCell;
Note your error message, "Error: skin must be Class or String" vs. the comment in the API reference,
"Note: Do not pass in an instance of a skin class. This may cause unexpected behavior."
06-15-2012 09:16 PM
06-15-2012 09:57 PM - edited 06-16-2012 08:33 PM
The API is looking for a class, not an object, when you set the cellrenderer property.
The cell renderer has a data property which you can inspect to get the label data.
This property gets populated by the list's data provider.
To add your 2nd custom label you can create it as an object property of your data provider
array elements. Something like:
arrMonth.push({label: "January", customlabel: "Custom label text"});
arrMonth.push({label: "February", customlabel: "Custom label text"});
The data provider is an array of object literals value objects (which can be object literals) with
properties you can define. The class expects a property called label, but you can add your own
object properties here.
Then in your cell renderer, you can reference
this.data.customlabel
to get to the custom label data.
06-15-2012 10:00 PM
06-15-2012 10:02 PM
BTW it's been a while since I last wrote a custom cell renderer; it may be that you also need to override
the protected drawLabel() method in the cell renderer to insure your custom label gets properly redrawn
whenever you scroll up and down through a list that is longer than its viewport. IIRC I had to do this to
set a checkbox property within the cell renderer.
06-15-2012 11:22 PM - edited 06-15-2012 11:23 PM
I did what you said, but now I'm getting this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference. at views::TwoLabelCell/init()[/Users/Nathan/Documents/Adobe Flash Builder 4.6/AIRTest/src/views/TwoLabelCell.as:27]
Any ideas?
06-16-2012 09:03 AM
06-16-2012 11:05 AM - edited 06-16-2012 11:14 AM
I've just implemented the overrides to onAdded and onRemoved like this, is it correct?
override protected function onAdded():void {
super.onAdded();
}
override protected function onRemoved():void {
super.onRemoved();
}Here's what's at line 27:
description.text = this.data.secondLabel;
06-16-2012 12:30 PM
Almost:
override protected function onAdded():void
{
super.onAdded();
this.addChild( this.description);
}
override protected function onRemoved():void
{
super.onRemoved();
this.removeChild( this.description);
}
And take it out of the init() function;
You have to test data since it can be called and it be null. I typically:
if( this.data != null && this.data.hasOwnProperty( 'secondLabel' ) )
{
this.description.text = this.data.secondLabel;
}