|
Considerations when using scroll bars in a mobile applicationTypically, if content takes up more than the visible area
of the screen, the application displays scroll bars. Use the Scroller control
to add scroll bars to your application. Some components, such as
the Spark List control, support scrolling without the need of using
the Scroller component. For more information, see Scrolling
Spark containers.
The hit area of a scroll bar is the area of the screen in which
you position the mouse to perform a scroll. In a desktop or browser-based
application, the hit area is the visible area of the scroll bar.
In a mobile application, scroll bars are hidden even when the content
is larger than the visible area of the screen. Hiding the scroll
bars enables the application to use the full width and height of
the screen.
A mobile application must differentiate between when the user
interacts with a control, such as by selecting a Button control,
from when the user wants to scroll. One consideration with scroll
bars in a mobile application is that Flex components often change
their appearance in response to a user interaction.
For example, when the user presses a Button control,
the button changes its appearance to indicate that it is selected.
When the user releases the button, the button changes its appearance
back to the deselected state. However, when scrolling, if the user
touches the screen over the Button, you do not want the button to
change its appearance.
Adobe engineer Steven Shongrunden shows an example
of working with scroll bars in Saving scroll position between views in a
mobile Flex Application.
Scrolling termsThe following terms are used to describe scrolling in a
mobile application:
- Content
- For a scrollable component, such as a Group container or
List control, the entire area of the component. Depending on the
screen size and application layout, only a subset of the content
might be visible.
- Viewport
- The subset of the content area of a component that is currently visible.
- Drag
- A touch gesture that occurs when the user touches a scrollable
area and then moves their finger so that the content moves along
with the gesture.
- Velocity
- The rate and direction of movement of a drag gesture. Measured
in pixels-per-millisecond along the X and Y axis.
- Throw
- A drag gesture where the user lifts their finger once the
drag gesture has reached a certain velocity, and the scrollable
content continues to move.
- Bounce
- A drag or throw gesture can move the viewport of a scrollable component
outside the component’s content. The viewport then displays an empty
area. When you release your finger, or the velocity of a throw reaches
zero, the viewport bounces back to its resting point with the viewport
filled with content. The movement slows as the viewport reaches
the resting point so that it comes to a smooth stop.
Scrolling modes in a mobile applicationScrollable components, such as List and Scroller, support
different types of scrolling based on the setting of the pageScrollingEnabled and scrollSnappingMode properties
of the component. These properties are only valid when the interactionMode style
is set to touch.
The following table describes the scrolling modes:
pageScrollingEnabled
|
scrollSnappingMode
|
Mode
|
false (default)
|
none (default)
|
By default, scrolling is pixel-based. The
final scroll position is any pixel location based on the drag or
throw gesture. For example, you scroll a List control. Scrolling
ends when you lift your finger even if a partial List item is visible.
|
false
|
leadingEdge, center, trailingEdge
|
Scrolling is pixel-based, but the content
snaps to a final position based on the value of scrollSnappingMode.
For
example, you scroll a List vertically with scrollSnappingMode set
to a value of leadingEdge. The List control snaps
to a final scroll position where the top list element is aligned
to the top of the list.
|
true
|
none
|
Scrolling is page-based. The size of the
viewport of the scrollable component determines the size of the
page. You can only scroll a single page at a time, regardless of
the gesture.
Scroll at least 50% of the visible area of the
component to cause the page to scroll to the next page. If you scroll
less than 50%, the component remains on the current page. Alternatively,
if the velocity of the scroll is high enough, the next page displays.
If the velocity is not high enough, the component remains on the
current page.
When content size is not an exact multiple
of the viewport size, additional padding is added to the last page
to make it fit completely in the viewport.
|
true
|
leadingEdge, center, trailingEdge
|
Scrolling is page-based, but the component
snaps to a final position based on the value of scrollSnappingMode.
To guarantee that the snapping mode is respected, the scrolling
distance is not always exactly equal to the size of the page.
|
Scrolling examples in a mobile applicationIn the following example, you use a Scroller component
to wrap a Group container in a mobile application. The Group container
has as its child an Image control containing a large image. By wrapping
the Group container in the Scroller, you can scroll the image:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\mobile\views\SparkMobilePixelScrollerHomeView.mxml -->
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<s:Scroller width="200" height="200">
<s:Group>
<s:Image width="300" height="400"
source="@Embed(source='../assets/logo.jpg')"/>
</s:Group>
</s:Scroller>
</s:View>
Notice that in this example, you omit any settings for of the pageScrollingEnabled and scrollSnappingMode properties. Therefore,
this example uses the default pixel scrolling mode, and you can
scroll to any pixel location in the image.
The next example shows a List control that sets the pageScrollingEnabled and scrollSnappingMode properties:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\mobile\views\SparkMobilePageScrollHomeView.mxml -->
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="Adobe Product List">
<s:layout>
<s:VerticalLayout paddingTop="10" paddingLeft="10" paddingRight="10"/>
</s:layout>
<fx:Script>
<![CDATA[
import spark.events.IndexChangeEvent;
protected function myList_changeHandler(event:IndexChangeEvent):void {
navigator.pushView(views.ProductPricelView,myList.selectedItem);
}
]]>
</fx:Script>
<s:List id="myList" labelField="Product"
height="200" width="100%"
borderVisible="true"
scrollSnappingMode="leadingEdge"
pageScrollingEnabled="true"
change="myList_changeHandler(event);">
<s:dataProvider>
<s:ArrayCollection>
<fx:Object Product="Adobe AIR" Price="11.99"/>
<fx:Object Product="Adobe BlazeDS" Price="11.99"/>
<fx:Object Product="Adobe ColdFusion" Price="11.99"/>
<fx:Object Product="Adobe Flash Player" Price="11.99"/>
<fx:Object Product="Adobe Flex" Price="Free"/>
<fx:Object Product="Adobe LiveCycleDS" Price="11.99"/>
<fx:Object Product="Adobe LiveCycle ES2" Price="11.99"/>
<fx:Object Product="Open Source Media Framework"/>
<fx:Object Product="Adobe Photoshop" Price="11.99"/>
<fx:Object Product="Adobe Illustrator" Price="11.99"/>
<fx:Object Product="Adobe Reader" Price="11.99"/>
<fx:Object Product="Adobe Acrobat" Price="11.99"/>
<fx:Object Product="Adobe InDesign" Price="Free"/>
<fx:Object Product="Adobe Connect" Price="11.99"/>
<fx:Object Product="Adobe Dreamweaver" Price="11.99"/>
<fx:Object Product="Open Framemaker"/>
</s:ArrayCollection>
</s:dataProvider>
</s:List>
</s:View>
This example uses page scrolling with a snap setting of leadingEdge. Therefore,
as you scroll the List, the List can scroll a single page at a time.
On a change of page, the control snaps to a final scroll position
where the top list element is aligned to the top of the list.
Scrolling considerations with StageTextStageText lets you use native text inputs in a mobile application,
rather than using the standard text field controls. However, a scrollable
container cannot hold a text input control, such as the TextInput
or Text Area control, that uses StageText. Therefore, to use a text
input control in a scrollable container, reskin the control so it
does not use StageText.
Flex ships with skins for the TextInput and TextArea controls
that do not rely on StageText. Use the following skins with these
controls in a scrollable container:
The following example shows a View container that uses a TextInput
and TextArea control in a scrollable container:
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\mobile\SparkMobileStageTextScrollHomeView.mxml -->
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="HomeView">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<!-- Create CSS class selectors that reference the skins
that do not rely on StageText. -->
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
.myTextInputStyle {
skinClass: ClassReference("spark.skins.mobile.TextInputSkin");
}
.myTextAreaStyle {
skinClass: ClassReference("spark.skins.mobile.TextAreaSkin");
}
</fx:Style>
<!-- Apply the class selectors to the TextInput and TextArea controls. -->
<s:Scroller width="100%" height="100%">
<s:VGroup height="250" width="100%"
paddingTop="10" paddingLeft="5" paddingRight="10">
<s:HGroup verticalAlign="middle">
<s:Label text="Text Input 1: "
fontWeight="bold"/>
<s:TextInput width="225"
styleName="myTextInputStyle"/>
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label text="Text Input 2: "
fontWeight="bold"/>
<s:TextInput width="225"
styleName="myTextInputStyle"/>
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label text="Text Input 3: "
fontWeight="bold"/>
<s:TextInput width="225"
styleName="myTextInputStyle"/>
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label text="Text Input 4: "
fontWeight="bold"/>
<s:TextInput width="225"
styleName="myTextInputStyle"/>
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label text="TextArea 1: "
fontWeight="bold"/>
<s:TextArea width="225" height="100"
styleName="myTextAreaStyle "/>
</s:HGroup>
</s:VGroup>
</s:Scroller>
</s:View>
Events and scroll barsFlex components rely on events to indicate that a user
interaction has occurred. In response to the user interaction, the
component can then change its appearance, or perform some other
action.
Application developers rely on events to handle user interaction.
For example, you typically use the Button control’s click event
to run an event handler in response to the user selecting the button.
Use the List control’s change event to run an event
handler when the user selects an item in the List.
The Flex scrolling mechanism relies on the mouseDown event.
That means the scrolling mechanism listens for mouseDown events
to determine if a scroll operation is to be initiated.
Interpret a user gesture as a scroll operationAn application consists of multiple Button controls in
a scrollable container:
Use your finger to press a Button control. The button
dispatches a mouseDown event.
Flex delays responding to the user interaction for a predefined
time period. The delay period ensures that the user is selecting
the button and not attempting to scroll the screen.
If, during
the delay period, you move your finger more than a predefined amount,
Flex interprets that gesture as a scroll action. The distance that
you have to move your finger for the gesture to be interpreted as
a scroll is approximately 0.08 inches. This distance corresponds
to about 20 pixels on a 252 DPI device.
Because you moved
your finger before the delay period expires, the Button control
never recognizes the interaction. The button never dispatches an event
or changes its appearance.
After the delay period expires, the Button control recognizes
the user interaction. The button changes its appearance to indicate
that it has been selected.
Use the touchDelay property
of the control to configure the duration of the delay. The default
value is 100 ms. If you set the touchDelay property
to 0, there is no delay and scrolling is initiated immediately.
After the delay period expires and Flex has dispatched the
mouse events, you then move your finger more than 20 pixels. The
Button control returns to the normal state, and the scroll action
is initiated.
In this case, the button changed its appearance
because the delay period expired. However, once you move your finger
more than 20 pixels, even after the delay period expires, Flex interprets
the gesture as a scroll action.
Note: Flex components support many different types of events besides
mouse events. When working with components, you decide how your
application reacts to these events. At the time of the mouseDown event,
the intended behavior of the user is ambiguous. The user could intend
to interact with the component or they could scroll. Because of
this ambiguity, Adobe recommends listening for click or mouseUp events
instead of the mouseDown event.
Handle scroll events in a mobile applicationTo signal the beginning of a scroll operation, the component
that dispatches the mouseDown event dispatches
a bubbling touchInteractionStarting event. If that
event is not canceled, the component dispatches a bubbling touchInteractionStart event.
When a component detects a touchInteractionStart event,
it must not attempt to respond to the user gesture. For example,
when a Button control detects a touchInteractionStart event,
it turns off any visual indicators that it set based on the initial mouseDown event.
If a component does not want to allow the scroll to start, the
component can call the preventDefault() method
in the event handler for the touchInteractionStarting event.
When the scroll operation completes, the component that dispatches
the mouseDown event dispatches a bubbling touchInteractionEnd event.
Scroll behavior based on the initial touch pointThe following table describes the way scrolling
is handled based on the location of the initial touch point:
Selected item
|
Behavior
|
Empty space,
noneditable text,
unselectable
text
|
No component recognizes the gesture. The
Scroller waits for the user to move the touch point more than 20
pixels before initiating scrolling.
|
Item in a List control
|
After the delay period, the item renderer
for the selected item changes the display to the selected state.
However, if at any time the user moves more than 20 pixels, then
the item changes its appearance to the normal state and scrolling
is initiated.
|
Button,
CheckBox,
RadioButton,
DropDownList
|
After the delay period expires, show its mouseDown state.
However, if the user moves the touch point more than 20 pixels,
then the control changes its appearance to the normal state and
initiates scrolling.
|
Button component inside a List item renderer
|
The item renderer never highlights. The
Button or the Scroller handles the gesture, the same as the normal
Button case.
|
|
|
|