• 雕虫小艺:Slider控件的制作(Flash)


    Slider是常用控件。Adobe官方提供的控件中,fl库所带的控件不好用,便有兄弟《自制Flash Slider滚动条Flex库中也提供有Slider控件,但是Flex控件太重量级,动不动就是一二百K的尺寸,很多场合没法用。并且,FlexSlider也不容易定制,比如,它的highlight tracktrack要低1像素,这在很多情况下是不合适的。

    本文修改MinimalComps项目的Slider控件代码,提供一个小巧的Slider控件解决方案,本方案具有以下优势:

    (1)小巧。不依赖于fl控件或Flex库,使用本控件不会让程序尺寸增加多少;

    (2)容易定制。很容易定制 highlight tracktrackthumb部分;

    (3)可数据绑定。

    MinimalComps项目提供了简单的Slider控件,该控件源代码为:

     

    View Code
    /**
     * Slider.as
     * Keith Peters
     * version 0.9.1
     * 
     * Abstract base slider class for HSlider and VSlider.
     * 
     * Copyright (c) 2010 Keith Peters
     * 
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     * 
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     * 
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     
    */
     
    package com.bit101.components
    {
        import flash.display.DisplayObjectContainer;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Rectangle;
        
        public class Slider extends Component
        {
            protected var _handle:Sprite;
            private var _back:Sprite;
            private var _backClick:Boolean = true;
            protected var _value:Number = 0;
            protected var _max:Number = 100;
            protected var _min:Number = 0;
            protected var _orientation:String;
            protected var _tick:Number = 1;
            
            public static const HORIZONTAL:String = "horizontal";
            public static const VERTICAL:String = "vertical";
            
            /**
             * Constructor
             * @param orientation Whether the slider will be horizontal or vertical.
             * @param parent The parent DisplayObjectContainer on which to add this Slider.
             * @param xpos The x position to place this component.
             * @param ypos The y position to place this component.
             * @param defaultHandler The event handling function to handle the default event for this component (change in this case).
             
    */
            public function Slider(orientation:String = Slider.HORIZONTAL, parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, defaultHandler:Function = null)
            {
                _orientation = orientation;
                super(parent, xpos, ypos);
                if(defaultHandler != null)
                {
                    addEventListener(Event.CHANGE, defaultHandler);
                }
            }
            
            /**
             * Initializes the component.
             
    */
            override protected function init():void
            {
                super.init();

                if(_orientation == HORIZONTAL)
                {
                    setSize(100, 10);
                }
                else
                {
                    setSize(10, 100);
                }
            }
            
            /**
             * Creates and adds the child display objects of this component.
             
    */
            override protected function addChildren():void
            {
                _back = new Sprite();
                _back.filters = [getShadow(2, true)];
                addChild(_back);
                
                _handle = new Sprite();
                _handle.filters = [getShadow(1)];
                _handle.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
                _handle.buttonMode = true;
                _handle.useHandCursor = true;
                addChild(_handle);
            }
            
            /**
             * Draws the back of the slider.
             
    */
            protected function drawBack():void
            {
                _back.graphics.clear();
                _back.graphics.beginFill(Style.BACKGROUND);
                _back.graphics.drawRect(0, 0, _width, _height);
                _back.graphics.endFill();

                if(_backClick)
                {
                    _back.addEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
                }
                else
                {
                    _back.removeEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
                }
            }
            
            /**
             * Draws the handle of the slider.
             
    */
            protected function drawHandle():void
            {   
                _handle.graphics.clear();
                _handle.graphics.beginFill(Style.BUTTON_FACE);
                if(_orientation == HORIZONTAL)
                {
                    _handle.graphics.drawRect(1, 1, _height - 2, _height - 2);
                }
                else
                {
                    _handle.graphics.drawRect(1, 1, _width - 2, _width - 2);
                }
                _handle.graphics.endFill();
                positionHandle();
            }
            
            /**
             * Adjusts value to be within minimum and maximum.
             
    */
            protected function correctValue():void
            {
                if(_max > _min)
                {
                    _value = Math.min(_value, _max);
                    _value = Math.max(_value, _min);
                }
                else
                {
                    _value = Math.max(_value, _max);
                    _value = Math.min(_value, _min);
                }
            }
            
            /**
             * Adjusts position of handle when value, maximum or minimum have changed.
             * TODO: Should also be called when slider is resized.
             
    */
            protected function positionHandle():void
            {
                var range:Number;
                if(_orientation == HORIZONTAL)
                {
                    range = _width - _height;
                    _handle.x = (_value - _min) / (_max - _min) * range;
                }
                else
                {
                    range = _height - _width;
                    _handle.y = _height - _width - (_value - _min) / (_max - _min) * range;
                }
            }
            
            
            
            
            ///////////////////////////////////
            // public methods
            ///////////////////////////////////
            
            /**
             * Draws the visual ui of the component.
             
    */
            override public function draw():void
            {
                super.draw();
                drawBack();
                drawHandle();
            }
            
            /**
             * Convenience method to set the three main parameters in one shot.
             * @param min The minimum value of the slider.
             * @param max The maximum value of the slider.
             * @param value The value of the slider.
             
    */
            public function setSliderParams(min:Number, max:Number, value:Number):void
            {
                this.minimum = min;
                this.maximum = max;
                this.value = value;
            }
            
            
            
            
            ///////////////////////////////////
            // event handlers
            ///////////////////////////////////
            
            /**
             * Handler called when user clicks the background of the slider, causing the handle to move to that point. Only active if backClick is true.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onBackClick(event:MouseEvent):void
            {
                if(_orientation == HORIZONTAL)
                {
                    _handle.x = mouseX - _height / 2;
                    _handle.x = Math.max(_handle.x, 0);
                    _handle.x = Math.min(_handle.x, _width - _height);
                    _value = _handle.x / (width - _height) * (_max - _min) + _min;
                }
                else
                {
                    _handle.y = mouseY - _width / 2;
                    _handle.y = Math.max(_handle.y, 0);
                    _handle.y = Math.min(_handle.y, _height - _width);
                    _value = (_height - _width - _handle.y) / (height - _width) * (_max - _min) + _min;
                }
                dispatchEvent(new Event(Event.CHANGE));
                
            }
            
            /**
             * Internal mouseDown handler. Starts dragging the handle.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onDrag(event:MouseEvent):void
            {
                stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, onSlide);
                if(_orientation == HORIZONTAL)
                {
                    _handle.startDrag(false, new Rectangle(0, 0, _width - _height, 0));
                }
                else
                {
                    _handle.startDrag(false, new Rectangle(0, 0, 0, _height - _width));
                }
            }
            
            /**
             * Internal mouseUp handler. Stops dragging the handle.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onDrop(event:MouseEvent):void
            {
                stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
                stage.removeEventListener(MouseEvent.MOUSE_MOVE, onSlide);
                stopDrag();
            }
            
            /**
             * Internal mouseMove handler for when the handle is being moved.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onSlide(event:MouseEvent):void
            {
                var oldValue:Number = _value;
                if(_orientation == HORIZONTAL)
                {
                    _value = _handle.x / (width - _height) * (_max - _min) + _min;
                }
                else
                {
                    _value = (_height - _width - _handle.y) / (height - _width) * (_max - _min) + _min;
                }
                if(_value != oldValue)
                {
                    dispatchEvent(new Event(Event.CHANGE));
                }
            }
            
            
            
            
            ///////////////////////////////////
            // getter/setters
            ///////////////////////////////////
            
            /**
             * Sets / gets whether or not a click on the background of the slider will move the handler to that position.
             
    */
            public function set backClick(b:Boolean):void
            {
                _backClick = b;
                invalidate();
            }
            public function get backClick():Boolean
            {
                return _backClick;
            }
            
            /**
             * Sets / gets the current value of this slider.
             
    */
            public function set value(v:Number):void
            {
                _value = v;
                correctValue();
                positionHandle();
                
                // This has the potential to set up an infinite loop if two sliders are listening to each other's change
                // events to sync to each other. Tentitively trying it out... 
                dispatchEvent(new Event(Event.CHANGE));
            }
            public function get value():Number
            {
                return Math.round(_value / _tick) * _tick;
            }
            
            /**
             * Gets / sets the maximum value of this slider.
             
    */
            public function set maximum(m:Number):void
            {
                _max = m;
                correctValue();
                positionHandle();
            }
            public function get maximum():Number
            {
                return _max;
            }
            
            /**
             * Gets / sets the minimum value of this slider.
             
    */
            public function set minimum(m:Number):void
            {
                _min = m;
                correctValue();
                positionHandle();
            }
            public function get minimum():Number
            {
                return _min;
            }
            
            /**
             * Gets / sets the tick value of this slider. This round the value to the nearest multiple of this number. 
             
    */
            public function set tick(t:Number):void
            {
                _tick = t;
            }
            public function get tick():Number
            {
                return _tick;
            }
            
        }
    }

    然而,MinimalCompsSlider控件的外观(http://www.minimalcomps.com/?page_id=5)很简单,见下图。

    由于外观直接写死了,没办法换皮肤,因此,难以用于生产环境。

     

    下面是我的改写版本:

     

    View Code
    /**
     * Slider.as
     * Keith Peters
     * version 0.9.10
     * 
     * Abstract base slider class for HSlider and VSlider.
     * 
     * Copyright (c) 2011 Keith Peters
     * 
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     * 
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     * 
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     * 
     * version 1.0
     * By. xiaotie@geblab.com
     * Changes: [2012-02-11] make it skinable 
     
    */
    package geb.controls
    {
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Rectangle;
        
        import geb.common.BaseComponent;
        
        [Event(name="change", type="flash.events.Event")]
        public class Slider extends BaseComponent
        {
            [Bindable]
            public var thumb:Sprite;
            [Bindable]
            public var track:Sprite;
            [Bindable]
            public var trackHighlight:Sprite;
            
            [Bindable]
            public var orientation:String = "horizontal";

            public var trackClickable:Boolean = true;
            
            [Bindable]
            public var ignoreThumbSize:Boolean = false;

            protected var _value:Number = 0;
            protected var _max:Number = 100;
            protected var _min:Number = 0;
            protected var _tick:Number = 0.01;
            
            public static const HORIZONTAL:String = "horizontal";
            public static const VERTICAL:String = "vertical";
            
            /**
             * Initializes the component.
             
    */
            override protected function init():void
            {
                super.init();
                
                if(orientation == HORIZONTAL)
                {
                    setSize(width, height);
                }
                else
                {
                    setSize(width, height);
                }
            }
            
            /**
             * Creates and adds the child display objects of this component.
             
    */
            override protected function addChildren():void
            {
                super.addChildren();
            }
            
            /**
             * Adjusts value to be within minimum and maximum.
             
    */
            protected function correctValue():void
            {
                if(_max > _min)
                {
                    _value = Math.min(_value, _max);
                    _value = Math.max(_value, _min);
                }
                else
                {
                    _value = Math.max(_value, _max);
                    _value = Math.min(_value, _min);
                }
            }
            
            private function get thumbSize():Number
            {
                if(thumb == null || ignoreThumbSize == truereturn 0;
                else if(orientation == HORIZONTAL)
                {
                    return thumb.width;
                }
                else
                {
                    return thumb.height;
                }
            }
            
            /**
             * Adjusts position of handle when value, maximum or minimum have changed.
             * TODO: Should also be called when slider is resized.
             
    */
            protected function updateDislpay():void
            {
                var range:Number;
                var highlightRange:Number;
                var pos:Number;
                var ts:Number = thumbSize;
                
                if(orientation == HORIZONTAL)
                {
                    range = _width - ts;
                    pos = (_value - _min) / (_max - _min) * range;
                    highlightRange = pos + ts * 0.5;
                    
                    if(thumb!=null)
                    {
                        thumb.x = pos - (ignoreThumbSize ? thumb.width * 0.5 : 0);
                        thumb.y = 0.5 * (this.height - thumb.height);
                    }
                    
                    if(trackHighlight != null)
                    {
                        trackHighlight.width = pos + 0.5 * ts;
                        trackHighlight.height = Math.min(height,trackHighlight.height);
                        trackHighlight.y = Math.max(0, 0.5 * (height - trackHighlight.height));
                        if(trackHighlight is BaseComponent)
                        {
                            BaseComponent(trackHighlight).invalidate(false);
                        }
                    }
                    
                    if(track != null)
                    {
                        track.width = width;
                        track.height = Math.min(height,track.height);
                        track.y = Math.max(0, 0.5 * (height - track.height));
                        if(track is BaseComponent)
                        {
                            BaseComponent(track).invalidate(false);
                        }
                    }
                }
                else
                {
                    range = _height - ts;
                    pos = height - ts - (_value - _min) / (_max - _min) * range;
                    highlightRange = pos + ts * 0.5;
                    
                    if(thumb != null)
                    {
                        thumb.x = 0.5 * (this.width - thumb.width);
                        thumb.y = pos - (ignoreThumbSize ? thumb.height * 0.5 : 0);
                    }
                    
                    if(trackHighlight != null)
                    {
                        trackHighlight.width = Math.min(width,trackHighlight.width);
                        trackHighlight.y = pos + 0.5 * ts;
                        trackHighlight.height = height - trackHighlight.y;
                        trackHighlight.x = Math.max(0, 0.5 * (width - trackHighlight.width));
                        if(trackHighlight is BaseComponent)
                        {
                            BaseComponent(trackHighlight).invalidate(false);
                        }
                    }
                    
                    if(track != null)
                    {
                        track.height = height;
                        track.width = Math.min(width,track.width);
                        track.x = Math.max(0, 0.5 * (width - track.width));
                        if(track is BaseComponent)
                        {
                            BaseComponent(track).invalidate(false);
                        }
                    }
                }
                
                if(track != null && this.contains(track) == false)
                {
                    addChild(track);
                    if(trackClickable)
                    {
                        track.useHandCursor = true;
                        track.buttonMode = true;
                        track.addEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
                    }
                    else
                    {
                        track.removeEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
                    }
                }
                
                if(trackHighlight != null && this.contains(trackHighlight) == false)
                {
                    addChild(trackHighlight);
                    if(trackClickable)
                    {
                        trackHighlight.useHandCursor = true;
                        trackHighlight.buttonMode = true;
                        trackHighlight.addEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
                    }
                    else
                    {
                        trackHighlight.removeEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
                    }
                }
                
                if(thumb != null && this.contains(thumb) == false)
                {
                    thumb.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
                    thumb.buttonMode = true;
                    thumb.useHandCursor = true;
                    addChild(thumb);
                }
                
            }
            
            ///////////////////////////////////
            // public methods
            ///////////////////////////////////
            
            /**
             * Draws the visual ui of the component.
             
    */
            override public function draw():void
            {
                super.draw();
                updateDislpay();
            }
            
            /**
             * Convenience method to set the three main parameters in one shot.
             * @param min The minimum value of the slider.
             * @param max The maximum value of the slider.
             * @param value The value of the slider.
             
    */
            public function setSliderParams(min:Number, max:Number, value:Number):void
            {
                this.minimum = min;
                this.maximum = max;
                this.value = value;
            }
            
            ///////////////////////////////////
            // event handlers
            ///////////////////////////////////
            
            /**
             * Handler called when user clicks the background of the slider, causing the handle to move to that point. Only active if backClick is true.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onBackClick(event:MouseEvent):void
            {
                var ts:Number = thumbSize;
                var pos:Number;
                if(orientation == HORIZONTAL)
                {
                    pos = mouseX - ( ignoreThumbSize ? 0 : thumb.width * 0.5);
                    pos = Math.max(pos, 0);
                    pos = Math.min(pos, _width - ts);
                    value = pos / (width - ts) * (_max - _min) + _min;
                }
                else
                {
                    pos = mouseY - ( ignoreThumbSize ? 0 : thumb.height * 0.5);
                    pos = Math.max(pos, 0);
                    pos = Math.min(pos, _height - ts);
                    value = (_height - ts - pos) / (height - ts) * (_max - _min) + _min;
                }
                
                dispatchEvent(new Event(Event.CHANGE));
            }
            
            /**
             * Internal mouseDown handler. Starts dragging the handle.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onDrag(event:MouseEvent):void
            {
                stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, onSlide);
                if(orientation == HORIZONTAL)
                {
                    var xStart:Number = ignoreThumbSize? - thumb.width * 0.5 : 0;
                    thumb.startDrag(false, new Rectangle(xStart, thumb.y, _width - thumbSize, 0));
                }
                else
                {
                    var yStart:Number = ignoreThumbSize? - thumb.height * 0.5 : 0;
                    thumb.startDrag(false, new Rectangle(thumb.x, yStart, 0, _height - thumbSize));
                }
            }
            
            /**
             * Internal mouseUp handler. Stops dragging the handle.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onDrop(event:MouseEvent):void
            {
                stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
                stage.removeEventListener(MouseEvent.MOUSE_MOVE, onSlide);
                stopDrag();
            }
            
            /**
             * Internal mouseMove handler for when the handle is being moved.
             * @param event The MouseEvent passed by the system.
             
    */
            protected function onSlide(event:MouseEvent):void
            {
                var oldValue:Number = _value;
                var pos:Number;
                if(orientation == HORIZONTAL)
                {
                    pos = ignoreThumbSize ? (thumb.x + thumb.width * 0.5) : thumb.x;
                    value = pos / (width - thumbSize) * (_max - _min) + _min;
                }
                else
                {
                    pos = ignoreThumbSize ? (thumb.y + thumb.height * 0.5) : thumb.y;
                    value = (height - thumbSize - pos) / (height - thumbSize) * (_max - _min) + _min;
                }
                
                if(value != oldValue)
                {
                    dispatchEvent(new Event(Event.CHANGE));
                }
            }
            
            ///////////////////////////////////
            // getter/setters
            ///////////////////////////////////
            
            /**
             * Sets / gets whether or not a click on the background of the slider will move the handler to that position.
             
    */
            public function set backClick(b:Boolean):void
            {
                trackClickable = b;
                invalidate();
            }
            
            public function get backClick():Boolean
            {
                return trackClickable;
            }
            
            /**
             * Sets / gets the current value of this slider.
             
    */
            [Bindable]
            public function set value(v:Number):void
            {
                _value = v;
                correctValue();
                updateDislpay();
            }

            [Bindable]
            public function get value():Number
            {
                return Math.round(_value / _tick) * _tick;
            }
            
            /**
             * Gets the value of the slider without rounding it per the tick value.
             
    */
            public function get rawValue():Number
            {
                return _value;
            }
            
            [Bindable]
            /**
             * Gets / sets the maximum value of this slider.
             
    */
            public function set maximum(m:Number):void
            {
                _max = m;
                correctValue();
                updateDislpay();
            }
            
            public function get maximum():Number
            {
                return _max;
            }
            
            [Bindable]
            /**
             * Gets / sets the minimum value of this slider.
             
    */
            public function set minimum(m:Number):void
            {
                _min = m;
                correctValue();
                updateDislpay();
            }
            
            public function get minimum():Number
            {
                return _min;
            }
            
            /**
             * Gets / sets the tick value of this slider. This round the value to the nearest multiple of this number. 
             
    */
            public function set tick(t:Number):void
            {
                _tick = t;
            }
            
            public function get tick():Number
            {
                return _tick;
            }
        }
    }

    BaseComponent类见我的其它博文:《只学一点点:我的技术学习策略 》(http://www.cnblogs.com/xiaotie/archive/2011/12/10/2283384.html)和《使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序!》(http://www.cnblogs.com/xiaotie/archive/2011/06/15/2081386.html)。

    下面演示Slider控件的使用:

     

    View Code
    <?xml version="1.0" encoding="utf-8"?>
    <common:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
                        xmlns:local
    ="*"
                        xmlns:common
    ="geb.common.*"
                        xmlns:gc
    ="geb.controls.*"
                        xmlns:shapes
    ="geb.shapes.*"
                        xmlns:containers
    ="geb.containers.*"
                        fillMode
    ="false" 
                        width
    ="300" height="300"
                        
    >
        <fx:Declarations>
            <!-- 定义slider1外观的三个形状 -->
            <shapes:Rectangle id="trackHighlight" color="0x125894" height="5" />
            <shapes:Rectangle id="track" color="0x343434" height="5" />
            <shapes:Ellipse id="thumb" color="0x999999" width="10" height="10" />
            
            <!-- 定义slider3外观的三个形状 -->
            <shapes:Rectangle id="trackHighlight2" color="0x125894" width="5" />
            <shapes:Rectangle id="track2" color="0x343434" width="5" />
            <shapes:Ellipse id="thumb2" color="0x999999" width="10" height="10" />
            
            <!-- 定义slider2外观的三个图片 -->
            <gc:Image id="thumbImage" height="10" width="10" source="@Embed(source='assets/sliderAssets/thumbSkin.png')" />
            <gc:Image id="trackHighlightImage" height="4" width="10" source="@Embed(source='assets/sliderAssets/trackHighlightSkin.png')" />
            <gc:Image id="trackImage" height="4" width="10" source="@Embed(source='assets/sliderAssets/trackSkin.png')" />
        </fx:Declarations>
        <shapes:Rectangle width="{width}" height="{height}" color="0xEEEEEE" />
        <gc:Slider id="slider1" x="50" y="50" width="70" height="20"
                   trackHighlight
    ="{trackHighlight}"
                   track
    ="{track}"
                   thumb
    ="{thumb}" ignoreThumbSize="false">
        </gc:Slider>
        <gc:Label x="130" y="50" autoSize="true" text="{slider1.value}" />
        <gc:Slider id="slider2" x="50" y="100" width="70" height="20"
                   trackHighlight
    ="{trackHighlightImage}" value="20" maximum="50"
                   track
    ="{trackImage}"
                   thumb
    ="{thumbImage}" ignoreThumbSize="true">
        </gc:Slider>
        <gc:Label x="130" y="100" autoSize="true" text="{slider2.value}" />
        <gc:Slider id="slider3" x="50" y="150" width="10" height="70"
                   trackHighlight
    ="{trackHighlight2}" orientation="vertical"
                   track
    ="{track2}"
                   thumb
    ="{thumb2}" ignoreThumbSize="true">
        </gc:Slider>
    </common:Application>

     

    在线演示:

     

    从上到下,可以看到三个Slider

    第一个Slider的皮肤由三个形状组成,track是黑色矩形,highlightTrack是蓝色矩形,thumb是圆。highlightTracktrack都规定了高度,这个高度,就是显示出来的highlightTracktrack高度,如果想让highlightTracktrack变粗,改变它的高度即可。Thumb规定了长和宽,如果修改thumb的大小,改变它的长宽即可,当然,如果长宽不等,则就是椭圆而非圆形了。

    第二个Slider是由三个图片组成的,以应对复杂精致的皮肤,所使用的三个图片如下:

    使用不同的图片,便是不同的Slider外观。

    第二个Slider和第一个Slider还有个不同,就是ignoreThumbSize属性为true。第一个Sliderthumb是圆形,把thumb拖到两端可以发现,thumb遮盖不住两端(如果是方形的thumb则没这个问题),因此,引入了ignoreThumbSize字段。ignoreThumbSize字段默认为false,当ignoreThumbSizetrue时,以thumb的中线为定位基准,这样便可避免当thumb是圆形时移动到两端,盖不住track两端的情况。

    第三个Sliderorientation设为vertical,因此,便是竖着的Slider

    Slider可供数据绑定,比如:

    <gc:Label x="130" y="50" autoSize="true" text="{slider1.value}" />

    通过这样简单的代码便可使slider1的值改变时,对应的Lable的文本也发生变化。

    是不是既小巧、又易用又灵活呢?

    版权所有,欢迎转载
  • 相关阅读:
    python开发环境准备
    MacOS X 安装OpenCV3.2
    tensorflow源码分析——BasicLSTMCell
    结对开发求一数组的最大子数组的和
    结对开发读文本中的二维数组求该二维数组最大子数组的和
    随机四则运算的出题程序java
    突现灵感想出较新简单算法实现求一数组最大子数组的和
    四则运算C++版
    Cys_Control(一) 项目搭建
    Cys_Control(二) MButton
  • 原文地址:https://www.cnblogs.com/xiaotie/p/2346956.html
Copyright © 2020-2023  润新知