Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android動畫--Activity界面180度翻轉

Android動畫--Activity界面180度翻轉

編輯:關於Android編程

這個動畫效果是把Activity當做一張紙,正反面都有內容,且當點擊正反面的任何一個翻轉按鈕,Activity都會以屏幕中心為翻轉中心點(Z軸的翻轉中心點可以自由設定),進行旋轉。

效果如下圖所示(不懂上傳Gif圖,懂的人請告知哈):
正面
翻轉(正面到反面)
翻轉(正面到反面)
反面
翻轉(反面到正面)
飯莊(反面到正面)
回到正面

這個動畫效果的思路是這樣的,首先兩個界面的布局都在同一個Layout文件中,因為這裡只有一個Activity,所以兩個界面的布局在同一個layout文件中就要有所設計。
在這裡,我使用的是FrameLayout作為父容器,包裹著兩個RelativeLayout子容器。當然其他布局也可以,只是在初始化時候必須先設置不可見的一面的布局android:visibility=“gone”
布局文件具體代碼如下:




    <framelayout android:id="@+id/framelayout" android:layout_height="match_parent" android:layout_width="match_parent">

        
        

            </framelayout>

注意,在兩個RelativeLayout中必須添加android:focusable=”true”
android:focusableInTouchMode=”true”這兩個屬性來隔離兩個界面的監聽事件,使得當前顯示的一面監聽有效,另一個不顯示的頁面的監聽無效,否則點擊事件會亂套。

接下來就是翻轉效果的設計,首先是確定翻轉中心點的位置,通過傳入X,Y,Z三個軸的中心點來確定。然後使用Camera根據傳入的翻轉度來進行翻轉,翻轉的類Rotate3D代碼如下:

/**
 * 實現3D旋轉動畫核心類
 * Created by PawN on 2015/6/12.
 */
public class Rotate3D extends Animation{

    // 開始角度
    private final float mFromDegrees;
    // 結束角度
    private final float mToDegrees;
    // X軸中心點
    private final float mCenterX;
    // Y軸中心點
    private final float mCenterY;
    // Z軸中心點
    private final float mDepthZ;
    //是否需要扭曲
    private final boolean mReverse;
    //攝像頭
    private Camera mCamera;

    public Rotate3D(float fromDegrees, float toDegrees, 
                    float centerX,float centerY, 
                    float depthZ, boolean reverse) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mCenterX = centerX;
        mCenterY = centerY;
        mDepthZ = depthZ;
        mReverse = reverse;
    }

    @Override
    public void initialize(int width, int height, 
                            int  parentWidth,
                            int parentHeight) {
        super.initialize(width, height, parentWidth,       
                         parentHeight);
        mCamera = new Camera();
    }

    @Override
    protected void applyTransformation(float  
                      interpolatedTime, Transformation t) {
        final float fromDegrees = mFromDegrees;
        // 生成中間角度
        float degrees = fromDegrees
                + ((mToDegrees - fromDegrees)
                * interpolatedTime);
        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Camera camera = mCamera;
        final Matrix matrix = t.getMatrix();//取得當前矩陣
        camera.save();
        if (mReverse) {
            camera.translate(0.0f, 0.0f, mDepthZ * 
                             interpolatedTime);
        } else {
            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - 
                             interpolatedTime));
        }
        camera.rotateY(degrees);//翻轉
        camera.getMatrix(matrix);// 取得變換後的矩陣
        camera.restore();
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }
}

接下來就是在TestRotateActivity中的使用了,整個翻轉過程分為兩個階段操作,第一階段是從當前頁面翻轉到整個Activity垂直於手機屏幕(到這個時刻,正反兩面都是不可見的)。第二階段是從當前的整個Activity垂直於手機屏幕(到這個時刻,正反兩面都是不可見的)狀態翻轉到第二個頁面顯示在手機屏幕上。具體流程如下圖所示:
翻轉模擬圖

TestRotateActivity的具體代碼如下:

public class TestRotateActivity extends Activity{

    //布局1
    private TextView tvOne;
    private Button btnRotateNext;
    //布局2
    private TextView tvTwo;
    private Button btnRotateBack;


    //頁面翻轉容器FrameLayout
    private FrameLayout flContainer;
    //布局1界面RelativeLayout
    private RelativeLayout relativeLayout1;
    //布局2界面RelativeLayout
    private RelativeLayout relativeLayout2;
    //初始化界面索引(1位布局1,2位布局2)
    private int index = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_rotate);
        initView();
        registerClickListener();
    }

    private void initView(){
        tvOne = (TextView)findViewById(R.id.tv_one);
        tvTwo = (TextView)findViewById(R.id.tv_two);
        flContainer = 
(FrameLayout)findViewById(R.id.frame_layout);
        relativeLayout1 = (RelativeLayout)findViewById(R.id.relative_layout_one);
        relativeLayout2 = (RelativeLayout)findViewById(R.id.relative_layout_two);

        btnRotateNext = (Button) findViewById(R.id.rotate_next);
        btnRotateBack = (Button)findViewById(R.id.rotate_back);
    }

    private void registerClickListener(){
        tvOne.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(TestRotateActivity.this,"one",Toast.LENGTH_SHORT).show();;
            }
        });

        tvTwo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(TestRotateActivity.this,"two",Toast.LENGTH_SHORT).show();;
            }
        });
        btnRotateNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(index==1){
                    //第一階段翻轉
                    applyRotation(1,0,90);
                    index =0;
                }else{
                    //第一階段翻轉
                    applyRotation(0,0,-90);
                    index = 1;
                }
            }
        });
        btnRotateBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(index==1){
                    //第一階段翻轉
                    applyRotation(1,0,90);
                    index =0;
                }else{
                    //第一階段翻轉
                    applyRotation(0,0,-90);
                    index = 1;
                }
            }
        });
    }


    /**
     * 執行翻轉第一階段翻轉動畫
     * @param tag view索引
     * @param start 起始角度
     * @param end 結束角度
     */
    private void applyRotation(int tag, float start, float end) {
        // 得到中心點(以中心翻轉)
        //X軸中心點
        final float centerX = flContainer.getWidth() / 2.0f;
        //Y軸中心點
        final float centerY = flContainer.getHeight() / 2.0f;
        //Z軸中心點
        final float depthZ = 500.0f;
        // 根據參數創建一個新的三維動畫,並且監聽觸發下一個動畫
        final Rotate3D rotation = new Rotate3D(start, end, centerX, centerY,depthZ, true);
        rotation.setDuration(300);//設置動畫持續時間
        rotation.setInterpolator(new AccelerateInterpolator());//設置動畫變化速度
        rotation.setAnimationListener(new DisplayNextView(tag));//設置第一階段動畫監聽器
        flContainer.startAnimation(rotation);


    }

    /**
     * 第一階段動畫監聽器
     *
     */
    private final class DisplayNextView implements Animation.AnimationListener {
        private final int tag;

        private DisplayNextView(int tag) {
           this.tag = tag;
        }

        public void onAnimationStart(Animation animation) {
        }

        public void onAnimationEnd(Animation animation) {
           //第一階段動畫結束時,也就是整個Activity垂直於手機屏幕,  
           //執行第二階段動畫
           flContainer.post(new SwapViews(tag));
           //調整兩個界面各自的visibility
           adjustVisiable();
        }

        public void onAnimationRepeat(Animation animation) {
        }
    }

    /**
     * 執行翻轉第二個階段動畫
     *
     */
    private final class SwapViews implements Runnable {
        private final int tag;

        public SwapViews(int position) {
           tag = position;
        }

        public void run() {
           if (tag == 0) {
              //首頁頁面以90~0度翻轉
               showView(relativeLayout1, relativeLayout2, 90, 0);
           } else if (tag == 1) {
            //音樂頁面以-90~0度翻轉
            showView(relativeLayout2, relativeLayout1, -90, 0);
           }
        }
    }

    /**
     * 顯示第二個視圖動畫
     * @param showView 要顯示的視圖
     * @param hiddenView 要隱藏的視圖
     * @param startDegree 開始角度
     * @param endDegree 目標角度
     */
    private void showView(RelativeLayout showView, RelativeLayout hiddenView, int startDegree, int endDegree) {
        //同樣以中心點進行翻轉
        float centerX = showView.getWidth() / 2.0f;
        float centerY = showView.getHeight() / 2.0f;
        float centerZ = 500.0f;
        if (centerX == 0 || centerY == 0) {
            //調用該方法getMeasuredWidth(),必須先執行measure()方法,否則會出異常。
            showView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
            //獲取該view在父容器裡面占的大小
            centerX = showView.getMeasuredWidth() / 2.0f;
            centerY = showView.getMeasuredHeight() / 2.0f;
        }
//        Log.e("centerX",centerX + "");
//        Log.e("centerY",centerY + "");
        hiddenView.setVisibility(View.GONE);
        showView.setVisibility(View.VISIBLE);
        Rotate3D rotation = new Rotate3D(startDegree, endDegree, centerX, centerY, centerZ, false);
        rotation.setDuration(300);//設置動畫持續時間
        rotation.setInterpolator(new DecelerateInterpolator());//設置動畫變化速度
        flContainer.startAnimation(rotation);
    }

    /**
     * 兩個布局的visibility調節
     */

    private void adjustVisiable(){
        if(tvOne.getVisibility() == View.VISIBLE){
            tvOne.setVisibility(View.GONE);
        }else {
            tvOne.setVisibility(View.VISIBLE);
        }
        if(tvTwo.getVisibility() == View.VISIBLE){
            tvTwo.setVisibility(View.GONE);
        }else {
            tvTwo.setVisibility(View.VISIBLE);
        }
    }
}

這樣就可以實現本章的Activity翻轉動畫效果了~有哪裡不妥的地方歡迎大家指正~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved