Selaa lähdekoodia

Merge branch 'master' of http://10.1.235.20:3000/ipu/android-share.git

chengwb3 8 vuotta sitten
vanhempi
commit
a39498f98f
1 muutettua tiedostoa jossa 249 lisäystä ja 48 poistoa
  1. 249 48
      wade-mobile-ui/src/com/wade/mobile/ui/comp/menu/PathMenu.java

+ 249 - 48
wade-mobile-ui/src/com/wade/mobile/ui/comp/menu/PathMenu.java

@ -3,6 +3,8 @@ package com.wade.mobile.ui.comp.menu;
3 3
import java.util.HashMap;
4 4
import java.util.Map;
5 5

6
import com.wade.mobile.ui.anim.AnimationTool;
7

6 8
import android.R.anim;
7 9
import android.content.Context;
8 10
import android.content.res.Resources;
@ -16,20 +18,19 @@ import android.view.animation.Animation.AnimationListener;
16 18
import android.widget.Button;
17 19
import android.widget.RelativeLayout;
18 20

19
import com.wade.mobile.ui.anim.AnimationTool;
20

21 21
public class PathMenu extends RelativeLayout{
22 22
	private Window window;
23 23
	private int leftMargin, bottomMargin;						//左边距和底边距
24 24
	private int contentTopHeight;								//屏幕状态栏宽高
25
	private int buttonRadius; 									//图片按钮
25
	private int buttonDiameter; 								//图片按钮
26 26
	private int radius; 										//扇形菜单半径
27
	private int originalRadius; 								//原始菜单半径
27 28
	private int timeSpent = 300; 								//最长动画耗时
28 29
	private int alpha = 127;									//透明度 0-255
29 30
	private double circle = Math.PI;							//扇形菜单占据一圈的比例,0~1 		
30
	/*
31
	private int intervalTimeSpent;                             	//菜单按钮之间的时间间隔
32
	*/
31
	
32
	//private int intervalTimeSpent;                            //菜单按钮之间的时间间隔
33
	
33 34
	private Button[] buttons;									//Path菜单按钮引用
34 35
	private int[] drawables;									//菜单子按钮的图片
35 36
	private int menuDrawable;									//菜单按钮的图片
@ -46,6 +47,13 @@ public class PathMenu extends RelativeLayout{
46 47
	
47 48
	private Map<String,Animation> animCache;					//动画缓存
48 49
	
50
	private Position position;										//pathmenu位置
51
	private boolean isLeft,isRight,isUp,isBottom;				//是否停边
52
	
53
	int screenWidth,screenHeight;
54
	
55
	private long touchStartTime;		
56
	
49 57
	/**click事件*/
50 58
	View.OnClickListener clickListener=new View.OnClickListener(){
51 59
		public void onClick(View v) {
@ -72,31 +80,48 @@ public class PathMenu extends RelativeLayout{
72 80
			int btnHeight = menuBtn.getHeight();
73 81
			switch (event.getAction()) {
74 82
			case MotionEvent.ACTION_DOWN:
83
				touchStartTime = System.currentTimeMillis();
75 84
				focusView(menuBtn);//获取焦点
76 85
				menuBtnX = menuBtn.getLeft();
77 86
				menuBtnY = menuBtn.getBottom();
78 87
				break;
79 88
			case MotionEvent.ACTION_MOVE:
80
				if(isCanDrag){
81
					int x_move = (int) event.getRawX();
82
					int y_move = (int) event.getRawY();
83
					
84
					/*滑动到一定程度时候才出发拖拽*/
85
					if(!isDrag&&((Math.abs(menuBtnX+btnWidth/2-x_move)>buttonRadius)
86
							||(Math.abs(menuBtnY+contentTopHeight-btnHeight/2-y_move)>buttonRadius))){
87
						isDrag = true;
88
					}
89
					
90
					if(isDrag){
91
						int top = y_move - btnHeight / 2 - contentTopHeight;
92
						int bottom = y_move + btnHeight / 2 - contentTopHeight;
93
						/*防止越界top,标题栏+状态栏*/
94
						if(y_move<contentTopHeight){
95
							top = -btnHeight / 2;
96
							bottom = btnHeight / 2;
89
				if(500 <= System.currentTimeMillis() - touchStartTime){ //当执行触摸时间大于0.5秒时,才执行移动;避免因屏幕敏感导致点击变成滑动事件
90
					if(isCanDrag){
91
						int x_move = (int) event.getRawX();
92
						int y_move = (int) event.getRawY();
93
						/*滑动到一定程度时候才出发拖拽*/
94
						if(!isDrag&&((Math.abs(menuBtnX+btnWidth/2-x_move)>(buttonDiameter/8))
95
								||(Math.abs(menuBtnY+contentTopHeight-btnHeight/2-y_move)>(buttonDiameter/8)))){
96
							isDrag = true;
97
						}
98
						
99
						if(isDrag){
100
							int top = y_move - btnHeight / 2 - contentTopHeight;
101
							int bottom = y_move + btnHeight / 2 - contentTopHeight;
102
							int left = x_move -  btnWidth / 2;
103
							int right = x_move + btnWidth / 2;
104
							/*防止越界top,标题栏+状态栏*/
105
							if(y_move<contentTopHeight + btnHeight/2){
106
								top = 0;
107
								bottom = btnHeight;
108
							}
109
							/*防止越界bottom*/
110
							if(screenHeight - y_move - btnHeight/2<= 0){
111
								top = screenHeight - contentTopHeight - btnHeight;
112
								bottom = screenHeight - contentTopHeight ;
113
							}
114
							if(x_move <= btnWidth/2){
115
								left = 0;
116
								right = btnWidth;
117
							}
118
							if(x_move >= screenWidth - btnWidth/2){
119
								left = screenWidth - btnWidth;
120
								right = screenWidth;
121
							}
122
							menuBtn.layout(left , top, right, bottom);
123
							menuBtn.postInvalidate();
97 124
						}
98
						menuBtn.layout(x_move - btnWidth / 2, top, x_move + btnWidth / 2, bottom);
99
						menuBtn.postInvalidate();
100 125
					}
101 126
				}
102 127
				break;
@ -119,9 +144,35 @@ public class PathMenu extends RelativeLayout{
119 144
					isDrag = false;
120 145
				}else{
121 146
					if(isOpen()){
122
						PathMenu.this.shutMenu();
147
						PathMenu.this.shutMenu(position);
123 148
					}else{
124
						PathMenu.this.openMenu();
149
						//判断靠边类型
150
						int x_up = menuBtn.getLeft();
151
						int y_up = menuBtn.getBottom();
152
						
153
						 /*根据离屏幕边框的距离判断菜单展开形状*/
154
						if (x_up + buttonDiameter/2 < originalRadius) {//x=0是指圆形按钮的最左边,而否中心
155
							isLeft = true;
156
						} else {
157
							isLeft = false;
158
						}
159
						if (screenWidth - x_up - buttonDiameter/2 < originalRadius) {
160
							isRight = true;
161
						} else {
162
							isRight = false;
163
						}
164
						if (y_up - buttonDiameter/2 - contentTopHeight< originalRadius) {
165
							isUp = true;
166
						} else {
167
							isUp = false;
168
						}
169
						if (screenHeight - y_up - buttonDiameter/2 < originalRadius) {
170
							isBottom = true;
171
						} else {
172
							isBottom = false;
173
						}
174
						position = getPosition(isLeft, isRight, isUp, isBottom);
175
						PathMenu.this.openMenu(position);
125 176
					}
126 177
				}
127 178
				break;
@ -148,9 +199,9 @@ public class PathMenu extends RelativeLayout{
148 199
	}
149 200
	
150 201
	/*********************设置属性 start*************************/
151
	public PathMenu setButtonRadius(int buttonRadius){
152
		if(this.buttonRadius<=0){
153
			this.buttonRadius = buttonRadius;
202
	public PathMenu setButtonDiameter(int buttonDiameter){
203
		if(this.buttonDiameter<=0){
204
			this.buttonDiameter = buttonDiameter;
154 205
		}
155 206
		return this;
156 207
	}
@ -158,6 +209,7 @@ public class PathMenu extends RelativeLayout{
158 209
	public PathMenu setRadius(int radius){
159 210
		if(this.radius<=0){
160 211
			this.radius = radius;
212
			this.originalRadius = radius;
161 213
		}
162 214
		return this;
163 215
	}
@ -178,7 +230,11 @@ public class PathMenu extends RelativeLayout{
178 230
		if(circle>1)
179 231
			circle = 1;
180 232
		this.circle = 2*Math.PI*circle;
181
		this.angle=(float)this.circle/(buttons.length-1);
233
		if(circle == 1){			
234
			this.angle=(float)this.circle/(buttons.length);
235
		}else {
236
			this.angle=(float)this.circle/(buttons.length - 1);
237
		}
182 238
		return this;
183 239
	}
184 240
	
@ -210,7 +266,7 @@ public class PathMenu extends RelativeLayout{
210 266
	    menuBtn.setBackgroundDrawable(resources.getDrawable(menuDrawable));  
211 267
	    this.addView(menuBtn);
212 268
	    
213
	    angle=(float)circle/(buttons.length-1);
269
//	    angle=(float)circle/(buttons.length-1);
214 270
	    
215 271
	    setVisibility(View.INVISIBLE);
216 272
	}
@ -225,18 +281,19 @@ public class PathMenu extends RelativeLayout{
225 281
		/*初始化默认值*/
226 282
		DisplayMetrics dm = new DisplayMetrics();                   		
227 283
        window.getWindowManager().getDefaultDisplay().getMetrics(dm);       //取得窗口属性  
228
        int screenWidth = (int)dm.widthPixels;                        		//窗口的宽度   
284
        screenWidth = (int)dm.widthPixels;                        		//窗口的宽度   
285
        screenHeight = (int)dm.heightPixels;
229 286
		
230 287
        /*计算标题栏和状态栏的高度*/
231 288
        if(this.contentTopHeight<=0){
232 289
        	this.contentTopHeight = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
233 290
        }
234 291
        
235
    	setButtonRadius(screenWidth / 8);
236
    	setRadius(this.buttonRadius * 2);
292
        setButtonDiameter(screenWidth / 8);
293
    	setRadius(this.buttonDiameter * 2);
237 294
		
238
		leftMargin = xposition - buttonRadius/2;
239
		bottomMargin = yposition - buttonRadius - contentTopHeight;
295
		leftMargin = xposition - buttonDiameter/2;
296
		bottomMargin = yposition - buttonDiameter - contentTopHeight;
240 297
		
241 298
		/*触发点越界时候的情况*/
242 299
		/*if(leftMargin + radius + buttonWidth > spacingWidth){
@ -249,8 +306,8 @@ public class PathMenu extends RelativeLayout{
249 306
		/*设置所有按钮的位置*/
250 307
		RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
251 308
				ViewGroup.LayoutParams.WRAP_CONTENT);
252
		params.height = buttonRadius;
253
		params.width =  buttonRadius;											
309
		params.height = buttonDiameter;
310
		params.width =  buttonDiameter;											
254 311
		params.setMargins(leftMargin, bottomMargin, 0, 0);
255 312
		
256 313
		for (int i = 0; i < buttons.length; i++) {
@ -288,13 +345,19 @@ public class PathMenu extends RelativeLayout{
288 345
		isOpen = true;
289 346
	}
290 347
	
291
	public void openMenu() {
348
	public void openMenu(Position position) {
349
//		if(position != 0 && position % 2 == 0){//当position为扇形,打开时初始半径变大1.5倍;
350
//			radius *= 1.5;
351
//		}
352
		
292 353
		int toX,toY;
293 354
		for(int i=0;i<buttons.length;i++){
294 355
			buttons[i].setVisibility(View.VISIBLE);
295 356
			
296
			toX=(int)(radius*Math.sin(i*angle-Math.PI/2));
297
			toY=(int)(radius*Math.cos(i*angle-Math.PI/2));
357
//			toX=(int)(radius*Math.sin(i*angle));
358
//			toY=(int)(radius*Math.cos(i*angle));
359
			toX = computOffset(position, i)[0];
360
			toY = computOffset(position, i)[1];
298 361
			
299 362
			Animation animation = animOpen(toX, -toY, timeSpent/*+i*intervalTimeSpent*/);
300 363
			/*animation.setFillAfter(true);*/ //达不到既定的效果
@ -309,15 +372,29 @@ public class PathMenu extends RelativeLayout{
309 372
	/**
310 373
	 * 关闭菜单
311 374
	 */
312
	public void shutMenu(){
375
	/**
376
	 * @param position
377
	 */
378
	/**
379
	 * @param position
380
	 */
381
	public void shutMenu(Position position){
313 382
		float toX, toY;
314 383
		for (int i = 0; i < buttons.length; i++) {
315
			toX=(float)(radius*Math.sin(i*angle-Math.PI/2));
316
			toY=(float)(radius*Math.cos(i*angle-Math.PI/2));
384
//			toX=(float)(radius*Math.sin(i*angle - Math.PI));
385
//			toY=(float)(radius*Math.cos(i*angle - Math.PI));
386
			
387
			toX = computOffset(position, i)[0];
388
			toY = computOffset(position, i)[1];
389
			
317 390
			buttons[i].startAnimation(animShut(buttons[i], -toX, toY, timeSpent));//点击按钮变大
318 391
		}
319 392
		isOpen = false;
320 393
		isCanDrag = true;
394
		
395
//		if(position != 0 && position % 2 == 0){//当position为扇形,关闭时恢复初始半径;
396
//			radius /= 1.5;
397
//		}
321 398
	}
322 399
	
323 400
	/************************动画效果实现start***************************/
@ -363,7 +440,7 @@ public class PathMenu extends RelativeLayout{
363 440
	public void reset(){
364 441
		/*解决Home出去时的BUG*/
365 442
		if(this.isOpen){
366
			shutMenu();
443
			shutMenu(position);
367 444
		}
368 445
		this.isOpen = false;
369 446
		this.isCanDrag = true;
@ -402,7 +479,7 @@ public class PathMenu extends RelativeLayout{
402 479
			button.clearAnimation();
403 480
			
404 481
			/*1.设置button,解决跨线程调用,Handle的实现在ViewRoot中,触发invalidate()*/
405
			button.layout(left, bottom,left+buttonRadius, bottom+buttonRadius);
482
			button.layout(left, bottom,left+buttonDiameter, bottom+buttonDiameter);
406 483
			button.postInvalidate();
407 484
			/*2.最原始的方式设置button*/
408 485
			/*RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
@ -428,4 +505,128 @@ public class PathMenu extends RelativeLayout{
428 505
	public void setOnButtonClickListener(OnButtonClickListener onButtonClickListener){
429 506
		this.onButtonClickListener = onButtonClickListener;
430 507
	}
431
}
508
	
509
	/********展开形状判定**********/
510
	public static enum Position {
511
		CENTER(0),				//中心正圆
512
	    TOP_CENTER(1),			//上中半圆
513
	    TOP_RIGHT(2),			//上右扇形
514
	    RIGHT_CENTER(3),		//右中半圆
515
	    BOTTOM_RIGHT(4),		//底右扇形
516
	    BOTTOM_CENTER(5),		//底中半圆
517
	    BOTTOM_LEFT(6),			//底左扇形
518
	    LEFT_CENTER(7),			//左中半圆
519
	    TOP_LEFT(8);			//上左扇形
520
	    
521
		private int position;
522

523
		private Position(int position) {
524
			this.position = position;
525
		}
526

527
		public int getPosition() {
528
			return this.position;
529
		}
530
	}
531
	
532
	/**
533
	 * 通过距离动态判断停靠位置
534
	 * @param isLeft
535
	 * @param isRight
536
	 * @param isUp
537
	 * @param isBottom
538
	 * @return
539
	 */
540
	private Position getPosition(boolean isLeft,boolean isRight,boolean isUp,boolean isBottom){
541
		if (isBottom) {
542
			if(isRight){
543
				return Position.BOTTOM_RIGHT;
544
			}else if (isLeft) {
545
				return Position.BOTTOM_LEFT;
546
			}else{
547
				return Position.BOTTOM_CENTER;
548
			}
549
		}else if (isUp) {
550
			if(isRight){
551
				return Position.TOP_RIGHT;
552
			}else if (isLeft) {
553
				return Position.TOP_LEFT;
554
			}else{
555
				return Position.TOP_CENTER;
556
			}
557
		}else if (isRight) {
558
			return Position.RIGHT_CENTER;
559
		}else if (isLeft) {
560
			return Position.LEFT_CENTER;
561
		}else{
562
			return Position.CENTER;
563
		}
564
	}
565
	/**
566
	 * 偏移量计算
567
	 */
568
	private int[] computOffset(Position position,int i){
569
		int toX = 0,toY =0 ;
570
		radius = buttonDiameter * 2;
571
		if(position.getPosition() != 0 && position.getPosition() % 2 == 0){//当position为扇形,打开时初始半径变大1.5倍;
572
			radius *= 1.5;
573
		}
574
		switch (position) {
575
		case CENTER:
576
			setCircle(1);
577
			toX =(int)(radius*Math.sin(i*angle));
578
			toY =(int)(radius*Math.cos(i*angle));
579
			break;
580
		case TOP_CENTER:
581
			setCircle(0.5f);
582
			toX = (int)(radius*Math.sin(i*angle + Math.PI/2));
583
			toY = (int)(radius*Math.cos(i*angle + Math.PI/2));
584
			break;
585
		case TOP_RIGHT:
586
			setCircle(0.25f);
587
			toX = (int)(radius*Math.sin(i*angle + Math.PI));
588
			toY = (int)(radius*Math.cos(i*angle + Math.PI));
589
			break;
590
		case RIGHT_CENTER:
591
			setCircle(0.5f);
592
			toX = (int)(radius*Math.sin(i*angle + Math.PI));
593
			toY = (int)(radius*Math.cos(i*angle + Math.PI));
594
			break;
595
		case BOTTOM_RIGHT:
596
			setCircle(0.25f);
597
			toX = (int)(radius*Math.sin(i*angle - Math.PI/2));
598
			toY = (int)(radius*Math.cos(i*angle - Math.PI/2));
599
			break;
600
		case BOTTOM_CENTER:
601
			setCircle(0.5f);
602
			toX = (int)(radius*Math.sin(i*angle - Math.PI/2));
603
			toY = (int)(radius*Math.cos(i*angle - Math.PI/2));
604
			break;
605
		case BOTTOM_LEFT:
606
			setCircle(0.25f);
607
			toX = (int)(radius*Math.sin(i*angle));
608
			toY = (int)(radius*Math.cos(i*angle));
609
			break;
610
		case LEFT_CENTER:
611
			setCircle(0.5f);
612
			toX = (int)(radius*Math.sin(i*angle));
613
			toY = (int)(radius*Math.cos(i*angle));
614
			break;
615
		case TOP_LEFT:
616
			setCircle(0.25f);
617
			toX = (int)(radius*Math.sin(i*angle + Math.PI/2));
618
			toY = (int)(radius*Math.cos(i*angle + Math.PI/2));
619
			break;
620
		default:
621
			break;
622
		}
623
		int [] xy = {toX,toY};
624
		return xy;
625
	}
626
	
627
	public PathMenu setPosition(Position position){
628
		this.position = position;
629
		return this;
630
	}
631
	
632
}