Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Adobe AIR Development

Reply
Developer
jtegen
Posts: 6,541
Registered: ‎10-27-2010
My Device: HTC One, PlayBook, LE Z10, DE Q10

Re: ScrollPane scrollX in movement

[ Edited ]

You would think it was this easy.  Mine does nothing.  My child container is a QNX List class that I change the height each time a new item is added to it and it scrolls fine when I move it around with the mouse.  The scrollY values are good in reading them when the list moves, but setting the attribute does not move it any.  Obviously, there is something that I might be doing.

 

Here's the code in case someone sees something obviously.  the scrollIndexVisible method is the part in question.

 

package views
{
	import flash.events.MouseEvent;
	
	import mx.core.UIComponent;
	
	import qnx.ui.core.Containment;
	import qnx.ui.data.DataProvider;
	import qnx.ui.events.ListEvent;
	import qnx.ui.events.ScrollEvent;
	import qnx.ui.listClasses.List;
	import qnx.ui.listClasses.ListSelectionMode;
	import qnx.ui.listClasses.ScrollDirection;
	import qnx.ui.listClasses.ScrollPane;
	
	public class ScrollList extends ScrollPane
	{
		public var list :List = new List();
		
		public var edgeColor     : uint = 0x666666;
		public var edgeAlpha     : Number = 1.0;
		public var edgeThickness : int = 1;
		//private var last_selection : int = -1;
		
		//////////////////////////////////////////////////////////////
	public function ScrollList()
	{
		super();
		this.scrollDirection = ScrollDirection.VERTICAL;
		this.containment = Containment.CONTAINED;
		this.list.selectionMode = ListSelectionMode.SINGLE;
		this.list.scrollable = false;
		this.list.dataProvider = new DataProvider( [] );
		this.setScrollContent( this.list );
		//this.list.addEventListener( ListEvent.ITEM_CLICKED, Selection );
		//this.list.addEventListener( MouseEvent.MOUSE_DOWN, MouseDown );
		//this.list.addEventListener( MouseEvent.MOUSE_UP, MouseUp );
		//this.addEventListener( ScrollEvent.SCROLL_BEGIN, StartScroll );
			
		//this.addEventListener(ScrollEvent.SCROLL_MOVE, ScrollMove );
	}
		
		
		///////////////////////////////////////////////////////////////
	public function scrollIndexVisible( index : int ) : void
	{
		var top : int = ( index * this.rowHeight ) - this.scrollY;
			
	
		// above
		if( top < 0 )
		{
			//this.scrollY = 100;
			this.scrollY = index * this.rowHeight;
			//this.update();
		}
		// below
		else if( top > this.height )
		{
			this.scrollY = ( index * this.rowHeight ) - this.height + this.rowHeight;
			//this.update();
		}
	}
		
	
		///////////////////////////////////////////////////////////
	public function get selectedIndex() : int
	{
		return this.list.selectedIndex;
	}
		
		///////////////////////////////////////////////////////////
	public function set selectedIndex( value : int ) : void
	{
		this.list.selectedIndex = value;
	}
		
		///////////////////////////////////////////////////////////
	public function set rowHeight( value : int ) : void
	{
		this.list.rowHeight = value;
	}
		
		///////////////////////////////////////////////////////////
	public function get rowHeight() : int
	{
		return this.list.rowHeight;
	}
		
		////////////////////////////////////////////////////////////////
	public function addItem( item : Object ) : void
	{
		this.list.dataProvider.addItem( item );
		this.list.height = this.list.dataProvider.length * this.list.rowHeight;
	}
		
		//////////////////////////////////////////////////////////
	override protected function draw():void
	{
		super.draw();
			
		this.list.width = this.width;

		this.update();
			
		this.graphics.clear();
		this.graphics.lineStyle( this.edgeThickness, this.edgeColor, this.edgeAlpha );
		this.graphics.drawRect( -this.edgeThickness, -this.edgeThickness, this.width+this.edgeThickness, this.height+this.edgeThickness );
		this.graphics.endFill();
		}
	}
}

 

Developer
studiochris
Posts: 165
Registered: ‎10-26-2010
My Device: BlackBerry® PlayBook™

Re: ScrollPane scrollX in movement

[ Edited ]

Hi John--

 

What's the reason you want to use a ScrollPane as the scrolling mechanism for a List? I don't see what you're trying to accomplish with the ScrollPane that a List itself isn't already capable of handling, except maybe keeping more rendered items in memory and maybe using ScrollPane's scrollbars, which look slightly different.

 

Both scrollX and scrollY for ScrollPane work under regular circumstances. Have you tried moving the scrollY outside of your scrollIndexVisible if statement to see if it works without applying any logic? If it does work that way, it'll be something in the if/else statement. Just glancing, are you sure rowHeight isn't 0? If it is, scrollY would always be 0 based on your if/else statement.

 

 

public function scrollIndexVisible( index : int ) : void
	{

		//assuming this.height = 100 (will never be more than its mask height) & this.scrollY = 25
		var top : int = ( index * 0 ) - 25; // equals -25
			
	
		// above
		if( -25 < 0 ) // always true, so else if never runs
		{
			this.scrollY = index * 0; // equals 0
		}
		// below
		else if( -25 > 100 ) // Will never be true because top is always a negative number... but if it was true, and if the initial comparison is false, which also isn't possible...
		{
			this.scrollY = ( index * 0 ) - 100 + 0; // equals -100 or negative this.height, which bounces scrollY back to 0 since it is less than the minimum scroll value
		}
	}

 

Perhaps try basing the calculations on this.getScrollContent().height or this.list.height.

Developer
jtegen
Posts: 6,541
Registered: ‎10-27-2010
My Device: HTC One, PlayBook, LE Z10, DE Q10

Re: ScrollPane scrollX in movement

Hi Chris:

 

The standard QNX List does not have any attribute to know the scroll offset of the list.  Upon selection of an item in the list, I am poping up another view that needs to be located next to the selected item.  If the items in the list are scrolled, there is no way to know its location relative to the parent container without knowing the scroll amount of the list (to convert to global coordinates).  Additionally, if the selected item is partially above or below the current parent view, I want to move that item so it is in full view to the user. 

 

Yes, the rowHeight is 47.

 

Hard coding an offset did nothing either.

 

It's funny, I can set the scrollY to 50 and then trace it back and it will trace 50.  But nothing moves.  I unselect the item, select it again, and the original scrollY is still there.  It is like I set it and then it gets set back to the original value.

Developer
studiochris
Posts: 165
Registered: ‎10-26-2010
My Device: BlackBerry® PlayBook™

Re: ScrollPane scrollX in movement

[ Edited ]

 

This is a complete shot in the dark guess, but this is my impression of what's happening. Maybe you're running into issues with the cellRenderer pool. Looking at the __drawnItems array of a list, it seems like it starts on the first item that would be visible in context of the Stage and not the list's masked viewport. If this is the case, the height of your list doesn't matter; you'll still only get enough renderers to fill the stage in whichever direction. So, check that array to see if _dataProvider.length == __drawnItems.length. If it is, you can skip the next 2 paragraphs because my theory is wrong (solution after those). If they don't match...
  
You have scrolling turned off for the List itself, but it is inside a ScrollPane that dispatches the very same ScrollEvents that List reacts to. It seems like ScrollPane and List both listen for events from the stage level (because they catch events "through" solid objects). When ScrollPane dispatches ScrollEvent.SCROLL_MOVE, since the List is still listening for those Events (it just doesn't dispatch them for itself), it catches them and the set data method of the cellRenderer is triggered which makes your list  appear to move with its limited renderers, just like it would do on its own.
  
When you set scrollY manually, the ScrollPane's scrollY property is changing and it is scrolled to that position, but it isn't dispatching ScrollEvent.SCROLL_MOVE, so the List's data doesn't change. It has nothing to trigger the data switch and thus update the renderers. From the front end, it looks like the list didn't scroll because it didn't.
  
Solution (or something to maybe spark an idea in your mind):
  
The only solution I see for this is to extend a couple of classes related to List, including List itself.
  
The first to extend is qnx.ui.tween.Scroller which is responsible for the scrolling in the List class (through a protected property List.__scrollMgr).
  
public class MyScroller extends Scroller implements qnx.ui.tween.IScroller
  
In extending this, there are a couple of protected properties that need to be exposed _prevX (the x position of the list content in relation to its mask) and _prevY (same as _prevX, but in the y direction -- this is the important one for you). You could also expose Scroller.mc.x and Scroller.mc.y through your own get and set methods, which should return the same values as _prevX and _prevY.
  
Scroller Constructor: 
  
public function Scroller (mc:DisplayObjectContainer[original is a Sprite], vwidth:Number[viewport width], vheight:Number[viewport height], mwidth:Number[mc width?], mheight:Number[mc height?], vertical:Boolean = false, _scrollThreshold:Number = 20, single:Boolean = true);
Next, extend List. In the constructor, run super(), then loop through the children of List and find the index of __scrollMgr (there are only 3 children, so this should be fast).
 
var scrollerIndex:int;

for(var i:uint = 1; i < this.numChildren; ++i)
{
     if( this.getChildAt( i - 1 ) is IScroller ) //or is Scroller
     {
           this.getChildAt(i - 1).dispose();
           break;
     }
}

 You may also need to loop through the original __scrollMgr before disposing of it to see if the List class adds anything special to it and you'd have to recreate and add those back... or pull the originals from the original __scrollMgr and add them back in the correct order to the new __scrollMgr from the next step.

 

Next recreate __scrollMgr as your extended Scroller class. This will give you access to those once protected and hidden properties.
__scrollMgr = new MyScroller(*parameters*);
this.addChildAt(__scrollMgr, scrollerIndex);
  
To get the Y position of the selected item within your extended List's masked viewport:
 
  1. on the ITEM_CLICKED event, get e.target.selectedIndex or e.target.index and multiply by e.target.rowHeight which is the y position of the list item in what would be the unmasked list (I'll call it itemPosition).
  2. Next, add __scrollMgr._prevY (in your publicly accessible form), which should be a negative number to itemPosition. (You could also use Math.abs to make _prevY positive and then subtract).
  3. The resulting number from #2 is the top coordinate of the selected list item. To get the bottom, if you need it, add rowHeight. 
Now that you know where the top and bottom of the selected item is, you can position your extra element as required.
 
Example:
 
selectedIndex = 9
rowHeight = 120
_prevY = -870

itemTop = top of selected item
itemBottom = bottom of selected item

selectedIndex * rowHeight = 1080
1080 + (-870) = itemTop = 210
210 + rowHeight = itemBottom = 330

//Middle-aligned popup: 

popup.y = list.y + ( ( rowHeight - popup.height) / 2 ) + itemTop;
popup.y = 0 + ( ( 120 - 300) / 2 )  + 210;
popup.y = -90 + 210
popup.y = 120;

 

 

Developer
rhgills
Posts: 39
Registered: ‎01-13-2011
My Device: Not Specified

Re: ScrollPane scrollX in movement

[ Edited ]
for(var i:uint = 1; i < this.numChildren; ++i)
{
     if( this.getChildAt( i - 1 ) is IScroller ) //or is Scroller
     {
           this.getChildAt(i - 1).dispose();
           break;
     }
}	

The above should be:

for(var i:uint = 0; i < this.numChildren; i++)
{
     if( this.getChildAt(i) is IScroller ) //or is Scroller
     {
           this.getChildAt(i).dispose();
           break;
     }

Your code doesn't check all the children.

Developer
agaripian
Posts: 133
Registered: ‎12-02-2010
My Device: Z10 & Dev Alpha C

Re: ScrollPane scrollX in movement

Did anyone ever get this working or implement a custom _scrollmgr to expose the scroll y position?

 

If so can you please share a sample app. I am trying to do the same with a BB10 Qnx Air list.

---------------------------------------------------------------------
Developer of Stocks for Blackberry 10