天天看點

每日一學(十二)Android動畫---屬性動畫(圓形菜單、扇形菜單)

      在上篇文章中,我們已經介紹了屬性動畫的基本用法:http://blog.csdn.net/u010838555/article/details/76214821

      這裡做一個執行個體-----扇形菜單~

每日一學(十二)Android動畫---屬性動畫(圓形菜單、扇形菜單)

#1.我們首先要用到一個屬性動畫 以下是實作一個最基本的簡單的對imageView的x坐标和y坐标進行移動的動畫。

/**
    * 第一個參數代表要操作的對象
    * 第二個參數代表要操作的對象的屬性
    * 第三個參數代表要操作的對象的屬性的起始值
    * 第四個參數代表要操作的對象的屬性的終止值
    */
   ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews, "translationX", 0, 500);
   ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews, "translationY", 0, 500);
   /**動畫集合,用來編排動畫**/
   AnimatorSet animatorSet = new AnimatorSet();
   /**設定動畫時長**/
   animatorSet.setDuration(500);
   /**設定同時播放x方向的位移動畫和y方向的位移動畫**/
   animatorSet.play(objectAnimatorX).with(objectAnimatorY);
   /**開始播放動畫**/
   animatorSet.start();
           

#2.如何擷取菜單展開的坐标,先複習下數學

這個是我的手稿,畫的比較粗糙,請大家見諒

每日一學(十二)Android動畫---屬性動畫(圓形菜單、扇形菜單)

#3.如何用代碼計算,計算公式

我們由上圖可以推導出計算公式如下:

圓點坐标:(x0,y0)

半徑:r

角度:a0

則圓上任一點為:(x1,y1)

x1 = x0 + r * cos(ao * 3.14 /180 )

y1 = y0 + r * sin(ao * 3.14 /180 )

#4.代碼實作

總共分為五步,代碼如下:

/**
     * 顯示扇形菜單
     */
    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
    private void showSectorMenu() {
        /***第一步,周遊所要展示的菜單ImageView*/
        for (int i = 0; i < imageViews.size(); i++) {
            PointF point = new PointF();
            /***第二步,根據菜單個數計算每個菜單之間的間隔角度*/
            int avgAngle = (90 / (imageViews.size() - 1));
            /**第三步,根據間隔角度計算出每個菜單相對于水準線起始位置的真實角度**/
            int angle = avgAngle * i;
            Log.d(TAG, "angle=" + angle);
            /**
             * 
             * 圓點坐标:(x0,y0)
             * 半徑:r
             * 角度:a0
             * 則圓上任一點為:(x1,y1)
             * x1   =   x0   +   r   *   cos(ao   *   3.14   /180   )
             * y1   =   y0   +   r   *   sin(ao   *   3.14   /180   )
             */
            /**第四步,根據每個菜單真實角度計算其坐标值**/
            point.x = (float) Math.cos(angle * (Math.PI / 180)) * radius1;
            point.y = (float) -Math.sin(angle * (Math.PI / 180)) * radius1;
            Log.d(TAG, point.toString());

            /**第五步,根據坐标執行位移動畫**/
            /**
             * 第一個參數代表要操作的對象
             * 第二個參數代表要操作的對象的屬性
             * 第三個參數代表要操作的對象的屬性的起始值
             * 第四個參數代表要操作的對象的屬性的終止值
             */
            ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews.get(i), "translationX", 0, point.x);
            ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews.get(i), "translationY", 0, point.y);
            /**動畫集合,用來編排動畫**/
            AnimatorSet animatorSet = new AnimatorSet();
            /**設定動畫時長**/
            animatorSet.setDuration(500);
            /**設定同時播放x方向的位移動畫和y方向的位移動畫**/
            animatorSet.play(objectAnimatorX).with(objectAnimatorY);
            /**開始播放動畫**/
            animatorSet.start();
        }
    }
           

#5.如何關閉菜單

啟示關閉菜單和打開菜單的操作是相反的,隻需要将起始坐标和終止坐标調換就可以了。
/**
     * 關閉扇形菜單
     */
    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
    private void closeSectorMenu() {
        for (int i = 0; i < imageViews.size(); i++) {
            PointF point = new PointF();
            int avgAngle = (90 / (imageViews.size() - 1));
            int angle = avgAngle * i;
            Log.d(TAG, "angle=" + angle);
            point.x = (float) Math.cos(angle * (Math.PI / 180)) * radius1;
            point.y = (float) -Math.sin(angle * (Math.PI / 180)) * radius1;
            Log.d(TAG, point.toString());

            ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews.get(i), "translationX", point.x, 0);
            ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews.get(i), "translationY", point.y, 0);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setDuration(500);
            animatorSet.play(objectAnimatorX).with(objectAnimatorY);
            animatorSet.start();
        }
    }
           

#6.菜單按鈕的旋轉動畫

其實就是打開菜單時進行45°旋轉,關閉的時候再旋轉會原來的0°;

Boolean isShowing = (Boolean) iv1.getTag();
            if (null == isShowing || isShowing == false) {
                ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv1, "rotation", 0, 45);
                objectAnimator.setDuration(500);
                objectAnimator.start();
                iv1.setTag(true);
                showSectorMenu();
            } else {
                iv1.setTag(false);
                ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv1, "rotation", 45, 0);
                objectAnimator.setDuration(500);
                objectAnimator.start();
                closeSectorMenu();
            }
           

#7.圓形菜單 圓形菜單其實就是對360度進行等分,原理一樣,代碼如下:

/**
     * 顯示圓形菜單
     */
    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
    private void showCircleMenu() {
        for (int i = 0; i < imageViews2.size(); i++) {
            PointF point = new PointF();
            int avgAngle = (360 / (imageViews2.size() - 1));
            int angle = avgAngle * i;
            Log.d(TAG, "angle=" + angle);
            point.x = (float) Math.cos(angle * (Math.PI / 180)) * radius2;
            point.y = (float) Math.sin(angle * (Math.PI / 180)) * radius2;
            Log.d(TAG, point.toString());
            ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews2.get(i), "translationX", 0, point.x);
            ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews2.get(i), "translationY", 0, point.y);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setDuration(500);
            animatorSet.play(objectAnimatorX).with(objectAnimatorY);
            animatorSet.start();
        }
    }

    /**
     * 關閉圓形菜單
     */
    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
    private void closeCircleMenu() {
        for (int i = 0; i < imageViews2.size(); i++) {
            PointF point = new PointF();
            int avgAngle = (360 / (imageViews2.size() - 1));
            int angle = avgAngle * i;
            Log.d(TAG, "angle=" + angle);
            point.x = (float) Math.cos(angle * (Math.PI / 180)) * radius2;
            point.y = (float) Math.sin(angle * (Math.PI / 180)) * radius2;

            Log.d(TAG, point.toString());
            ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(imageViews2.get(i), "translationX", point.x, 0);
            ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(imageViews2.get(i), "translationY", point.y, 0);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setDuration(500);
            animatorSet.play(objectAnimatorX).with(objectAnimatorY);
            animatorSet.start();
        }
    }
           

源碼:http://download.csdn.net/detail/u010838555/9913004