Flex 4 水平 / 垂直 反転スライダーコンポーネント

2012.02.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

日々のお仕事シリーズ(仮称)

Flex 4 には、HSlider ( 水平 )、VSlider ( 垂直 )と、2 種類のスライダーコンポーネントが用意されていますが、最大値から最大値への進行方向がそれぞれ固定されています。 ( HSlider : 左→右、VSlider : 下→上 )

稀に、逆方向に値が増減するモノを求められることがあるのですが、そのような機能は実装されていないので、自前で用意します。

反転機能付き水平スライダーコンポーネント (ReverseHSlider.as)

package jp.classmethod.component {
    import flash.events.KeyboardEvent;
    import flash.geom.Matrix;
    import flash.ui.Keyboard;
    import spark.components.HSlider;
    /**
     * <p>ReverseHSlider クラスは、オリジナルの HSlider を水平方向に反転させたコンポーネントです。</p>
     * @author hirohata.taiga
     */
    public class ReverseHSlider extends HSlider {
        /**
         * <p>水平方向の反転の有無を示すブール値です。</p>
         */
        public function get isReverse():Boolean {
            return _isReverse;
        }
        /** @private */
        public function set isReverse(value:Boolean):void {
            _isReverse = value;
            invalidateProperties();
            invalidateDisplayList();
        }
        /** @private */
        private var _isReverse:Boolean;
        /**
         * <p>コンストラクタ</p>
         */
        public function ReverseHSlider() {
            super();
        }
        /** @private */
        protected override function keyDownHandler(event:KeyboardEvent):void {
            var keyCode_:int = event.keyCode;
            if(keyCode_ == Keyboard.LEFT && _isReverse) {
                keyCode_ = Keyboard.RIGHT;
            }
            else if(keyCode_ == Keyboard.RIGHT && _isReverse) {
                keyCode_ = Keyboard.LEFT;
            }
            else if(keyCode_ == Keyboard.DOWN && _isReverse) {
                keyCode_ = Keyboard.UP;
            }
            else if(keyCode_ == Keyboard.UP && _isReverse) {
                keyCode_ = Keyboard.DOWN;
            }
            event.keyCode = keyCode_;
            super.keyDownHandler(event);
        }
        /** @private */
        protected override function updateDisplayList(w:Number, h:Number):void {
            super.updateDisplayList(w, h);
            var m:Matrix = new Matrix();
            m.scale(_isReverse ? -1 : 1, 1);
            m.tx = _isReverse ? unscaledWidth : 0;
            transform.matrix = m;
        }
    }
}

反転機能付き垂直スライダーコンポーネント (ReverseVSlider.as)

package jp.classmethod.component {
    import flash.events.KeyboardEvent;
    import flash.geom.Matrix;
    import flash.ui.Keyboard;
    import spark.components.VSlider;
    /**
     * <p>ReverseVSlider クラスは、オリジナルの VSlider を垂直方向に反転させたコンポーネントです。</p>
     * @author hirohata.taiga
     */
    public class ReverseVSlider extends VSlider {
        /**
         * <p>垂直方向の反転の有無を示すブール値です。</p>
         */
        public function get isReverse():Boolean {
            return _isReverse;
        }
        /** @private */
        public function set isReverse(value:Boolean):void {
            _isReverse = value;
            invalidateProperties();
            invalidateDisplayList();
        }
        /** @private */
        private var _isReverse:Boolean;
        /**
         * <p>コンストラクタ</p>
         */
        public function ReverseVSlider() {
            super();
        }
        /** @private */
        protected override function keyDownHandler(event:KeyboardEvent):void {
            var keyCode_:int = event.keyCode;
            if(keyCode_ == Keyboard.LEFT && _isReverse) {
                keyCode_ = Keyboard.RIGHT;
            }
            else if(keyCode_ == Keyboard.RIGHT && _isReverse) {
                keyCode_ = Keyboard.LEFT;
            }
            else if(keyCode_ == Keyboard.DOWN && _isReverse) {
                keyCode_ = Keyboard.UP;
            }
            else if(keyCode_ == Keyboard.UP && _isReverse) {
                keyCode_ = Keyboard.DOWN;
            }
            event.keyCode = keyCode_;
            super.keyDownHandler(event);
        }
        /** @private */
        protected override function updateDisplayList(w:Number, h:Number):void {
            super.updateDisplayList(w, h);
            var m:Matrix = new Matrix();
            m.scale(1, _isReverse ? -1 : 1);
            m.ty = _isReverse ? unscaledHeight : 0;
            transform.matrix = m;
        }
    }
}

実装コード (Main.mxml)

<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:fx = "http://ns.adobe.com/mxml/2009"
xmlns:s  = "library://ns.adobe.com/flex/spark"
xmlns:c  = "jp.classmethod.component.*"
fontSize = "20"
>

<s:VGroup width="200" verticalCenter="0" horizontalCenter="0" gap="50">

    <s:ToggleButton id="tg" width="200"
                    label="{tg.selected?'isReverse=true':'isReverse=false'}" />

    <s:VGroup width="100%" horizontalAlign="center">
        <s:Label id="hLabel" text="{String(hSlider.value)}" />
        <c:ReverseHSlider 
            id="hSlider" width="200" height="30"
            isReverse="{tg.selected}" minimum="0" maximum="10" stepSize="1" />
    </s:VGroup>

    <s:HGroup width="100%" verticalAlign="middle" horizontalAlign="center">
        <s:Label id="vLabel" width="40" text="{String(vSlider.value)}" />
        <c:ReverseVSlider 
            id="vSlider" width="30" height="200" 
            isReverse="{tg.selected}" minimum="0" maximum="10" stepSize="1" />
    </s:HGroup>

</s:VGroup>

</s:Application>

解説

isReverse という反転の有無を示すプロパティを用意して、描画のタイミング ( updateDisplayList() ) でプロパティの状態に応じた変換マトリックス ( 変換行列 ) を作成して、コンポーネントの Transform オブジェクトの matrix プロパティに適用させます。

これだけで反転は実現できますが、ついでに十字キー操作のお世話もしておきました。isReverse プロパティの状態に応じてイベントオブジェクトを改竄 ( 上下左右を反転 ) しています。

出力結果

出力結果は次の通り

[SWF]http://public-blog-dev.s3.amazonaws.com/wp-content/uploads/2012/02/ReverseSliderSample20120207.swf,640,480[/SWF]