12-14-2010 01:19 AM
Hi all, I'm extending the qnx.ui.listClasses.CellRenderer for my TileList. I noticed that sometimes this.data would be null in my overridden onAdded() function.
After some testing, I realized if I use a timer to check this.data a few seconds later, it would be populated with the correct data, so it seems that the data binding is happening an instant after the onAdded() function is called.
I'm happy to rely on the timer delay for now, but does anyone have a better solution? Is there another event I should be listening to instead of depending on onAdded() ?
Solved! Go to Solution.
12-14-2010 01:30 AM
hey ryan,
i saw your post in the other thread and have been at it for quite some time since then. i gotta say im stumped. i thought i had cellrenderer's all figured out and then u come along and find this haha. im gonna be spending night trying to nail this anamoly. the same thing happens when you have any sort of list that is larger than the viewable area without scrolling. ill get back to you with any findings good luck to ya!
12-14-2010 01:36 AM
glad that this is validated, was beginning to think i'm the only with the problem =)
yes you described it exactly, it mostly happens to those tiles that are off screen initially.
btw J. Rab you seem to be on the forum 24hrs! haha
12-14-2010 01:45 AM - edited 12-14-2010 01:46 AM
My hackish way around the problem:
package {
import qnx.ui.listClasses.CellRenderer;
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
public class MyCellRenderer extends CellRenderer
{
public function MyCellRenderer(){
super();
}
override protected function onAdded():void {
super.onAdded();
// your code here, addChild()'s etc.
var me:MyCellRenderer = this;
var timer:Timer;
if( me.data == null ){
trace('MyCellRenderer.onAdded: me.data is null');
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER,nextStep);
timer.start();
}else{
nextStep();
}
function nextStep(evt:TimerEvent=null):void{
if( me.data == null ){
trace('MyCellRenderer.onAdded: me.data is still null');
return;
}else{
if (timer){
timer.stop();
timer.removeEventListener(TimerEvent.TIMER,nextSte p);
timer = null;
}
}
// Do the normal stuff here
}
}
}
}
Edit: fixed some typos
12-14-2010 01:54 AM
hey,
stuff like this makes me forget all about sleep haha clearly i dont sleep much at all !
ok so i think i got the fix for it. instead of just relying on the onAdded() method we have to look into the drawLabel() method as well. in the contstructor this time we make the new object checkBox where our customization starts later on with so we dont have duplicates of that object created every time the drawLabel method is called. instead of doing the heavy lifting in the onAdded method we are just going to remove the label object that shows up via the cell renderer. after that when the drawLabel() method is called thats when we do our customization. mine includes a checkbox just to test it out. then we finally remove our object as usual in the onRemoved() method.
here's the updated code for the renderer:
package
{
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextFieldAutoSize;
import qnx.ui.buttons.CheckBox;
import qnx.ui.buttons.LabelPlacement;
import qnx.ui.listClasses.AlternatingCellRenderer;
import qnx.ui.listClasses.List;
import qnx.ui.text.Label;
public class MyCustomCellRenderer extends AlternatingCellRenderer
{
/*
* Place the object out here so that other methods can
* access it
*/
private var newCheckBox:CheckBox;
public function MyCustomCellRenderer()
{
super();
/*
* Add the checkbox here so we dont keep re-adding a check box
* whenever the onAdded method is called. other wise there
* would be a lot of objects for checkbox
*/
newCheckBox = new CheckBox();
}
override protected function onAdded():void
{
super.onAdded();
/*
* Do not want to use the label object at all. we want
* to fully customize our cell renderer. for some reason
* the label object is not considered a child object
* when the drawLabel method is called so we must
* removed it in this method where it is considered a
* child object
*/
removeChild(label);
}
override protected function drawLabel():void
{
if (this.data)
{
/*
* Sometimes this function is called prematurely when there
* is no data object available and it is null so we only
* do our custom label when there is a data object available
*/
newCheckBox.width = 500;
newCheckBox.label = this.data.label;
newCheckBox.labelPadding = 10;
newCheckBox.labelPlacement = LabelPlacement.RIGHT;
newCheckBox.setPosition(10,10);
addChild(newCheckBox);
}
}
override protected function onRemoved():void
{
super.onRemoved();
/*
* Remember to remove the checkbox object
*/
removeChild(newCheckBox);
}
}
}
i've tested this on a one column list and also a tilelist and its functioning at 100%. let me know if i've missed something. glad you brought this up! good luck!
12-14-2010 06:31 AM
drawLabel() eh? Strange thing is I tried this previously but data was null as well. Will give it a go later and let you know the result.
12-14-2010 07:46 AM
hey ryan,
yeah it will come up as null thats why you must do a check for the data object to make sure it is not null and then go ahead and get it drawn.
12-14-2010 09:02 AM
Cool moving my code into drawLabel works indeed.
I guess that means now you really have CellRenderer figured out =)
12-14-2010 09:08 AM
haha yeah until you find some other way to break it! but i'll be ready ![]()
12-14-2010 10:58 AM
Be careful with drawLabel if your list ever will get resized (like during an orientation change). It will get called each time the parent list size changes. So if you're adding a control there, it would get added multiple times, so you may want to check to see if it is already added before you try to add it.