雕虫小艺: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的文本也发生变化。

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

版权所有,欢迎转载
原文地址:https://www.cnblogs.com/xiaotie/p/2346956.html