A Simpler Button Scroll


For one of my projects, a client asked for vertical list with up/down buttons in place of scrollbars with smooth scrolling.
I found a few classes that gave a partial solution, but some gave choppy results, and for others I didn’t like their long and complex code. After a lot of tryouts I came across Doug McCune’s ButtonScrollingCanvas, which came close to what I needed.

The ButtonScrollingCanvas container is one of many flex controls in the excellent open source flexlib library – a must for any serious flex developer. It is a container component that uses buttons placed over the edges of the container to do the scrolling of its children, and the buttons can be fully skinned.

Inspired by the flexlib code, I decided to write my own container based on the same ideas, only with a slightly different implementation.


This resulted in ButtonScrollLite, a container suitable for games and touch displays, where you just tap the arrows to flip through content of any kind.  Its simple to use – just place any child elements inside it in the mxml and it works right out of the box. The arrow buttons are fully sinkable, so anyone can decide to roll their own buttons.

Properties:

  • direction  – (horizontal|vertical) default is vertical
  • scrollSize  – the size (in pixels) to scroll in a single step- default is 10. Typically you want to set it to the size of one item in your list, although they can be in different sizes.

The bulk of the code is in 2 functions: createChildren and updateDisplayList.

 override protected function createChildren():void
        {
            super.createChildren();
 
            // We have 4 buttons for each side of the conainter
	    	leftButton = new Button();
		rightButton = new Button();
		upButton = new Button();
		downButton = new Button();
 
		leftButton.styleName = getStyle("leftButtonStyleName");
		rightButton.styleName = getStyle("rightButtonStyleName");
		upButton.styleName = getStyle("upButtonStyleName");
		downButton.styleName = getStyle("downButtonStyleName");
 
		// this is the main canvas component, we tell it to
		// never show the scrollbars since we're controlling them
		// on our own
		innerCanvas = new Canvas();
		innerCanvas.document = this.document;
		innerCanvas.horizontalScrollPolicy = ScrollPolicy.OFF;
		innerCanvas.verticalScrollPolicy = ScrollPolicy.OFF;
 
		...
	}

First, createChildren sets up the four buttons and their styles (so they are skinnable). It also creates the inner canvas, that will hold the actual contents, and turns off the scroll policy so that no scrollbars will show.

All the rest is handled in updateDisplayList:

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            super.updateDisplayList(unscaledWidth,unscaledHeight);
 
            ...
            var btnSpace:Number = btnHeight + _buttonGap;
 
            if (_direction == VERTICAL) {
            	innerCanvas.setActualSize(unscaledWidth,
            	            	      unscaledHeight - btnSpace*2);
            	innerCanvas.move(0, btnSpace);
            }
            else {
            	btnSpace = btnWidth + _buttonGap;
            	innerCanvas.setActualSize(unscaledWidth - btnSpace*2,
            	            	     unscaledHeight);
            	innerCanvas.move(btnSpace, 0);
            }
 
	    positionButtons(unscaledWidth, unscaledHeight);
            callLater(enableOrDisableButtons);
        }

The buttons and inner canvas are sized and placed in their position, depending on the layout direction (vertical or horizontal).

To perform the smooth scroll, I used a tweener (Greensock TweenLite) – this saved me the need to use timer events or enter frame, and the easing function gives it a more natural motion.

Feel free to use the class in any apps,  modify it , or use new skins.

2 thoughts on “A Simpler Button Scroll

Comments are closed.