兩個activity的3D翻轉動畫.md

一.業務需求

這裏在公司項目設計時,用到了一個小的需求,就是點擊一個按鈕然後整個activity的頁面進行3d翻轉;

二.設計思路

由於是2個activity的之間的翻轉動畫,就意味着前90度是A頁面進行翻轉翻轉結束後B頁面從90到0度完成整個翻轉過程;再從B翻轉到A也是同樣,B先翻轉90度然後A再從90度翻轉到0度,這樣就完成了一個銜接;
那麼這裏就需要一個3D的翻轉類,

三.代碼實現

import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.graphics.Camera;
import android.graphics.Matrix;

/**
 * An animation that rotates the view on the Y axis between two specified angles.
 * This animation also adds a translation on the Z axis (depth) to improve the effect.
 */
public class Rotate3dAnimation extends Animation {
    private final float mFromDegrees;
    private final float mToDegrees;
    private final float mCenterX;
    private final float mCenterY;
    private final float mDepthZ;
    private final boolean mReverse;
    private Camera mCamera;

    /**
     * Creates a new 3D rotation on the Y axis. The rotation is defined by its
     * start angle and its end angle. Both angles are in degrees. The rotation
     * is performed around a center point on the 2D space, definied by a pair
     * of X and Y coordinates, called centerX and centerY. When the animation
     * starts, a translation on the Z axis (depth) is performed. The length
     * of the translation can be specified, as well as whether the translation
     * should be reversed in time.
     *
     * @param fromDegrees the start angle of the 3D rotation
     * @param toDegrees the end angle of the 3D rotation
     * @param centerX the X center of the 3D rotation
     * @param centerY the Y center of the 3D rotation
     * @param reverse true if the translation should be reversed, false otherwise
     */
    public Rotate3dAnimation(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);
    }
}


import android.app.Activity;
import android.util.Log;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;

public class RotationHelper {

    DisplayNextView displayNext;

    public RotationHelper(Activity con,int order){
        displayNext = new DisplayNextView(con, order);
    }

    // 逆時針旋轉90
    public void applyFirstRotation(ViewGroup layout,float start, float end) {
        // Find the center of the container
        final float centerX = layout.getWidth() / 2.0f;
        final float centerY = layout.getHeight() / 2.0f;
        Log.i("centerX =" + centerX, "centerX");
        Log.i("centerY =" + centerY, "centerY");

        // Create a new 3D rotation with the supplied parameter
        // The animation listener is used to trigger the next animation
        final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end,
                centerX, centerY, 310.0f, true);
        rotation.setDuration(700);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        rotation.setAnimationListener(displayNext);
        layout.startAnimation(rotation);
    }

    public void applyLastRotation(ViewGroup layout,float start, float end) {
        // Find the center of the container
        final float centerX = layout.getWidth() / 2.0f;
        final float centerY = layout.getHeight() / 2.0f;
        Log.i("centerX =" + centerX, "centerX");
        Log.i("centerY =" + centerY, "centerY");

        // Create a new 3D rotation with the supplied parameter
        // The animation listener is used to trigger the next animation
        final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end,
                160, 192, 310.0f, false);
        rotation.setDuration(700);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        layout.startAnimation(rotation);
    }
}


import android.app.Activity;
import android.view.animation.Animation;

public class DisplayNextView implements Animation.AnimationListener {

    Object obj;

    // 動畫監聽器的構造函數
    Activity ac;
    int order;

    public DisplayNextView(Activity ac, int order) {
        this.ac = ac;
        this.order = order;
    }

    public void onAnimationStart(Animation animation) {
    }

    public void onAnimationEnd(Animation animation) {
        doSomethingOnEnd(order);
    }

    public void onAnimationRepeat(Animation animation) {
    }

    private final class SwapViews implements Runnable {
        public void run() {
            switch (order) {
                case Constants.KEY_FIRST_INVERSE:
                    ((TranslateLayout) ac).jumpToSecond();
                    break;
                case Constants.KEY_SECOND_CLOCKWISE:
                    ((Second) ac).jumpToFirst();
                    break;
            }
        }
    }

    //動畫完成的監聽
    public void doSomethingOnEnd(int _order) {
        switch (_order) {
            case Constants.KEY_FIRST_INVERSE:
                ((TranslateLayout) ac).layout1.post(new SwapViews());
                break;

            case Constants.KEY_SECOND_CLOCKWISE:
                ((Second) ac).layout2.post(new SwapViews());
                break;
        }
    }
}
public class Constants {//相關常量

    public final static int KEY_FIRST_INVERSE = 1;

    public final static int KEY_FIRST_CLOCKWISE = 2;

    public final static int KEY_SECOND_INVERSE = 3;

    public final static int KEY_SECOND_CLOCKWISE = 4;
}

//第一個頁面
public class TranslateLayout extends Activity implements OnClickListener {

    RelativeLayout layout1;

    String tag="";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first);
        ImageView first_btn = (ImageView) findViewById(R.id.first_btn);
        first_btn.setOnClickListener(this);

        layout1 = (RelativeLayout) findViewById(R.id.layout1);
        showView();

    }

    public void showView() {
        /* 取得Intent中的Bundle對象 */
        Bundle bundle = this.getIntent().getExtras();

        if (bundle != null) {
            /* 取得Bundle對象中的數據 */
            tag = bundle.getString("second","");
            Log.d("first_tag",tag);
            if (tag.equals("Second")) {
                rotateHelper = new RotationHelper(this,
                        Constants.KEY_FIRST_CLOCKWISE);
                rotateHelper.applyLastRotation(layout1, -90, 0);
            }
        }
    }

    RotationHelper rotateHelper;

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        rotateHelper = new RotationHelper(this, Constants.KEY_FIRST_INVERSE);
        rotateHelper.applyFirstRotation(layout1, 0, -90);
    }

    @Override
    protected void onPause() {
        overridePendingTransition(0, 0);
        super.onPause();
    }

    public void jumpToSecond() {
        Intent in = new Intent();
        in.setClass(this, Second.class);
        // new一個Bundle對象,並將要傳遞的數據傳入
        Bundle bundle = new Bundle();
        bundle.putString("front", "First");
        /* 將Bundle對象assign給Intent */
        in.putExtras(bundle);
        // 如果已經打開過的實例,將不會重新打開新的Activity
        startActivity(in);
        //關閉掉動畫
        overridePendingTransition(0, 0);
    }

}
/**
 * Created by cxf on 2017/9/13.
 *
 * @title
 * @describe
 * @email [email protected]
 */


//第二個頁面
public class Second extends Activity implements OnClickListener {

    String tag = "";

    RotationHelper rotateHelper;

    RelativeLayout layout2;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second);

        layout2 = (RelativeLayout) findViewById(R.id.layout2);
        showView();
        setListener();
    }

    public void setListener() {
        ImageView second_btn = (ImageView) findViewById(R.id.second_btn);
        second_btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        rotateHelper = new RotationHelper(this,
                Constants.KEY_SECOND_CLOCKWISE);
        rotateHelper.applyFirstRotation(layout2, 0, 90);
    }

    public void showView() {
        /* 取得Intent中的Bundle對象 */
        Bundle bundle = this.getIntent().getExtras();

        if (bundle != null) {
            /* 取得Bundle對象中的數據 */
            tag = bundle.getString("front");
        }

        System.out.println("bundle =" + tag);

        if (tag.equals("First")) {
            rotateHelper = new RotationHelper(this, Constants.KEY_SECOND_INVERSE);
            rotateHelper.applyLastRotation(layout2, 90, 0);
        }
    }

    @Override
    protected void onDestroy() {
        overridePendingTransition(0, 0);
        super.onDestroy();
    }

    public void jumpToFirst() {
        Intent in = new Intent();
        in.setClass(this, TranslateLayout.class);
        Bundle bundle = new Bundle();
        bundle.putString("second", "Second");
        in.putExtras(bundle);
        startActivity(in);
        overridePendingTransition(0, 0);
        finish();
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章