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子类:

view source

print?

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.控件代码的实现:

view source

print?

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.测试代码:

view source

print?

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左右),所以还是那句话,能自己手写的就自己手写,除非自己写不了,再用系统的组件。

原文地址:https://www.cnblogs.com/happysky97/p/1884570.html