Преглед на файлове

移除快捷入口源码

leijie преди 8 години
родител
ревизия
5eabf9a36e
променени са 28 файла, в които са добавени 0 реда и са изтрити 967 реда
  1. 0 9
      ipupathmenu/.classpath
  2. 0 2
      ipupathmenu/.gitignore
  3. 0 27
      ipupathmenu/AndroidManifest.xml
  4. 0 20
      ipupathmenu/proguard-project.txt
  5. 0 15
      ipupathmenu/project.properties
  6. BIN
      ipupathmenu/res/drawable-hdpi/composer_button.png
  7. BIN
      ipupathmenu/res/drawable-hdpi/composer_camera.png
  8. BIN
      ipupathmenu/res/drawable-hdpi/composer_icn_plus.png
  9. BIN
      ipupathmenu/res/drawable-hdpi/composer_music.png
  10. BIN
      ipupathmenu/res/drawable-hdpi/composer_place.png
  11. BIN
      ipupathmenu/res/drawable-hdpi/composer_sleep.png
  12. BIN
      ipupathmenu/res/drawable-hdpi/composer_sun.png
  13. BIN
      ipupathmenu/res/drawable-hdpi/composer_thought.png
  14. BIN
      ipupathmenu/res/drawable-hdpi/composer_with.png
  15. BIN
      ipupathmenu/res/drawable-hdpi/friends_delete.png
  16. BIN
      ipupathmenu/res/drawable-hdpi/ic_launcher.png
  17. BIN
      ipupathmenu/res/drawable-mdpi/ic_launcher.png
  18. BIN
      ipupathmenu/res/drawable-xhdpi/ic_launcher.png
  19. BIN
      ipupathmenu/res/drawable-xxhdpi/ic_launcher.png
  20. 0 11
      ipupathmenu/res/values-v11/styles.xml
  21. 0 12
      ipupathmenu/res/values-v14/styles.xml
  22. 0 10
      ipupathmenu/res/values-w820dp/dimens.xml
  23. 0 7
      ipupathmenu/res/values/dimens.xml
  24. 0 6
      ipupathmenu/res/values/strings.xml
  25. 0 20
      ipupathmenu/res/values/styles.xml
  26. 0 106
      ipupathmenu/src/com/ai/ipu/ipupathmenu/AnimationTool.java
  27. 0 106
      ipupathmenu/src/com/ai/ipu/ipupathmenu/MainActivity.java
  28. 0 616
      ipupathmenu/src/com/ai/ipu/ipupathmenu/PathMenu.java

+ 0 - 9
ipupathmenu/.classpath

@ -1,9 +0,0 @@
1
<?xml version="1.0" encoding="UTF-8"?>
2
<classpath>
3
	<classpathentry kind="src" path="src"/>
4
	<classpathentry kind="src" path="gen"/>
5
	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
6
	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
7
	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
8
	<classpathentry kind="output" path="bin/classes"/>
9
</classpath>

+ 0 - 2
ipupathmenu/.gitignore

@ -1,2 +0,0 @@
1
/gen/
2
/bin/

+ 0 - 27
ipupathmenu/AndroidManifest.xml

@ -1,27 +0,0 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
    package="com.ai.ipu.ipupathmenu"
4
    android:versionCode="1"
5
    android:versionName="1.0" >
6
7
    <uses-sdk
8
        android:minSdkVersion="15"
9
        android:targetSdkVersion="21" />
10
11
    <application
12
        android:allowBackup="true"
13
        android:icon="@drawable/ic_launcher"
14
        android:label="@string/app_name"
15
        android:theme="@style/AppTheme" >
16
        <activity
17
            android:name=".MainActivity"
18
            android:label="@string/app_name" >
19
            <intent-filter>
20
                <action android:name="android.intent.action.MAIN" />
21
22
                <category android:name="android.intent.category.LAUNCHER" />
23
            </intent-filter>
24
        </activity>
25
    </application>
26
27
</manifest>

+ 0 - 20
ipupathmenu/proguard-project.txt

@ -1,20 +0,0 @@
1
# To enable ProGuard in your project, edit project.properties
2
# to define the proguard.config property as described in that file.
3
#
4
# Add project specific ProGuard rules here.
5
# By default, the flags in this file are appended to flags specified
6
# in ${sdk.dir}/tools/proguard/proguard-android.txt
7
# You can edit the include path and order by changing the ProGuard
8
# include property in project.properties.
9
#
10
# For more details, see
11
#   http://developer.android.com/guide/developing/tools/proguard.html
12
13
# Add any project specific keep options here:
14
15
# If your project uses WebView with JS, uncomment the following
16
# and specify the fully qualified class name to the JavaScript interface
17
# class:
18
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19
#   public *;
20
#}

+ 0 - 15
ipupathmenu/project.properties

@ -1,15 +0,0 @@
1
# This file is automatically generated by Android Tools.
2
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3
#
4
# This file must be checked in Version Control Systems.
5
#
6
# To customize properties used by the Ant build system edit
7
# "ant.properties", and override values to adapt the script to your
8
# project structure.
9
#
10
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12
13
# Project target.
14
target=android-22
15
android.library=true

BIN
ipupathmenu/res/drawable-hdpi/composer_button.png


BIN
ipupathmenu/res/drawable-hdpi/composer_camera.png


BIN
ipupathmenu/res/drawable-hdpi/composer_icn_plus.png


BIN
ipupathmenu/res/drawable-hdpi/composer_music.png


BIN
ipupathmenu/res/drawable-hdpi/composer_place.png


BIN
ipupathmenu/res/drawable-hdpi/composer_sleep.png


BIN
ipupathmenu/res/drawable-hdpi/composer_sun.png


BIN
ipupathmenu/res/drawable-hdpi/composer_thought.png


BIN
ipupathmenu/res/drawable-hdpi/composer_with.png


BIN
ipupathmenu/res/drawable-hdpi/friends_delete.png


BIN
ipupathmenu/res/drawable-hdpi/ic_launcher.png


BIN
ipupathmenu/res/drawable-mdpi/ic_launcher.png


BIN
ipupathmenu/res/drawable-xhdpi/ic_launcher.png


BIN
ipupathmenu/res/drawable-xxhdpi/ic_launcher.png


+ 0 - 11
ipupathmenu/res/values-v11/styles.xml

@ -1,11 +0,0 @@
1
<resources>
2
3
    <!--
4
        Base application theme for API 11+. This theme completely replaces
5
        AppBaseTheme from res/values/styles.xml on API 11+ devices.
6
    -->
7
    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
8
        <!-- API 11 theme customizations can go here. -->
9
    </style>
10
11
</resources>

+ 0 - 12
ipupathmenu/res/values-v14/styles.xml

@ -1,12 +0,0 @@
1
<resources>
2
3
    <!--
4
        Base application theme for API 14+. This theme completely replaces
5
        AppBaseTheme from BOTH res/values/styles.xml and
6
        res/values-v11/styles.xml on API 14+ devices.
7
    -->
8
    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
9
        <!-- API 14 theme customizations can go here. -->
10
    </style>
11
12
</resources>

+ 0 - 10
ipupathmenu/res/values-w820dp/dimens.xml

@ -1,10 +0,0 @@
1
<resources>
2
3
    <!--
4
         Example customization of dimensions originally defined in res/values/dimens.xml
5
         (such as screen margins) for screens with more than 820dp of available width. This
6
         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
7
    -->
8
    <dimen name="activity_horizontal_margin">64dp</dimen>
9
10
</resources>

+ 0 - 7
ipupathmenu/res/values/dimens.xml

@ -1,7 +0,0 @@
1
<resources>
2
3
    <!-- Default screen margins, per the Android Design guidelines. -->
4
    <dimen name="activity_horizontal_margin">16dp</dimen>
5
    <dimen name="activity_vertical_margin">16dp</dimen>
6
7
</resources>

+ 0 - 6
ipupathmenu/res/values/strings.xml

@ -1,6 +0,0 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<resources>
3
4
    <string name="app_name">ipu快捷菜单</string>
5
6
</resources>

+ 0 - 20
ipupathmenu/res/values/styles.xml

@ -1,20 +0,0 @@
1
<resources>
2
3
    <!--
4
        Base application theme, dependent on API level. This theme is replaced
5
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
6
    -->
7
    <style name="AppBaseTheme" parent="android:Theme.Light">
8
        <!--
9
            Theme customizations available in newer API levels can go in
10
            res/values-vXX/styles.xml, while customizations related to
11
            backward-compatibility can go here.
12
        -->
13
    </style>
14
15
    <!-- Application theme. -->
16
    <style name="AppTheme" parent="AppBaseTheme">
17
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18
    </style>
19
20
</resources>

+ 0 - 106
ipupathmenu/src/com/ai/ipu/ipupathmenu/AnimationTool.java

@ -1,106 +0,0 @@
1
package com.ai.ipu.ipupathmenu;
2

3
import android.R.anim;
4
import android.content.Context;
5
import android.view.animation.AlphaAnimation;
6
import android.view.animation.Animation;
7
import android.view.animation.AnimationSet;
8
import android.view.animation.RotateAnimation;
9
import android.view.animation.ScaleAnimation;
10
import android.view.animation.TranslateAnimation;
11

12
public class AnimationTool {
13
	/**
14
	 * 位移动化
15
	 * @param fromX					位移起始X坐标
16
	 * @param fromY					位移起始Y坐标
17
	 * @param toX					位移结束X坐标
18
	 * @param toY					位移结束Y坐标
19
	 * @param durationMillis		动画时长
20
	 */
21
	public static TranslateAnimation createTranslate(float fromX, float fromY, float toX, float toY, long durationMillis) {
22
		// TODO Auto-generated method stub
23
		TranslateAnimation animation = new TranslateAnimation(fromX, toX, fromY, toY);	
24
		animation.setDuration(durationMillis);
25
		return animation;
26
	}
27
	
28
	/**
29
	 * 转移旋转动画
30
	 * @param toDegrees 			旋转角度,负号表示逆时针旋转。
31
	 * @param pivotX				偏离X中心轴的尺寸(单位为对象自身长度?)
32
	 * @param pivotY				偏离Y中心轴的尺寸(单位为对象自身长度?)
33
	 * @param durationMillis		动画时长
34
	 * 设置RELATIVE_TO_SELF表明所有参数是相对于对象自己
35
	 */
36
	public static RotateAnimation createRotate(float toDegrees, float pivotX, float pivotY, long durationMillis) {
37
		// TODO Auto-generated method stub
38
		RotateAnimation animation = new RotateAnimation(0, toDegrees, Animation.RELATIVE_TO_SELF, pivotX, Animation.RELATIVE_TO_SELF, pivotY);
39
		animation.setDuration(durationMillis);
40
		return animation;
41
	}
42
	
43
	/**
44
	 * 尺寸伸缩动画
45
	 * @param toX					尺寸动画结束时在X坐标上的伸缩尺寸 
46
	 * @param toY					尺寸动画结束时在Y坐标上的伸缩尺寸 
47
	 * @param durationMillis		动画时长
48
	 * @param float pivotX 			动画相对于物件的X坐标的开始位置
49
	 * @param float pivotY			 动画相对于物件的Y坐标的开始位置 
50
	 * 0.0表示收缩到没有,1.0表示正常无伸缩,值小于1.0表示收缩,值大于1.0表示放大
51
	 * 设置RELATIVE_TO_SELF表明所有参数是相对于对象自己
52
	 */
53
	public static ScaleAnimation createScale(float toX, float toY, float pivotX, float pivotY, long durationMillis) {
54
		ScaleAnimation animation = new ScaleAnimation(1.0f, toX, 1.0f, toY, Animation.RELATIVE_TO_SELF, pivotX, Animation.RELATIVE_TO_SELF, pivotY);
55
		animation.setDuration(durationMillis);
56
		return animation;
57
	}
58
	
59
	/**
60
	 * 渐变透明度动画
61
	 * @param fromAlpha				动画起始透明度 
62
	 * @param toAlpha				动画结束透明度 
63
	 * @param durationMillis		动画时长
64
	 * @return
65
	 */
66
	public static AlphaAnimation createAlpha(float fromAlpha, float toAlpha, long durationMillis) {
67
		// TODO Auto-generated method stub
68
		AlphaAnimation animation = new AlphaAnimation(fromAlpha, toAlpha);
69
		animation.setDuration(durationMillis);
70
		return animation;
71
	}
72
	
73
	/**
74
	 * 创建混合动画
75
	 * @param animations
76
	 */
77
	public static AnimationSet createSet(Animation ... animations){
78
		AnimationSet animationSet = new AnimationSet(true);
79
		for(Animation animation : animations){
80
			animationSet.addAnimation(animation);
81
		}
82
		return animationSet;
83
	}
84
	
85
	/**
86
	 * 指定动画插入器 
87
	 * accelerate_decelerate_interpolator  加速-减速 动画 
88
     * accelerate_interpolator        加速-动画
89
     * decelerate_interpolator        减速- 动画
90
	 */
91
	public static void setInterpolator(Animation animation, Context context, int resID) {
92
		// TODO Auto-generated method stub
93
		if(resID < 0){
94
			resID = anim.accelerate_decelerate_interpolator;
95
		}
96
		animation.setInterpolator(context, resID);
97
	}
98
	
99
	/**
100
	 * 动画结束后是否填充,默认不填充,可以使用在Set对象上
101
	 */
102
	public static void setFillAfter(Animation animation,boolean isFill) {
103
		// TODO Auto-generated method stub
104
		animation.setFillAfter(isFill);
105
	}
106
}

+ 0 - 106
ipupathmenu/src/com/ai/ipu/ipupathmenu/MainActivity.java

@ -1,106 +0,0 @@
1
package com.ai.ipu.ipupathmenu;
2

3
import android.app.Activity;
4
import android.graphics.Rect;
5
import android.os.Bundle;
6
import android.util.DisplayMetrics;
7
import android.view.View;
8
import android.view.ViewGroup;
9
import android.view.ViewGroup.LayoutParams;
10
import android.webkit.WebView;
11
import android.widget.FrameLayout;
12
import android.widget.LinearLayout;
13

14
public class MainActivity extends Activity {
15

16
	/*声明各控件*/	
17
	private WebView webView = null;
18
	private LinearLayout linearLayout = null;
19
	private static PathMenu pathMenu = null;
20

21
	private int menuDrawable = R.drawable.friends_delete;
22
	//pathMenu中button的图片
23
	private static int[] drawables = {							   
24
		R.drawable.composer_sleep,
25
		R.drawable.composer_thought,
26
		R.drawable.composer_music,
27
		R.drawable.composer_place,
28
		R.drawable.composer_with,
29
		R.drawable.composer_camera
30
	};   
31
	 
32
	public void onCreate(Bundle savedInstanceState){
33
        super.onCreate(savedInstanceState);
34
        
35
//        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
36
//				WindowManager.LayoutParams.FLAG_FULLSCREEN);// 隐藏状态栏
37
//		getWindow().requestFeature(Window.FEATURE_NO_TITLE);// 隐藏标题栏
38
		
39
        /*构建主界面*/
40
        setContentView(createMenu());
41
        
42
        pathMenu.setOnButtonClickListener(new PathMenu.OnButtonClickListener() {
43
			public void onButtonClick(View v, int id) {
44
				//点击扇行菜单事件
45
				if(id==0) webView.loadUrl("http://js.wap.ifeng.com/");
46
				if(id==1) webView.loadUrl("http://wap.taobao.com/");
47
				if(id==2) webView.loadUrl("http://wap.163.com/");
48
				if(id==3) webView.loadUrl("http://www.google.com.hk/intl/zh-CN/mobile/");
49
				if(id==4) webView.loadUrl("http://m.sohu.com/");
50
				if(id==5) webView.loadUrl("http://sina.cn/");
51
			}
52
		});
53
        
54
        pathMenu.setCircle(0.5f);
55
    }
56
	
57
	/**
58
	 * 窗体构建以后才能获取标题栏+状态栏的高度
59
	 */
60
	@Override
61
	public void onWindowFocusChanged(boolean hasFocus) {
62
		// TODO Auto-generated method stub
63
		super.onWindowFocusChanged(hasFocus);
64
		DisplayMetrics dm = new DisplayMetrics();                   		
65
        getWindowManager().getDefaultDisplay().getMetrics(dm);       		//取得窗口属性  
66
        int screenWidth = (int)dm.widthPixels;                        		//窗口的宽度   
67
        int screenHeight = (int)dm.heightPixels;                      		//窗口高度 
68
        
69
		Rect frame = new Rect();
70
		getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
71
		
72
        /*设置菜单初始位置*/
73
        pathMenu.setPosition((int)screenWidth/2, (int)screenHeight);
74
	}
75
	
76
	private View createMenu() {
77
		// TODO Auto-generated method stub
78
		linearLayout = new LinearLayout(this);
79
		linearLayout.setLayoutParams(new ViewGroup.LayoutParams(
80
				ViewGroup.LayoutParams.MATCH_PARENT,
81
				ViewGroup.LayoutParams.MATCH_PARENT));
82
		linearLayout.setOrientation(LinearLayout.VERTICAL);
83
		
84
		FrameLayout frameLayout = new FrameLayout(this);
85
		
86
		webView = new WebView(this);
87
		webView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
88
		frameLayout.addView(webView);
89
		
90
		pathMenu = new PathMenu(getWindow(), this, drawables, menuDrawable, true);
91
		
92
		pathMenu.setPosition(PathMenu.POSITION_BOTTOM_RIGHT);
93
		
94
        frameLayout.addView(pathMenu);
95
		linearLayout.addView(frameLayout);
96

97
		return linearLayout;
98
	}
99
	
100
	@Override
101
	protected void onRestart() {
102
		// TODO Auto-generated method stub
103
		super.onRestart();
104
		pathMenu.reset();
105
	}
106
}

+ 0 - 616
ipupathmenu/src/com/ai/ipu/ipupathmenu/PathMenu.java

@ -1,616 +0,0 @@
1
package com.ai.ipu.ipupathmenu;
2

3
import java.util.HashMap;
4
import java.util.Map;
5

6
import android.R.anim;
7
import android.content.Context;
8
import android.content.res.Resources;
9
import android.util.DisplayMetrics;
10
import android.view.MotionEvent;
11
import android.view.View;
12
import android.view.ViewGroup;
13
import android.view.Window;
14
import android.view.animation.Animation;
15
import android.view.animation.Animation.AnimationListener;
16
import android.widget.Button;
17
import android.widget.RelativeLayout;
18

19
public class PathMenu extends RelativeLayout{
20
	private Window window;
21
	private int leftMargin, bottomMargin;						//左边距和底边距
22
	private int contentTopHeight;								//屏幕状态栏宽高
23
	private int buttonRadius; 									//图片按钮半径
24
	private int radius; 										//扇形菜单半径
25
	private int timeSpent = 300; 								//最长动画耗时
26
	private int alpha = 127;									//透明度 0-255
27
	private double circle = Math.PI;							//扇形菜单占据一圈的比例,0~1 		
28
	/*
29
	private final int maxTimeSpent = 1000; 						//最长动画耗时
30
	private final int minTimeSpent = 400;                       //最短动画耗时
31
	private int intervalTimeSpent;                             	//菜单按钮之间的时间间隔
32
	*/
33
	private Button[] buttons;									//Path菜单按钮引用
34
	private int[] drawables;									//菜单子按钮的图片
35
	private int menuDrawable;									//菜单按钮的图片
36
	private float angle;                                       	//菜单按钮之间的夹角
37
	
38
	private Button menuBtn;										//菜单主按钮
39
	private int menuBtnX;										//记录菜单按钮坐标
40
	private int menuBtnY;										//记录菜单按钮坐标
41
	
42
	private boolean isOpen;										//菜单是否被打开
43
	private boolean isDrag;										//是否拖拽中	
44
	
45
	private boolean isCanDrag;									//是否能拖拽
46
	
47
	private Map<String,Animation> animCache;					//动画缓存
48
	
49
	private int position;			//pathmenu位置
50
	
51
	private int distance; 										//圆弧按钮的最大边距
52
	
53
	private boolean isLeft,isRight,isUp,isBottom;				//是否停边
54
	
55
	int screenWidth,screenHeight;
56
	
57
	/**click事件*/
58
	View.OnClickListener clickListener=new View.OnClickListener(){
59
		public void onClick(View v) {
60
			int selectedItem = Integer.parseInt((String) v.getTag());
61
			for (int i = 0; i < buttons.length; i++) {
62
				if (i == selectedItem) {
63
					buttons[i].startAnimation(animClick(buttons[i], 2.0f, 2.0f, timeSpent));//点击按钮变大
64
				} else {
65
					buttons[i].startAnimation(animClick(buttons[i], 0.1f, 0.1f, timeSpent));//其他按钮变小
66
				}
67
			}
68
			if (onButtonClickListener != null) {
69
				onButtonClickListener.onButtonClick(v, selectedItem);
70
			}
71
		}
72
	};
73
	
74
	View.OnTouchListener touchListener = new View.OnTouchListener(){
75
		@Override
76
		public boolean onTouch(View view, MotionEvent event) {
77
			// TODO Auto-generated method stub
78
			//menuBtn和view为同一个对象
79
			int btnWidth = menuBtn.getWidth();
80
			int btnHeight = menuBtn.getHeight();
81
			switch (event.getAction()) {
82
			case MotionEvent.ACTION_DOWN:
83
				focusView(menuBtn);//获取焦点
84
				menuBtnX = menuBtn.getLeft();
85
				menuBtnY = menuBtn.getBottom();
86
				break;
87
			case MotionEvent.ACTION_MOVE:
88
				if(isCanDrag){
89
					int x_move = (int) event.getRawX();
90
					int y_move = (int) event.getRawY();
91
					/*滑动到一定程度时候才出发拖拽*/
92
					if(!isDrag&&((Math.abs(menuBtnX+btnWidth/2-x_move)>buttonRadius)
93
							||(Math.abs(menuBtnY+contentTopHeight-btnHeight/2-y_move)>buttonRadius))){
94
						isDrag = true;
95
					}
96
					
97
					if(isDrag){
98
						int top = y_move - btnHeight / 2 - contentTopHeight;
99
						int bottom = y_move + btnHeight / 2 - contentTopHeight;
100
						int left = x_move -  btnWidth / 2;
101
						int right = x_move + btnWidth / 2;
102
						/*防止越界top,标题栏+状态栏*/
103
						if(y_move<contentTopHeight + btnHeight/2){
104
							top = 0;
105
							bottom = btnHeight;
106
						}
107
						/*防止越界bottom*/
108
						if(screenHeight - y_move - btnHeight/2<= 0){
109
							top = screenHeight - contentTopHeight - btnHeight;
110
							bottom = screenHeight - contentTopHeight ;
111
						}
112
						if(x_move <= btnWidth/2){
113
							left = 0;
114
							right = btnWidth;
115
						}
116
						if(x_move >= screenWidth - btnWidth/2){
117
							left = screenWidth - btnWidth;
118
							right = screenWidth;
119
						}
120
						menuBtn.layout(left , top, right, bottom);
121
						menuBtn.postInvalidate();
122
					}
123
				}
124
				break;
125
			case MotionEvent.ACTION_UP:
126
				if(!isOpen()){
127
					int x_up = menuBtn.getLeft();
128
					int y_up = menuBtn.getBottom();
129
					leftMargin = x_up;
130
					bottomMargin = y_up-btnHeight;
131
					for (int i = 0; i < buttons.length; i++) {
132
						buttons[i].layout(x_up, y_up-btnHeight, x_up + btnWidth, y_up);
133
						buttons[i].postInvalidate();
134
						if(buttons[i].getVisibility()==View.VISIBLE){
135
							buttons[i].setVisibility(View.INVISIBLE);
136
						}
137
					}
138
				}
139
				
140
				if(isDrag){
141
					isDrag = false;
142
				}else{
143
					if(isOpen()){
144
						PathMenu.this.shutMenu(position);
145
					}else{
146
						//判断靠边类型
147
						int x_up = menuBtn.getLeft();
148
						int y_up = menuBtn.getBottom();
149
						
150
						distance = radius + buttonRadius;
151
						if(x_up  + buttonRadius < distance){
152
							isLeft = true;
153
						}else {
154
							isLeft = false;
155
						}
156
						if ( (screenWidth - x_up -buttonRadius)  < distance) {
157
							isRight = true;
158
						}else {
159
							isRight = false;
160
						}
161
						if(y_up + buttonRadius - contentTopHeight < distance){
162
							isUp = true;
163
						}else {
164
							isUp = false;
165
						}
166
						if((screenHeight - y_up - contentTopHeight - buttonRadius) < distance){
167
							isBottom = true;
168
						}else {
169
							isBottom = false;
170
						}
171
						position = getPosition(isLeft, isRight, isUp, isBottom);
172
						PathMenu.this.openMenu(position);
173
					}
174
				}
175
				break;
176
			default:
177
				break;
178
			}
179
			return false;
180
		}
181
		
182
	};
183
	
184
	public PathMenu(Window window, Context context, int[] drawables, int menuDrawable, boolean isCanDrag){
185
		super(context);
186
		this.window = window; 
187
		this.drawables = drawables;
188
		this.menuDrawable = menuDrawable;
189
		this.isCanDrag = isCanDrag;
190
		animCache = new HashMap<String,Animation>();
191
		onFinishInflate();//构建界面
192
	}
193
	
194
	public PathMenu(Window window, Context context, int[] drawables, int menuDrawable){
195
		this(window, context, drawables, menuDrawable, false);
196
	}
197
	
198
	/*********************设置属性 start*************************/
199
	public PathMenu setButtonRadius(int buttonRadius){
200
		if(this.buttonRadius<=0){
201
			this.buttonRadius = buttonRadius;
202
		}
203
		return this;
204
	}
205
	
206
	public PathMenu setRadius(int radius){
207
		if(this.radius<=0){
208
			this.radius = radius;
209
		}
210
		return this;
211
	}
212
	
213
	public PathMenu setTimeSpent(int timeSpent){
214
		this.timeSpent = timeSpent;
215
		return this;
216
	}
217
	
218
	public PathMenu setAlpha(int alpha){
219
		this.alpha = alpha;
220
		return this;
221
	}
222
	
223
	public PathMenu setCircle(float circle){
224
		if(circle<0)
225
			circle = 0;
226
		if(circle>1)
227
			circle = 1;
228
		this.circle = 2*Math.PI*circle;
229
		if(circle == 1){			
230
			this.angle=(float)this.circle/(buttons.length);
231
		}else {
232
			this.angle=(float)this.circle/(buttons.length - 1);
233
		}
234
		return this;
235
	}
236
	
237
	/*********************设置属性 end***************************/
238
	/**
239
	 * 构建布局
240
	 */
241
	protected void onFinishInflate() {
242
		super.onFinishInflate();
243
		
244
	    this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
245
	        
246
	    Resources resources = this.getResources();
247
	    /*构建菜单按钮*/
248
	    int menuNum = drawables.length;
249
	    buttons=new Button[menuNum];
250
	    for(int i=0;i<menuNum;i++){
251
	    	buttons[i] = new Button(getContext());
252
	    	buttons[i].setTag(String.valueOf(i));
253
			buttons[i].setOnClickListener(clickListener);
254
	    	buttons[i].setBackgroundDrawable(resources.getDrawable(drawables[i]));
255
	 	    this.addView(buttons[i]);
256
	    }
257
		
258
	    /*构建取消按钮*/
259
	    menuBtn = new Button(getContext());
260
	    menuBtn.setTag(String.valueOf(menuNum));
261
	    menuBtn.setOnTouchListener(touchListener);
262
	    menuBtn.setBackgroundDrawable(resources.getDrawable(menuDrawable));  
263
	    this.addView(menuBtn);
264
	    
265
//	    angle=(float)circle/(buttons.length-1);
266
	    
267
	    setVisibility(View.INVISIBLE);
268
	}
269
	
270
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
271
		super.onSizeChanged(w, h, oldw, oldh);
272
	}
273
	
274
	/***********************对外提供方法**************************/
275
	public void setPosition(int xposition, int yposition) {
276
		// TODO Auto-generated method stub
277
		/*初始化默认值*/
278
		DisplayMetrics dm = new DisplayMetrics();                   		
279
        window.getWindowManager().getDefaultDisplay().getMetrics(dm);       //取得窗口属性  
280
        screenWidth = (int)dm.widthPixels;                        		//窗口的宽度   
281
        screenHeight = (int)dm.heightPixels;
282
		
283
        /*计算标题栏和状态栏的高度*/
284
        if(this.contentTopHeight<=0){
285
        	this.contentTopHeight = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
286
        }
287
        
288
    	setButtonRadius(screenWidth / 8);
289
    	setRadius(this.buttonRadius * 2);
290
		
291
		leftMargin = xposition - buttonRadius/2;
292
		bottomMargin = yposition - buttonRadius - contentTopHeight;
293
		
294
		/*触发点越界时候的情况*/
295
		/*if(leftMargin + radius + buttonWidth > spacingWidth){
296
			leftMargin = spacingWidth - radius - buttonWidth;
297
		}*/
298
		/*if(bottomMargin - buttonWidth < spacingHeight){
299
			bottomMargin = (buttonWidth + (spacingHeight));
300
		}*/
301
		
302
		/*设置所有按钮的位置*/
303
		RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
304
				ViewGroup.LayoutParams.WRAP_CONTENT);
305
		params.height = buttonRadius;
306
		params.width =  buttonRadius;											
307
		params.setMargins(leftMargin, bottomMargin, 0, 0);
308
		
309
		for (int i = 0; i < buttons.length; i++) {
310
			buttons[i].clearAnimation();
311
			buttons[i].setLayoutParams(params);
312
			buttons[i].setVisibility(View.INVISIBLE);
313
		}
314
		menuBtn.clearAnimation();
315
		menuBtn.setLayoutParams(params);
316
		menuBtn.getBackground().setAlpha(alpha);
317
		
318
		setVisibility(View.VISIBLE);
319
	}
320
 
321
	/**
322
	 * 外界事件打开菜单
323
	 * 如长按屏幕事件,这个时候需要先设置各个元素的坐标
324
	 * @param xposition			初始X坐标
325
	 * @param yposition			初始Y坐标
326
	 */
327
	public void openMenu(int xposition, int yposition) {
328
		setPosition(xposition, yposition);
329
		
330
		int toX,toY;
331
		for(int i=0;i<buttons.length;i++){
332
			buttons[i].setVisibility(View.VISIBLE);
333
			
334
			toX=(int)(radius*Math.sin(i*angle-Math.PI/2));
335
			toY=(int)(radius*Math.cos(i*angle-Math.PI/2));
336
			Animation animation = animOpen(toX, -toY, timeSpent/*+i*intervalTimeSpent*/);
337
			/*animation.setFillAfter(true);*/ //达不到既定的效果
338
			animation.setAnimationListener(new ButtonAnimationListener(buttons[i],leftMargin+toX, bottomMargin-toY));
339
			buttons[i].startAnimation(animation);
340
		}
341
		isOpen = true;
342
	}
343
	
344
	public void openMenu(int position) {
345
//		if(position != 0 && position % 2 == 0){//当position为扇形,打开时初始半径变大1.5倍;
346
//			radius *= 1.5;
347
//		}
348
		
349
		int toX,toY;
350
		for(int i=0;i<buttons.length;i++){
351
			buttons[i].setVisibility(View.VISIBLE);
352
			
353
//			toX=(int)(radius*Math.sin(i*angle));
354
//			toY=(int)(radius*Math.cos(i*angle));
355
			toX = computOffset(position, i)[0];
356
			toY = computOffset(position, i)[1];
357
			
358
			Animation animation = animOpen(toX, -toY, timeSpent/*+i*intervalTimeSpent*/);
359
			/*animation.setFillAfter(true);*/ //达不到既定的效果
360
			animation.setAnimationListener(new ButtonAnimationListener(buttons[i],leftMargin+toX, bottomMargin-toY));
361
			buttons[i].startAnimation(animation);
362
		}
363
		menuBtn.getBackground().setAlpha(255);
364
		isOpen = true;
365
		isCanDrag = false;
366
	}
367
	
368
	/**
369
	 * 关闭菜单
370
	 */
371
	/**
372
	 * @param position
373
	 */
374
	/**
375
	 * @param position
376
	 */
377
	public void shutMenu(int position){
378
		float toX, toY;
379
		for (int i = 0; i < buttons.length; i++) {
380
//			toX=(float)(radius*Math.sin(i*angle - Math.PI));
381
//			toY=(float)(radius*Math.cos(i*angle - Math.PI));
382
			
383
			toX = computOffset(position, i)[0];
384
			toY = computOffset(position, i)[1];
385
			
386
			buttons[i].startAnimation(animShut(buttons[i], -toX, toY, timeSpent));//点击按钮变大
387
		}
388
		isOpen = false;
389
		isCanDrag = true;
390
		
391
//		if(position != 0 && position % 2 == 0){//当position为扇形,关闭时恢复初始半径;
392
//			radius /= 1.5;
393
//		}
394
	}
395
	
396
	/************************动画效果实现start***************************/
397
	private Animation animOpen(float toX, float toY, long durationMillis){
398
		return AnimationTool.createTranslate(0, 0, toX, toY, durationMillis);
399
	}
400
	
401
	private Animation animShut(final Button btn, final float toX, final float toY, final long durationMillis){
402
		Animation aAnimation = AnimationTool.createRotate(-720, 0.5f, 0.5f, durationMillis);
403
		aAnimation.setAnimationListener(new AnimationListener(){
404
			@Override
405
			public void onAnimationStart(Animation animation) {}
406
			@Override
407
			public void onAnimationRepeat(Animation animation) {}
408
			@Override
409
			public void onAnimationEnd(Animation animation){
410
				Animation tAnimation = AnimationTool.createTranslate(0, 0, toX, toY, durationMillis);
411
				/*绑定动画结束以后的事件*/
412
				tAnimation.setFillAfter(true);
413
				tAnimation.setAnimationListener(new ButtonAnimationListener(btn, leftMargin, bottomMargin));
414
				btn.startAnimation(tAnimation);
415
				btn.setVisibility(View.INVISIBLE);
416
			}
417
		});	
418
		return aAnimation;
419
	}
420
	
421
	private Animation animClick(Button btn, float toX, float toY, long durationMillis){
422
		/*动画需要相对于圆心*/
423
		Animation animation = AnimationTool.createScale(toX, toY, 0.5f, 0.5f, durationMillis);
424
		animation.setInterpolator(getContext(), anim.accelerate_decelerate_interpolator);
425
		/*绑定动画结束以后的事件*/
426
		animation.setAnimationListener(new ButtonAnimationListener(btn, leftMargin, bottomMargin));
427
		
428
		isOpen = false;
429
		return animation;
430
	}
431
	/************************动画效果实现end***************************/
432
	public boolean isOpen() {
433
		return isOpen;
434
	}
435
	
436
	public void reset(){
437
		/*解决Home出去时的BUG*/
438
		if(this.isOpen){
439
			shutMenu(position);
440
		}
441
		this.isOpen = false;
442
		this.isCanDrag = true;
443
	}
444

445
	/************************按钮监听***************************/
446
	private void focusView(View v) {
447
		// TODO Auto-generated method stub
448
		if (v != null) {
449
			v.setFocusable(true);
450
			v.setFocusableInTouchMode(true);
451
			v.requestFocus();
452
		}
453
	}
454
	/************************动画事件监听***************************/
455
	/**
456
	 * 动画结束以后设置Button坐标。如果使用setFillAfter达不到既定的效果。
457
	 * Button显示在A处,Button实际的位置还是在B处。
458
	 */
459
	class ButtonAnimationListener implements AnimationListener{
460
		private Button button;
461
		private int left, bottom;
462
		
463
		public ButtonAnimationListener(Button button, int left, int bottom){
464
			this.button = button;
465
			this.left = left;
466
			this.bottom = bottom;
467
		}
468
		
469
		public void onAnimationStart(Animation animation){
470
		}
471
		public void onAnimationRepeat(Animation animation) {
472
		}
473
		public void onAnimationEnd(Animation animation){
474
			/*如果不清除动画,在动画结束时有屏闪的BUG,此动作最好在layout之前*/
475
			button.clearAnimation();
476
			
477
			/*1.设置button,解决跨线程调用,Handle的实现在ViewRoot中,触发invalidate()*/
478
			button.layout(left, bottom,left+buttonRadius, bottom+buttonRadius);
479
			button.postInvalidate();
480
			/*2.最原始的方式设置button*/
481
			/*RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
482
				ViewGroup.LayoutParams.WRAP_CONTENT);
483
			params.height = buttonWidth;
484
			params.width =  buttonWidth;											
485
			params.setMargins(left, bottom, 0, 0);
486
			button.setLayoutParams(params);*/
487
			
488
			//关闭菜单的最后透明化
489
			if(!isOpen()){
490
				button.setVisibility(View.INVISIBLE);
491
				menuBtn.getBackground().setAlpha(alpha);
492
			}
493
		}
494
	}
495
	/************************按钮事件抽象设计***************************/
496
	private OnButtonClickListener onButtonClickListener;
497
	
498
	public interface OnButtonClickListener{
499
		void onButtonClick(View v,int id);
500
	}
501
	public void setOnButtonClickListener(OnButtonClickListener onButtonClickListener){
502
		this.onButtonClickListener = onButtonClickListener;
503
	}
504
	
505
	
506
	/********展开形状判定**********/
507
	public static final int POSITION_CENTER = 0;		//中心正圆
508
    public static final int POSITION_TOP_CENTER = 1;	//上中半圆
509
    public static final int POSITION_TOP_RIGHT = 2;		//上右扇形
510
    public static final int POSITION_RIGHT_CENTER = 3;	//右中半圆
511
    public static final int POSITION_BOTTOM_RIGHT = 4;	//底右扇形
512
    public static final int POSITION_BOTTOM_CENTER = 5;	//底中半圆
513
    public static final int POSITION_BOTTOM_LEFT = 6;	//底左扇形
514
    public static final int POSITION_LEFT_CENTER = 7;	//左中半圆
515
    public static final int POSITION_TOP_LEFT = 8;		//上左扇形
516
	
517
	/**
518
	 * 通过距离动态判断停靠位置
519
	 * @param isLeft
520
	 * @param isRight
521
	 * @param isUp
522
	 * @param isBottom
523
	 * @return
524
	 */
525
	private int getPosition(boolean isLeft,boolean isRight,boolean isUp,boolean isBottom){
526
		if (isBottom) {
527
			if(isRight){
528
				return POSITION_BOTTOM_RIGHT;
529
			}else if (isLeft) {
530
				return POSITION_BOTTOM_LEFT;
531
			}
532
			return POSITION_BOTTOM_CENTER;
533
		}else if (isUp) {
534
			if(isRight){
535
				return POSITION_TOP_RIGHT;
536
			}else if (isLeft) {
537
				return POSITION_TOP_LEFT;
538
			}
539
			return POSITION_TOP_CENTER;
540
		}else if (isRight) {
541
			return POSITION_RIGHT_CENTER;
542
		}else if (isLeft) {
543
			return POSITION_LEFT_CENTER;
544
		}
545
//		if(!isLeft && !isRight && !isUp && !isBottom){
546
			return POSITION_CENTER;
547
//		}
548
	}
549
	/**
550
	 * 偏移量计算
551
	 */
552
	private int[] computOffset(int position,int i){
553
		int toX = 0,toY =0 ;
554
		radius = buttonRadius * 2;
555
		if(position != 0 && position % 2 == 0){//当position为扇形,打开时初始半径变大1.5倍;
556
			radius *= 1.5;
557
		}
558
		switch (position) {
559
		case POSITION_CENTER:
560
			setCircle(1);
561
			toX =(int)(radius*Math.sin(i*angle));
562
			toY =(int)(radius*Math.cos(i*angle));
563
			break;
564
		case POSITION_TOP_CENTER:
565
			setCircle(0.5f);
566
			toX = (int)(radius*Math.sin(i*angle + Math.PI/2));
567
			toY = (int)(radius*Math.cos(i*angle + Math.PI/2));
568
			break;
569
		case POSITION_TOP_RIGHT:
570
			setCircle(0.25f);
571
			toX = (int)(radius*Math.sin(i*angle + Math.PI));
572
			toY = (int)(radius*Math.cos(i*angle + Math.PI));
573
			break;
574
		case POSITION_RIGHT_CENTER:
575
			setCircle(0.5f);
576
			toX = (int)(radius*Math.sin(i*angle + Math.PI));
577
			toY = (int)(radius*Math.cos(i*angle + Math.PI));
578
			break;
579
		case POSITION_BOTTOM_RIGHT:
580
			setCircle(0.25f);
581
			toX = (int)(radius*Math.sin(i*angle - Math.PI/2));
582
			toY = (int)(radius*Math.cos(i*angle - Math.PI/2));
583
			break;
584
		case POSITION_BOTTOM_CENTER:
585
			setCircle(0.5f);
586
			toX = (int)(radius*Math.sin(i*angle - Math.PI/2));
587
			toY = (int)(radius*Math.cos(i*angle - Math.PI/2));
588
			break;
589
		case POSITION_BOTTOM_LEFT:
590
			setCircle(0.25f);
591
			toX = (int)(radius*Math.sin(i*angle));
592
			toY = (int)(radius*Math.cos(i*angle));
593
			break;
594
		case POSITION_LEFT_CENTER:
595
			setCircle(0.5f);
596
			toX = (int)(radius*Math.sin(i*angle));
597
			toY = (int)(radius*Math.cos(i*angle));
598
			break;
599
		case POSITION_TOP_LEFT:
600
			setCircle(0.25f);
601
			toX = (int)(radius*Math.sin(i*angle + Math.PI/2));
602
			toY = (int)(radius*Math.cos(i*angle + Math.PI/2));
603
			break;
604
		default:
605
			break;
606
		}
607
		int [] xy = {toX,toY};
608
		return xy;
609
	}
610
	
611
	public PathMenu setPosition(int position){
612
		this.position = position;
613
		return this;
614
	}
615
	
616
}