程序媛也话Android 之 自定义控件垂直方向滑动条.docx

上传人:b****4 文档编号:4381362 上传时间:2022-12-01 格式:DOCX 页数:17 大小:162.28KB
下载 相关 举报
程序媛也话Android 之 自定义控件垂直方向滑动条.docx_第1页
第1页 / 共17页
程序媛也话Android 之 自定义控件垂直方向滑动条.docx_第2页
第2页 / 共17页
程序媛也话Android 之 自定义控件垂直方向滑动条.docx_第3页
第3页 / 共17页
程序媛也话Android 之 自定义控件垂直方向滑动条.docx_第4页
第4页 / 共17页
程序媛也话Android 之 自定义控件垂直方向滑动条.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

程序媛也话Android 之 自定义控件垂直方向滑动条.docx

《程序媛也话Android 之 自定义控件垂直方向滑动条.docx》由会员分享,可在线阅读,更多相关《程序媛也话Android 之 自定义控件垂直方向滑动条.docx(17页珍藏版)》请在冰豆网上搜索。

程序媛也话Android 之 自定义控件垂直方向滑动条.docx

程序媛也话Android之自定义控件垂直方向滑动条

Android里已经有足够多的控件供开发者使用,但有时候我们还是会想要一些不一样的东西,比如一些UI特效,比如一些3D动画,今天就讲讲比较basic的东西:

自定义控件。

 

1.效果图

如果项目里需要一个通用的控件,然后UI给你这样一个效果图,你接下来会打算怎么做?

 用户可以按住拖动

点击要切换的状态,然后自动滑动到那一端

 

(本来是没有这个效果图的,又不想一张张贴不同的状态,就画了一下这个gif图,关于怎么在ubuntu下画gif图,可以看一下下面这篇)

程序媛也会画图之在ubuntu下用GIMP制作gif

 

 

2.分析

看一下有没有现成的widget,这似乎和android.widget.Switch有点类似,可是Swithc是水平的,水平没有关系,改成垂直的问题不大,先来尝试下好了,就先把背景和button的图片换一下,来看一下结果是怎样:

额。

这个切换似乎生硬了点,没有渐变的动画。

好吧,那还是重新自己写一个控件吧。

 

 

3.创建Andriod自定义控件的步骤

怎么建立一个自定义的控件,说起来并不难,有三个内容需要实现:

3.1新建一个控件类,继承android.view.View类:

1publicclassXXXViewextendsView{

2...

3protectedvoidonDraw(Canvascanvas){

4...

5}

6

7publicbooleanonTouchEvent(MotionEventevent){

8...

9}

10

11publicinterfaceOnXXXListener{//状态回调,同View.OnClickListener

12publicabstractvoidxxx();

13publicabstractvoidxxx();

14}

15}

 

3.2在布局文件xml里使用这个控件:

id=”@+id/xxx”

android:

layoutWidth=”...”

android:

layoutHeight=”...”>

 

3.3在Activity类里获得这个控件:

1mXXXView=(XXXView)findViewById(R.id.xxx);

2mXXXView.setListener(mXXXViewListener);

以上这简单的3个步骤就是创建和使用控件的内容了,到这里,如果你是个喜欢着急写代码的人,你也可以先搭一个程序框架出来跑跑看啦。

 

 

 

4.考虑怎么画?

4.1拖动

用户需要能拖动Button,那也就是说我们在控件里需要捕获用户的touchevent,知道用户到底是做了什么动作(ACTION_DOWN,ACTION_MOVE,UP),还有操作的位置在哪里(getX(),getY()).

这些信息从哪里可以知道?

--》onTouchEvent()回调!

4.2动画

动画的本质就是图片+位置+时间差。

在效果图中,用户也可以点击一个状态,让控件滑动。

那这个滑动的过程就是一个动画的。

图片我们有,那怎么把图片画到Canvas上?

-》在onDraw()回调里面画。

在主线程里只要调用invalidate(),就会重新触发onDraw()的执行。

如果我们在一定的时间间隔,在不同的位置重新画图片,不就是动画了?

位置可以从用户行为获得,或者自己计算;

时间差,在Android里面控制时间最容易的是什么?

当然是Handler啦,因为它可以发送delay的消息。

4.3渐变的实现

效果图中还有个渐变的过程,这个看起来好像蛮麻烦,其实也好办。

因为有Alpha的存在。

我们可以在画的时候根据不同的位置,设置Paint不同的Alpha值,一个图片Alpha慢慢减小,另一个图片Alpha慢慢增大。

ok,分析到这里,就大概知道该怎么做了,在onTouchEvent()回调里,获得用户的行为和位置,并记录下来,在适当的时候发送Message给Handler,或者直接调用invalidate()重新画。

在Handler里,接收到信息,就根据当前的状态,更新图片下一个应该出现的位置,然后调用invalidate()触发重新画。

 

 

 

5.计算位置

ok,上面已经确定以什么方式做了,接下来就要用到一点点数学的计算了。

我们要确定图片从哪里开始动,动到哪里结束,还有在什么位置开始切换状态。

先切下图:

   

 

 

 

(文字也做成了图片,其实凡是涉及到文字的都不应该做成图片,如果有人切换到中文,然后他又不认识onoff呢,而且这些文字应该要可设置的才对。

这里图方便就做成图片了。

 

然后就是一些重要坐标位置啦:

图1  蓝色是那个长条的图片,绿色两块是在两个状态下Button所在的位置。

 

图2  黄色的区域是两个小的灰色文字图片

 

图3  这个区域就是文字开始切换的区域

 

 

 

6.伪代码

现在方法也有了,数据也有了,就可以开始写代码了。

为了叙述方便,就用伪代码代替了,下面是最重要的三个部分的伪码:

处理用户行为的逻辑:

1publicbooleanonTouchEvent(MotionEventevent){//处理用户行为

2caseACTION_DOWN:

3if(坐标在图1中蓝色区域){//touch在无效的区域

4return;

5}

6

7if(坐标在图1中绿色区域中Button在的区域){//当前状态是on,就是上面的区域,否则,就是下面的区域

8获得坐标与上边缘的距离gap;

9}else{

10设置正在滑动标志;

11设置动画的方向,发送Message;//会执行到这里的情况是,比如当前状态是on,用户点击了off那一端,那接下来控件就要自动滑动切换到off状态。

12}

13break;

14

15caseACTION_MOVE:

16if(上次Down是在无效区域|正在切换状态){//此时不用响应Move动作。

17return;

18}

19

20if(根据当前的坐标计算,滑块将不在背景区域){

21return;

22}

23

24if(根据当前的坐标计算,在文字交换的区域){

25设置交换标记;

26}

27记录滑块当前位置;

28invalidate();

29break;

30

31caseACTION_UP:

32if(上次Down是在无效区域|正在切换状态){//此时不用响应Up动作。

33return;

34}

35

36取消交换标识;

37if(根据当前坐标计算,最后的状态是on){

38设置滑块位置为on状态时的位置;

39修改状态为on;

40invalidate();

41}else{

42设置滑块位置为off状态时的位置;

43修改状态为off;

44invalidate();

45}

46}

处理自动滑动:

1privateHandlermHandler=newHandler(){//用于处理自动滑动那部分逻辑

2publicvoidhandleMessage(Messagemsg){

3if(计数>20){

4设置当前状态;

5设置滑块的位置;

6取消正在滑动的标志;

7计数归0;

8return;

9}

10

11根据计数,获得interpolator.getInterpolation;//这里用了AccelerateDecelerateInterpolator,让动画有一个加速的效果,其实这么短的距离效果看不出来。

12计算滑块的位置;

13invalidate();

14计数+1;

15sendMessageDelayed(0,20);//20ms后画下一帧。

16}

17

18};

 

画:

1protectedvoidonDraw(Canvascanvas){//具体画的代码

2画背景;

3

4if(在状态交换区域){

5根据滑块位置这是Paint的Alpha值;

6用上面设置的Paint画那四个小图;//在状态交换的时候,四个小图都是显示的。

7}else{

8根据当前的状态,画on滑块或off滑块;

9}

10}

 

ok,有上面3部分的内容,基本上就可以了。

下面就是运行起来的效果,(不好表示啦,其实就是效果图那样的)

 

贴个对应的代码段:

Handler:

1privateHandlermHandler=newHandler(){

2@Override

3publicvoidhandleMessage(Messagemsg){

4if(drawCount>20){

5if(button_status==STATUS_OFF){

6button_status=STATUS_ON;

7buttonY=buttonTopY;

8if(listener!

=null){

9listener.slipToTop();

10}

11}else{

12button_status=STATUS_OFF;

13buttonY=buttonBottomY;

14if(listener!

=null){

15listener.slipToBottom();

16}

17}

18

19isTouchDownAnotherSide=false;

20drawCount=0;

21return;

22}

23

24floatp;

25if(isToBottom){

26p=(float)(drawCount*0.05);

27}else{

28p=(float)(1-drawCount*0.05);

29}

30floatinter=interpolator.getInterpolation(p);

31buttonY=buttonTopY+(buttonBottomY-buttonTopY)*inter;

32

33if(buttonY>=exchangeBeginY&&buttonY<=exchangeEndY){

34isExchange=true;

35}else{

36isExchange=false;

37}

38invalidate();

39drawCount++;

40sendEmptyMessageDelayed(0,20);

41}

42};

ViewCode

 

onDraw():

1@Override

2protectedvoidonDraw(Canvascanvas){

3//TODOAuto-generatedmethodstub

4canvas.drawBitmap(mBackBitmap,0,0,null);

5

6if(isExchange){

7//inexchangearea,weshouldsetalpha

8PaintmPaint=newPaint();

9

10intalpha=(int)(255-255*(buttonY-25.5)/50);

11mPaint.setAlpha(alpha);

12canvas.drawBitmap(mONBitmap,buttonTopX,buttonY,mPaint);

13canvas.drawBitmap(mOFFTextBitmap,textBottomX,textBottomY,mPaint);

14

15mPaint.setAlpha(255-alpha);

16canvas.drawBitmap(mOFFBitmap,buttonBottomX,buttonY,mPaint);

17canvas.drawBitmap(mONTextBitmap,textTopX,textTopY,mPaint);

18}else{

19if(getNearLocation(0,buttonY)==STATUS_ON){

20canvas.drawBitmap(mONBitmap,buttonTopX,buttonY,null);

21canvas.drawBitmap(mOFFTextBitmap,textBottomX,textBottomY,null);

22}else{

23canvas.drawBitmap(mOFFBitmap,buttonBottomX,buttonY,null);

24canvas.drawBitmap(mONTextBitmap,textTopX,textTopY,null);

25}

26}

27}

ViewCode

 

onTouchEvent():

1@Override

2publicbooleanonTouchEvent(MotionEventevent){

3//TODOAuto-generatedmethodstub

4

5floatx=event.getX();

6floaty=event.getY();

7switch(event.getAction()){

8caseMotionEvent.ACTION_DOWN:

9

10if(isTouchDownAnotherSide){

11returntrue;

12}

13

14//checkiftouchrightplace

15if(isOutOfFrontBitmap(x,y)){

16isTouchDownValid=false;

17returntrue;

18}

19

20if(listener!

=null){

21listener.touchedDown();

22}

23

24if(isInFrontBitmap(x,y)){

25//touchincurrentmode

26Log.e("Slip","ACTION_DOWN:

yes!

infrontBitmap");

27isTouchDownValid=true;

28touchDownGap=getGap(x,y);

29}else{

30//touchantherside

31Log.e("Slip","ACTION_DOWN:

no!

infrontBitmap");

32isTouchDownValid=false;

33isTouchDownAnotherSide=true;

34if(button_status==STATUS_ON){

35isToBottom=true;

36mHandler.sendEmptyMessage(0);

37}else{

38isToBottom=false;

39mHandler.sendEmptyMessage(0);

40}

41}

42break;

43caseMotionEvent.ACTION_MOVE:

44//iftouchdownwrongplace,weignorenextaction

45if(!

isTouchDownValid||isTouchDownAnotherSide){

46returntrue;

47}

48if(!

isInBackBitmap(x,y)){

49Log.e("Slip","ACTION_MOVE:

no!

isInBackBitmap");

50returntrue;

51}

52if(isInExchangeArea(x,y)){

53isExchange=true;

54}else{

55isExchange=false;

56}

57buttonY=y-touchDownGap;

58this.invalidate();

59

60break;

61caseMotionEvent.ACTION_UP:

62//iftouchdownwrongplace,weignorenextaction

63if(!

isTouchDownValid||isTouchDownAnotherSide){

64Log.e("Slip","ACTION_UP:

no!

isTouchDownValid");

65returntrue;

66}

67

68isExchange=false;

69

70if(getFinalLocation(x,y)==STATUS_ON){

71buttonY=buttonTopY;

72if(button_status!

=STATUS_ON){

73button_status=STATUS_ON;

74Log.e("Slip","ACTION_UP:

STATUS_ON!

getFinalLocation");

75if(listener!

=null){

76listener.slipToTop();

77}

78}else{

79if(listener!

=null){

80listener.touchedUp();

81}

82}

83this.invalidate();

84

85}else{

86buttonY=buttonBottomY;

87if(button_status!

=STATUS_OFF){

88button_status=STATUS_OFF;

89Log.e("Slip","ACTION_UP:

STATUS_OFF!

getFinalLocation");

90if(listener!

=null){

91listener.slipToBottom();

92}

93}else{

94if(listener!

=null){

95listener.touchedUp();

96}

97}

98this.invalidate();

99}

100

101break;

102default:

103break;

104}

105

106returntrue;

107}

ViewCode

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1