Flash/Flex学习笔记(36):自己动手实现一个滑块控件(JimmySilder)
先看最终的演示:
滑块条的应用实在太广泛了:mp3播放器中声量的大小控制,视频播放时的画面亮度调节,阅读新闻时字体大小的实时调整,对象的大小互动控制...
分析:
1.任何一个滑块条控件的UI部分,基本上可以分为:背景滑块条 + 滑块按钮 二个部分
所以我分成了三部分: JimmySilderBar(背景条),JimmySilderButton(拖动钮),JimmySilder(真正的滑动控件,将前二个组合在一起),为了重用,这三个部分都做成MovieClip元件放在库里,这样以后要换风格或颜色时,只要在库里编辑元件,所有的地方自然全变了.
另外在JimmySilder这个元件中,为了能在代码中引用到另外二个元件的实例,JimmySilderButton实例被命名为_mcBtn,而JimmySilderBar实例被命名为_mcBar

2.拖动问题
MovieClip有startDrag/endDrag方法,而且startDarg方法还能方便的设置拖动的边界(即拖动时,滑块钮不能拖到背景条以外的地方),so...这个问题也解决了
3.属性/事件支持
既然是滑块控件,肯定要能得到当前的位置/值,另外拖动(以导致值变化)时,应该能触发使用者自己定义的处理方法(否则就变成一个单纯只能拖来拖去的东东,不能跟其它对象的属性关联交互,那就没啥意义了)
实现:
1.为了支持事件,首先也定义一个Event子类:
01 package Jimmy.Event {
02 import flash.events.Event;
03
04 public class ValueChangeEvent extends Event {
05 public static const VALUE_CHANGE:String = "VALUE_CHANGE";
06 private var _OldValue:Number,_NewValue:Number;
07
08 public function ValueChangeEvent(eventType:String,oldValue:Number,newValue:Number){
09 this._OldValue = oldValue;
10 this._NewValue = newValue;
11 super(eventType);
12 }
13
14 public function get OldValue():Number{
15 return _OldValue;
16 }
17
18 public function get NewValue():Number{
19 return _NewValue;
20 }
21 }
22 }
2.控件代码的实现:
001 //滑块控件 beta 0.001 -- by 菩提树下的杨过 http://yjmyzz.cnblogs.com/
002 package {
003 import flash.display.Sprite;
004 import flash.display.MovieClip;
005 import flash.events.MouseEvent;
006 import flash.ui.Mouse;
007 import flash.events.Event;
008 import flash.ui.MouseCursor;
009 import flash.geom.Rectangle;
010 import Jimmy.Event.ValueChangeEvent;
011
012 public class JimmySilder extends MovieClip {
013
014 private var _btnWidth:uint;//滑块宽度
015 private var _btnHeight:uint;//滑块高度
016 private var _barWidth:uint;//滑块背景条宽度
017 private var _barHeight:uint;//滑块背景条高度
018 private var _isDragging:Boolean=false;//是否正在拖动
019 private var _value:Number=0.0;//滑块的值(百分比)
020
021 public function JimmySilder(btnWidth:uint = 10,btnHeight:uint = 30,barWidth:uint=200,barHeight:uint=10,v:Number=0.5):void {
022
023 //trace("JimmySilder's constructor is called.");
024
025 this._btnWidth=btnWidth;
026 this._btnHeight=btnHeight;
027 this._barWidth=barWidth;
028 this._barHeight=barHeight;
029
030 init();
031
032 this.Value=v;
033
034 this.addEventListener(Event.ADDED_TO_STAGE,AddedToStage);
035
036
037 }
038
039 private function AddedToStage(e:Event):void{
040 this.stage.addEventListener(MouseEvent.MOUSE_MOVE,stageMouseMoveHandler);
041 this.stage.addEventListener(MouseEvent.MOUSE_UP,stageMouseUpHandler);
042 }
043
044 //属性Value的setter方法
045 public function set Value(v:Number):void {
046 if (v<=0) {
047 v=0.0;
048 }
049 if (v>=1) {
050 v=1.0;
051 }
052 this._value=v;
053 this._mcBtn.x = _mcBar.width/(-2) + _mcBar.width * _value;//根据value百分比值来定位mcBtn的横坐标
054 }
055
056 //属性Value的getter方法
057 public function get Value():Number {
058 return _value;
059 }
060
061 //初始化
062 private function init():void {
063 this._mcBtn.width=_btnWidth;
064 this._mcBtn.height=_btnHeight;
065 this._mcBar.width=_barWidth;
066 this._mcBar.height=_barHeight;
067
068 this._mcBtn.addEventListener(MouseEvent.MOUSE_OVER, mcBtnMouseOverHandler);
069 this._mcBtn.addEventListener(MouseEvent.MOUSE_OUT, mcBtnMouseOutHandler);
070 this._mcBtn.addEventListener(MouseEvent.MOUSE_DOWN,mcBtnMouseDownHandler);
071
072 this._mcBar.addEventListener(MouseEvent.MOUSE_DOWN,mcBarMouseDownHandler);
073 //trace("init 初始化完成");
074 }
075
076 //切换光标为手形
077 private function mcBtnMouseOverHandler(e:MouseEvent) {
078 Mouse.cursor=MouseCursor.HAND;
079 }
080
081 //切换光标为系统光标
082 private function mcBtnMouseOutHandler(e:MouseEvent) {
083 Mouse.cursor=MouseCursor.AUTO;
084 }
085
086 //开始拖动
087 private function mcBtnMouseDownHandler(e:MouseEvent) {
088 //trace("开始拖动");
089 _mcBtn.startDrag(true,new Rectangle(_mcBar.width/(-2),0,_mcBar.width,0));//注意:这里锁定中心在指定区域拖动
090 _isDragging=true;
091 }
092
093 //停止拖动
094 private function stageMouseUpHandler(e:MouseEvent) {
095 //trace("停止拖动");
096 _mcBtn.stopDrag();
097 _isDragging=false;
098 }
099
100 //在自身区域上移动时,动态计算_value值
101 private function stageMouseMoveHandler(e:MouseEvent) {
102 if (_isDragging) {
103 RaiseEvent();
104 //trace(_value);
105 }
106 }
107
108
109
110 //在背景条上点击时,滑块直接跳到该位置
111 private function mcBarMouseDownHandler(e:MouseEvent) {
112 _mcBtn.x=mouseX;
113 RaiseEvent();
114 }
115
116 //触发事件
117 private function RaiseEvent():void {
118 var _oldValue:Number=_value;
119 _value = (_mcBtn.x + _mcBar.width/2)/_mcBar.width;
120 var _valueChangeEvent:ValueChangeEvent=new ValueChangeEvent(ValueChangeEvent.VALUE_CHANGE,_oldValue,_value);
121 dispatchEvent(_valueChangeEvent);//触发事件
122 }
123 }
124 }
3.测试代码:
01 import Jimmy.Event.ValueChangeEvent;
02
03 var silder:JimmySilder = new JimmySilder();
04
05 silder.width = 200;
06 silder.height = 20;
07 silder.x = stage.stageWidth/2;
08 silder.y = 200;
09
10 //trace(silder.Value);
11
12 addChild(silder);
13
14 silder.addEventListener(ValueChangeEvent.VALUE_CHANGE, ValueChangeHandler);
15
16 testObj.scaleX = testObj.scaleY = silder.Value;
17
18 testObj2.rotation = silder.Value * 360;
19
20 function ValueChangeHandler(e:ValueChangeEvent){
21 //trace("当前滑块的值是:" + e.NewValue);
22 testObj.scaleX = testObj.scaleY = e.NewValue;
23
24 testObj2.rotation = silder.Value * 360;
25 }
源文件下载: http://cid-2959920b8267aaca.skydrive.live.com/self.aspx/Flash/JimmySilder.rar
后记:可能有人会问,为啥不直接用系统内置的组件,要费这么大劲自己重造轮子? 如果您自己试下就会知道了,用了系统组件后,swf文件大约会在19k或22k,而按本文的办法,同样的swf,最终只有7K(精简了1/3左右),所以还是那句话,能自己手写的就自己手写,除非自己写不了,再用系统的组件。
浙公网安备 33010602011771号