Working with Touch in Flex

5

Category : Flex, Scrolling, Touch Interactions

At Adobe MAX, this year, I spoke at the 360|MAX conference about touch events in Flex. Some of the topics I talked about are:
 

  • Touch events and MultiTouch.inputMode in Flash
  • Flex touch basics
  • Why touch is difficult
  • How Flex components coordinate to interpret and react to ambiguous touch interactions
  • How to write your own code to deal with touch interactions and coordinate with other components appropriately

 
As part of that, I showed off two examples:
 

  1. How to create a checkmark item renderer to distinguish between down and selected in a touch environment
  2. How to create an item renderer that responds to a swipe gesture and shows a delete button (similar to iPhone’s email application)

 
Please help yourselves to the PowerPoint presentation (PPT | PDF) and the Flash Builder project with both applications. You can also play around with the first application below, and let me know if you have any questions about this. More information around touch interactions can also be found on the Mobile List, Scroller and Touch Specification.

AutoScrolling for Flex Tree

52

Category : Flex, Scrolling, Tree

We’ve been mostly fixing bugs on the SDK as we prepare for the release for MAX, and one of the bugs that was assigned to me was SDK-9645, https://bugs.adobe.com/jira/browse/SDK-9645.

The problem was that in a Tree (and other List-based components), when you set the horizontalScrollPolicy to auto, the scrollbars actually don’t come out when they should. This seems like a bug at first, but we did this by design for performance reasons. In order to display the scrollbar properly, we need to measure the width of all the items (on-screen or not) and this would just take too much time to do by default. So instead, to get a scrollbar to show up, you need to set maxHorizontalScrollPosition, which is how much the user can scroll.

However, this can be annoying, especially as you might not know how big your data is. So I’ve created a simple component that extends Tree that measures the width of all the renderers so the scrollbars are calculated correctly.

In order to do this, in updateDisplayList, which is called whenever we need to redraw, I call measureWidthOfItems, which calculates the max width for all the item renderers. This means that redrawing takes some more time and is a little slower. Anyways, here’s the code:

package{
    import flash.events.Event;
 
    import mx.controls.Tree;
    import mx.core.mx_internal;
    import mx.core.ScrollPolicy;
    import mx.events.TreeEvent;
 
    public class AutoSizeTree extends Tree
    {
         public function AutoSizeTree(){
              super();
              horizontalScrollPolicy = ScrollPolicy.AUTO;
         }
 
         // we need to override maxHorizontalScrollPosition because setting
         // Tree's maxHorizontalScrollPosition adds an indent value to it,
         // which we don't need as measureWidthOfItems seems to return exactly
         // what we need.  Not only that, but getIndent() seems to be broken
         // anyways (SDK-12578).
 
         // I hate using mx_internal stuff, but we can't do
         // super.super.maxHorizontalScrollPosition in AS 3, so we have to
         // emulate it.
         override public function get maxHorizontalScrollPosition():Number
         {
              if (isNaN(mx_internal::_maxHorizontalScrollPosition))
                  return 0;
 
              return mx_internal::_maxHorizontalScrollPosition;
         }
 
         override public function set maxHorizontalScrollPosition(value:Number):void
         {
              mx_internal::_maxHorizontalScrollPosition = value;
              dispatchEvent(new Event("maxHorizontalScrollPositionChanged"));
 
              scrollAreaChanged = true;
              invalidateDisplayList();
         }
 
         override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
         {
              // we call measureWidthOfItems to get the max width of the item renderers.
              // then we see how much space we need to scroll, setting maxHorizontalScrollPosition appropriately
              var diffWidth:Number = measureWidthOfItems(0,0) - (unscaledWidth - viewMetrics.left - viewMetrics.right);
 
              if (diffWidth <= 0)
                  maxHorizontalScrollPosition = NaN;
              else
                  maxHorizontalScrollPosition = diffWidth;
 
              super.updateDisplayList(unscaledWidth, unscaledHeight);
         }
    }
}

 

[Code updated 3/20/09]

Because we’re doing this extra calculation, it means for a Tree with a lot of items, we may become slower. There are better ways of doing the same thing besides measuring every single renderer in updateDisplayList(), but this is definitely the easiest way. If performance is really a problem with this, let me know, and I’ll try to come up with something a little smarter.

Below is an example, with the top one being the new AutoSizeTree component and the bottom one being the old one. Notice how the top is a little slower when resizing with an effect (this shows it’s a little slower when laying out in general) when lots of the items are open.

[Post updated on 3/20/09 to fix an issue: SDK-18499]