1. 程式人生 > >Android--可收放旋轉選單

Android--可收放旋轉選單

效果:


實現:

1.設定屬性:在values資料夾下建立arr.xml,內容:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!--半徑屬性-->
    <attr name="radius" format="dimension" />
    <!--自定義控制元件屬性-->
    <declare-styleable name="RotateMenu">
        <!--<attr name="position" />-->
<attr name="radius" /> </declare-styleable> </resources>

自定義View:

public class RotateMenuView extends ViewGroup {

    /**定義螢幕的寬度*/
    private int pm_width;

    /**定義螢幕的高度*/
    private int pm_height;

    /**定義選單半徑*/
    private int mRadius;

    /**
     * 列舉類 選單狀態
     */
public enum Status { OPEN, CLOSE } /**預設為關閉狀態*/ private Status mCurrentStatus = Status.CLOSE; /**觸發選單的按鈕*/ private View mButton; /** * 單擊子選單的回撥介面 */ public interface OnRotateMenuItemClickListener { void onClick(View view, int pos); } /**子選單單擊事件*/
private OnRotateMenuItemClickListener mMenuItemClickListener; //構造方法 public RotateMenuView(Context context) { this(context,null); } //構造方法 public RotateMenuView(Context context, AttributeSet attrs) { this(context, attrs,0); } //構造方法 public RotateMenuView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //獲取螢幕寬高 WindowManager windowManager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); pm_width=windowManager.getDefaultDisplay().getWidth(); pm_height=windowManager.getDefaultDisplay().getHeight(); // 獲取自定義屬性的值 TypedArray typedArray=context.getTheme().obtainStyledAttributes(attrs, R.styleable.RotateMenu,defStyleAttr,0); //獲取按鈕半徑屬性值 mRadius= (int) typedArray.getDimension(R.styleable.RotateMenu_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100,getResources().getDisplayMetrics())); //回收資源 typedArray.recycle(); } /** *測量自定義控制元件中所有子控制元件的尺寸 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //獲取所有的按鈕 int count = getChildCount(); //遍歷所有的按鈕 for (int i = 0; i < count; i++) { // 測量所有按鈕,寬度與高度 measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** *設定按鈕的位置 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //如果按鈕佈局發生改變 if (changed) { //呼叫主按鈕佈局位置的方法 buttonLayout(); childLayout(); } } /** * 設定主按鈕在佈局中的位置 */ private void buttonLayout() { mButton = getChildAt(0); //獲取選單主按鈕 //設定按鈕的單擊事件 mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //呼叫主按鈕旋轉的方法 rotatemButton(v, 0f, 360f, 500); //呼叫收縮子按鈕動畫方法 shrinkMenu(500); } }); //初始化按鈕左邊距與上邊距 int l = 0; int t = 0; //獲取主按鈕的寬度與高度 int width = mButton.getMeasuredWidth(); int height = mButton.getMeasuredHeight(); //判斷主按鈕中間按鈕的位置 l = pm_width/2-width/2; t = getMeasuredHeight() - height; //設定主按鈕在父容器的位置 mButton.layout(l, t, l + width, t + width); } private void childLayout() { //獲取所有的子按鈕 int count = getChildCount(); //遍歷所有按鈕,第一個是主按鈕,所以其他子按鈕的總數是count - 1 for (int i = 0; i < count - 1; i++) { //獲取子控制元件下標,因為子按鈕是從1開始的,所以i + 1 View child = getChildAt(i + 1); //隱藏子按鈕 child.setVisibility(View.GONE); //獲取子按鈕的寬高尺寸 int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); //中心座標(pm_width/2-childWidth/2,getMeasuredHeight() - height) int c_x = pm_width / 2 - childWidth / 2; int c_y = getMeasuredHeight() - childHeight/2; //子按鈕與父容器左邊距 int childLeft = (int) (mRadius * Math.sin(Math.PI / (count - 2) * i)); int childTop = (int) (mRadius * Math.sin(Math.PI / (count - 2) * i)); childTop = getMeasuredHeight() - childHeight - childTop; if (i == 0) { childLeft = c_x - mRadius; childTop = getMeasuredHeight() - childHeight; } else if (i == 1) { childLeft = c_x - childLeft; } else if (i == 2) { childLeft = c_x; childTop=getMeasuredHeight() - childHeight-mRadius; } else if (i == 3) { childLeft = c_x + childLeft; } else if (i == 4) { childLeft = c_x + mRadius; childTop = getMeasuredHeight() - childHeight; } //設定子按鈕的位置 child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); } } /** *收縮子按鈕動畫 */ public void shrinkMenu(int time) { //獲取所有的子按鈕 int count = getChildCount(); //遍歷所有按鈕 for (int i = 0; i < count - 1; i++){ //獲取子按鈕下標 final View childView = getChildAt(i + 1); //顯示子按鈕 childView.setVisibility(View.VISIBLE); //動畫開始與結束的位置x,y int clx = (int) (mRadius * Math.sin(Math.PI / (count - 2) * i)); int cty = (int) (mRadius * Math.cos(Math.PI / (count - 2) * i)); if (i == 0) { //第一個子按鈕 clx = mRadius; cty = 0; } else if (i == 1) { //第二個子按鈕 } else if (i == 2) { //第三個子按鈕 clx = 0; cty = mRadius; } else if (i == 3) { //第四個子按鈕 clx=(int) (mRadius * Math.cos(Math.PI / (count - 2) * i)); cty=-cty; } else if (i == 4) { //第五個子按鈕 clx = - mRadius; cty = 0; } //設定動畫集合 AnimationSet animset = new AnimationSet(true); Animation tranAnim = null; //如果當前按鈕選單為關閉狀態 if (mCurrentStatus == Status.CLOSE){ //設定開啟按鈕選單動畫 tranAnim = new TranslateAnimation(clx,0 , cty, 0); //子按鈕可以單擊 childView.setClickable(true); //子按鈕可調焦 childView.setFocusable(true); } else{ //如果當前按鈕選單為開啟狀態,設定關閉按鈕選單動畫 tranAnim = new TranslateAnimation(0, clx, 0, cty); //子按鈕不可點選 childView.setClickable(false); //子按鈕不可調焦 childView.setFocusable(false); } // 動畫顯示的時間 tranAnim.setDuration(time); //停止最後一幀的位置 tranAnim.setFillAfter(true); tranAnim.setStartOffset((i * 100) / count); //設定動畫監聽器 tranAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } /** *動畫結束後隱藏子按鈕 */ @Override public void onAnimationEnd(Animation animation) { if (mCurrentStatus == Status.CLOSE) { childView.setVisibility(View.GONE); } } }); // 旋轉動畫 RotateAnimation rotateAnim = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //設定旋轉的時間 rotateAnim.setDuration(time); //停止最後一幀的位置 rotateAnim.setFillAfter(true); //新增旋轉動畫 animset.addAnimation(rotateAnim); //新增平移動畫 animset.addAnimation(tranAnim); //啟動動畫 childView.startAnimation(animset); final int pos = i + 1; //子按鈕單擊事件 childView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mMenuItemClickListener != null) mMenuItemClickListener.onClick(childView, pos); //呼叫字按鈕單擊動畫方法 childButtonClickAnim(pos - 1); //呼叫選單狀態方法 menuStatus(); } }); } // 切換選單狀態 menuStatus(); } /** * 子按鈕單擊動畫的方法 */ private void childButtonClickAnim(int pos) { for (int i = 0; i < getChildCount() - 1; i++) { View childView = getChildAt(i + 1); //當前單擊的子按鈕 if (i == pos) { //啟動子按鈕變大並消失動畫 childView.startAnimation(scaleBigAnim(200)); } else { //啟動其它沒有被單擊的按鈕變小並消失動畫 childView.startAnimation(scaleSmallAnim(200)); } //子按鈕不可點選 childView.setClickable(false); //子按鈕不可調焦 childView.setFocusable(false); } } /** *沒有被單擊的子按鈕,變小並消失的動畫方法 */ private Animation scaleSmallAnim(int time) { //設定動畫集合 AnimationSet animationSet = new AnimationSet(true); //縮放動畫 ScaleAnimation scaleAnim = new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //透明度動畫 AlphaAnimation alphaAnim = new AlphaAnimation(1f, 0.0f); //新增縮放動畫 animationSet.addAnimation(scaleAnim); //新增透明度動畫 animationSet.addAnimation(alphaAnim); //設定動畫時間 animationSet.setDuration(time); //停止最後一幀的位置 animationSet.setFillAfter(true); return animationSet; } /** * 單擊子按鈕,當前子按鈕變大並消失動畫方法 */ private Animation scaleBigAnim(int time) { //設定動畫集合 AnimationSet animationSet = new AnimationSet(true); //縮放動畫 ScaleAnimation scaleAnim = new ScaleAnimation(1.0f, 4.0f, 1.0f, 4.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //透明度動畫 AlphaAnimation alphaAnim = new AlphaAnimation(1f, 0.0f); //新增縮放動畫 animationSet.addAnimation(scaleAnim); //新增透明度動畫 animationSet.addAnimation(alphaAnim); //設定動畫時間 animationSet.setDuration(time); //停止最後一幀的位置 animationSet.setFillAfter(true); return animationSet; } /** * 切換選單狀態 */ private void menuStatus() { mCurrentStatus = (mCurrentStatus == Status.CLOSE ? Status.OPEN : Status.CLOSE); } /** *設定主按鈕旋轉動畫 */ private void rotatemButton(View v, float start, float end, int time) { //中心旋轉動畫 RotateAnimation anim = new RotateAnimation(start, end, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //設定旋轉的時間 anim.setDuration(time); //停止最後一幀的位置 anim.setFillAfter(true); //開始動畫 v.startAnimation(anim); } }

 

3.main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:menu="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    tools:context=".MainActivity">
    <com.example.shanshan.statemenu.RotateMenuView
        android:id="@+id/satelliteMenu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        menu:radius="100dp">
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@mipmap/button_bg" >

            <ImageView
                android:id="@+id/id_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:src="@mipmap/button_in" />

        </RelativeLayout>

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img5"
            android:tag="@string/text_btn1" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img4"
            android:tag="@string/text_btn2" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img3"
            android:tag="@string/text_btn3" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img2"
            android:tag="@string/text_btn4" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img1"
            android:tag="@string/text_btn5" />
    </com.example.shanshan.statemenu.RotateMenuView>
</RelativeLayout>