Menu

ToggleSwitch

SourceForge Editorial Staff

ToggleSwitch - Functional and Design Specification


\

Summary and Background

ToggleSwitch is a variation of ToggleButton that has become popular on mobile and tablet devices. The ToggleSwitch is binary (on/off, selected/unselected, etc) like ToggleButton, but behaves similarly to a physical switch that slides between an on and off position. ToggleSwitch defines the path of movement as the track, and the moving content as the thumb. Like a slider, ToggleSwitch adds the ability to drag the thumb along the track between positions. On release, the thumb will snap to the closest of the on or off positions.

Exposing the toggle control as a two position switch can provide some UI benefits. The two-state nature of the control, as well as its current state, are both simple to grasp from the component's appearance. The dragging behavior also makes the component highly interactive for touch-based devices.

\

Usage Scenarios

As an interactive toggling control, ToggleSwitch is most often used in "On/Off"-like controls, particularly in settings panels. The component originated on mobile devices, and is currently most often used on those devices (rather than on desktop). Some users will be satisfied with the default skin, while others may want to create their own.

In Flash Builder, users should interact with this component the same as any other skinnable component. They can use the component with its default skin, or they can go through the process of developing their own custom skin. There should not be any need for custom tooling for this component.

\

Detailed Description

ToggleSwitch is a subclass of ToggleButtonBase, with some interactions similar to HSlider. Like ToggleButton, it can be selected or unselected, and has the combination of (up, over, down, disabled) and (not selected, selected) states. Similar to HSlider, the thumb's position is controlled entirely by the component. At runtime, it sits at one side of the track in the selected set of states and the opposite side in the unselected set of states. Clicking on the component will switch the component from selected to unselected, and move the thumb to its corresponding position. Using the drag gesture on the component will move the thumb along the track. Upon release, the thumb will move to whichever end of the track it is closest to and switch to the appropriate selected state.

There are 3 main ToggleSwitch variations. It is possible to create any of these using a skin for ToggleSwitch.

  1. Static background

The labels remain fixed relative to the track, and the thumb moves to cover them.

  1. Sliding background

The labels (and background) are part of the moving content. A clipping mask hides the content outside the track.

  1. Dynamic label

The on/off label is on the thumb and changes to reflect the current state.

The most important pieces of a ToggleSwitch skin are the thumb and track. The thumb is the content that moves in response to user interaction. The track determines the horizontal path along which the thumb should move. The thumb's left visual bound will line up with the track's left visual bound at one extreme, and the thumb's right visual bound will line up with the track's right visual bound at the other extreme. This behavior is similar to HSlider. If part of the thumb (such as on/off labels in the second variation) should move outside the track, it should be placed outside the visual bounds of the thumb. In such a case, a clipping mask should be used to hide content currently outside the track. The skin may also contain several different labels, such as the selected and unselected labels (the On/Off labels in the first two variations), or a more general label for the component (as in the third variation).

The ToggleSwitch controls the position of the thumb, not the skin. In a left-to-right layout direction, the thumb will sit at the left of the track when the ToggleSwitch is not selected, and at the right of the track when selected. The user can interact with the component by clicking or dragging . Dragging will move the thumb horizontally along the track, and upon release the component will animate the thumb moving to the closest end of the track. Clicking will animate the thumb moving to the opposite end of the track. The thumb will animate based on the slideDuration style, similar to HSlider. The ToggleSwitch selection will change when the thumb finishes animating.

Some key points:

  • Click and drag interactions apply to the entire component. Dragging anywhere on the component will move the thumb. Clicking anywhere on the component will toggle the value of selected.
  • ToggleSwitch will have "over" states as a descendant of ToggleButtonBase, but will not enter these states on a mobile device.

\

API Description

ToggleSwitch.as

package spark.components
{

    import mx.core.IVisualElement;

    import spark.components.supportClasses.ToggleButtonBase;

    /**

     *  Color applied to highlight the selected side of the ToggleSwitch skin
     *
     *  @default #3f7fba
     */
    <a href="Style%28name%3D%26quot%3BaccentColor%26quot%3B%2C%20type%3D%26quot%3Buint%26quot%3B%2C%20format%3D%26quot%3BColor%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%29">Style(name="accentColor", type="uint", format="Color", inherit="yes")</a>

    /**

     *  Duration in milliseconds for a sliding animation
     *  moving the thumb across the entire track.
     *  This duration is for an animation that covers the entire distance of the
     *  track; smaller distances will use a proportionally smaller duration.
     *
     *  @default 125
     */
    <a href="Style%28name%3D%26quot%3BslideDuration%26quot%3B%2C%20type%3D%26quot%3BNumber%26quot%3B%2C%20format%3D%26quot%3BTime%26quot%3B%2C%20inherit%3D%26quot%3Bno%26quot%3B%29">Style(name="slideDuration", type="Number", format="Time", inherit="no")</a>

    /**

     *  Color of text shadows.
     *
     *  @default 0x000000
     */
    <a href="Style%28name%3D%26quot%3BtextShadowColor%26quot%3B%2C%20type%3D%26quot%3Buint%26quot%3B%2C%20format%3D%26quot%3BColor%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%2C%20theme%3D%26quot%3Bmobile%26quot%3B%29">Style(name="textShadowColor", type="uint", format="Color", inherit="yes", theme="mobile")</a>

    /**

     *  Alpha of text shadows.
     *
     *  @default 0.65
     */
    <a href="Style%28name%3D%26quot%3BtextShadowAlpha%26quot%3B%2C%20type%3D%26quot%3BNumber%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%2C%20minValue%3D%26quot%3B0.0%26quot%3B%2C%20maxValue%3D%26quot%3B1.0%26quot%3B%2C%20theme%3D%26quot%3Bmobile%26quot%3B%29">Style(name="textShadowAlpha", type="Number", inherit="yes", minValue="0.0", maxValue="1.0", theme="mobile")</a>


    <a href="Exclude%28name%3D%26quot%3BtextAlign%26quot%3B%2C%20kind%3D%26quot%3Bstyle%26quot%3B%29">Exclude(name="textAlign", kind="style")</a>

    /**

     *  The Spark ToggleSwitch component is a component that can flip between
     *  a selected and non selected state. The ToggleSwitch has a <code>thumb</code>
     *  skin part that moves between the two ends of the <code>track</code> skin part,
     *  similar to a Spark <code>Slider</code>.
     *
     *  Clicking on the component will flip it from non-selected to selected,
     *  and vice-versa. A user can also drag the thumb along the track. When released,
     *  the thumb will move to the closest end of the track, and the <code>ToggleSwitch</code>
     *  will change to be either selected or non-selected, according to the thumb's
     *  position.
     *
     *  @see spark.components.ToggleButton
     *  @see spark.components.HSlider
     **/
    public class ToggleSwitch extends ToggleButtonBase
    {

        //--------------------------------------------------------------------------
        //
        //  Skin Parts
        //
        //--------------------------------------------------------------------------

        <a href="SkinPart%28required%3D%26quot%3Bfalse%26quot%3B%29">SkinPart(required="false")</a>

        /**

         *  A skin part that defines an IVisualElement
         *  that can be dragged along the track, causing an increase or
         *  decrease the <code>value</code> property. When not being
         *  dragged, the thumb will be at one end of the track when not
         *  selected, and the other when selected.
         */
        public var thumb:IVisualElement;

        <a href="SkinPart%28required%3D%26quot%3Bfalse%26quot%3B%29">SkinPart(required="false")</a>

        /**

         *  A skin part that defines the path along which
         *  the thumb moves.
         */
        public var track:IVisualElement;

        //--------------------------------------------------------------------------
        //
        //  Properties
        //
        //--------------------------------------------------------------------------

        <a href="Bindable%28event%3D%26quot%3BthumbPositionChanged%26quot%3B%29">Bindable(event="thumbPositionChanged")</a>

        /**

         *  A number between 0 and 1 representing the thumb's
         *  current position on the track.
         **/
        public function get thumbPosition():Number;

}

ToggleSwitchSkin.as

package spark.skins.mobile
{
/**

 *  ActionScript-based skin for ToggleSwitch. The colors of the component can
 *  be customized using styles. This class is responsible for most of the
 *  graphics drawing, with some additional fxg assets.
 */
public class ToggleSwitchSkin extends MobileSkin
{
    //----------------------------------------------------------------------------------------------
    //
    //  Constructor
    //
    //----------------------------------------------------------------------------------------------

    /**

     *  Constructor
     **/
    public function ToggleSwitchSkin();

    //----------------------------------------------------------------------------------------------
    //
    //  Variables
    //
    //----------------------------------------------------------------------------------------------

    /**

     *  The width used to draw the thumb skin part
     */
    protected var layoutThumbWidth:Number;

    /**

     *  The height used to draw the thumb skin part
     */
    protected var layoutThumbHeight:Number;

    /**

     *  The size of the ellipse to use for thumb and track corners
     */
    protected var layoutCornerEllipseSize:Number;

    /**

     * The size of the border outlining the component
    */
    protected var layoutBorderSize:Number;

    /**

     *  The stroke weight outlining the component
     */
    protected var layoutOuterStrokeWeight:Number;

    /**

     * The padding between the labels and the thumb
     */
    protected var layoutInnerPadding:Number;

    /**

     * The padding between the labels and the edge of the track
     */
    protected var layoutOuterPadding:Number;

    /**

     * The offset between a label and its shadow
     */
    protected var layoutTextShadowOffset:Number;

    /**

     *  The label for the selected side of the component.
     *  Exposed for styling.
     */
    public var selectedLabelDisplay:LabelDisplayComponent;

    /**

     *  The label for the unselected side of the component.
     *  Exposed for styling.
     */
    public var unselectedLabelDisplay:LabelDisplayComponent;

    //----------------------------------------------------------------------------------------------
    //
    //  Properties
    //
    //----------------------------------------------------------------------------------------------

    /**

     *  The text of the label showing when the component is selected.
     *  Subclasses can override this to customize the selected label.
     */
    protected function get selectedLabel():String;
    protected function set selectedLabel(value:String):void;

    /**

     *  The text of the label showing when the component is not selected.
     *  Subclasses can override this to customize the unselected label.
     */
    protected function get unselectedLabel():String;
    protected function set unselectedLabel(value:String):void;
}
}

/**

 *  Internal component that holds StyleableTextFields to produce a drop shadow effect.
 *  Combines label and shadow into a single component to allow proper styling.
 */
class LabelDisplayComponent extends UIComponent implements IDisplayText {}

\

B Features

  1. Adding an additional skin part to more easily support content that slides along with the thumb.
  2. Adding left and right icon skin parts.
  3. Adding non-horizontal sliding switches.
  4. Creating default desktop skins.

\

Examples and Usage

Main.mxml

...
<s:ToggleSwitch skinClass="ToggleSwitchSkin" change="changeHandler(event)"/>
...

ToggleSwitchSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:mx="library://ns.adobe.com/flex/mx">
    <!-- host component -->
    <fx:Metadata>
        <a href="HostComponent%28%26quot%3Bspark.components.ToggleSwitch%26quot%3B%29">HostComponent("spark.components.ToggleSwitch")</a>
    </fx:Metadata>

    <fx:Declarations>
        <s:SolidColor id="lightGrey" color="0xcccccc"/>
        <s:SolidColor id="grey" color="0x999999"/>
        <s:SolidColor id="darkGrey" color="0x808080"/>
    </fx:Declarations>

    <!-- states -->
    <s:states>
        <s:State name="disabledAndSelected" />
        <s:State name="downAndSelected" />
        <s:State name="overAndSelected" />
        <s:State name="upAndSelected" />
        <s:State name="disabled" />
        <s:State name="down" />
        <s:State name="over" />
        <s:State name="up" />
    </s:states>

    <s:Group width="200" height="50" horizontalCenter="0" verticalCenter="0">
        <s:Rect id="track" width="200" height="50" fill="{darkGrey}"/>
        <s:Label id="selectedLabelDisplay" text="ON" left="0" right="100" top="0" bottom="0"
                 textAlign="center" verticalAlign="middle"/>
        <s:Label id="unselectedLabelDisplay" text="OFF" left="100" right="0" top="0" bottom="0"
                 textAlign="center" verticalAlign="middle"/>
    </s:Group>
    <s:Rect id="thumb" width="100" height="50" fill="{lightGrey}"
        fill.down="{grey}" fill.downAndSelected="{grey}"/>
</s:Skin>

\

Additional Implementation Details

ToggleSwitch will be be part of mobilecomponents.swc

The default toggle switch skin will contain two protected String members "selectedLabel" and "unselectedLabel". Subclasses can override or set these to change the class labels. The skin will expose "selectedLabelDisplay" and "unselectedLabelDisplay" IDs for styling.

\

Compiler Work

None

\

Cross-Form-Factor Considerations

This feature will initially be targeted at mobile devices, with a set of mobile skins.

Desktop use will not be fully supported until additional desktop skins are made.

\

Cross-Platform Considerations

None

\

Backwards Compatibility

Syntax changes

None

Behavior

None

Warnings/Deprecation

None

\

Accessibility

ToggleSwitch will inherit ToggleButtonBase's accessibility implementation.

\

Performance

Animation and events must be responsive to user input on mobile devices.

\

Globalization

The labels may contain localized text.

\

Localization

ToggleSwitch can be mirrored using the layoutDirection style.

\

Issues and Recommendations

  1. Should ToggleSwitch support non-horizontal sliding?
    1. No. ToggleSwitch will initially support only the horizontal sliding case.
  2. When animating the thumb between selected and non-selected states, does ToggleSwitch officially change selection and notify listeners during the animation, or after it completes?
    1. ToggleSwitch will change skin states and notify listeners after the thumb has reached its final position.

Related

Wiki: Flex 4.6
Wiki: ToggleSwitch

MongoDB Logo MongoDB