android

来源:互联网 发布:电信4g网络信号不好 编辑:程序博客网 时间:2024/06/06 07:37

参考:
camera、Matrix概念
Matrix的set,pre,post调用顺序

常用的API如下:
rotateX(float degree) 绕着x轴旋转degree个度数
rotateY(float degree) 绕着y轴旋转degree个度数
rotateZ(float degree) 绕着z轴旋转degree个度数
translate(float x,float y,float z) 平移一段距离
save()和restore() 作用跟Canvas的一样,保存原状态,操作完之后,恢复到原状态。

效果图:

这里写图片描述

好吧,电脑没显卡的弊端。。。

Rotate3dAnimation:3D动画

package com.example.rotatepicbrowserdemo;import android.view.animation.Animation;import android.view.animation.Transformation;import android.graphics.Camera;import android.graphics.Matrix;/** * 在两个指定角度之间绕Y轴旋转视图的动画。(3D动画) * <p> * 这个动画也在z轴(深度)上添加了一个转化来提高效果。 */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;    /**     * 在Y轴上创建一个新的3D旋转。旋转是由它的开始角和它的结束角来定义的。     * <p>     * 旋转围绕在二维空间的一个中心点,确定由一对X和Y坐标,称为centerX 和 centerY.     * <p>     * 当动画开始时,执行z轴(深度)上的转化。可以指定转化的长度,以及转化是否应该及时倒转。     *     * @param fromDegrees the start angle of the 3D rotation:3D旋转 起始角度     * @param toDegrees   the end angle of the 3D rotation:3D旋转 结束角度     * @param centerX     the X center of the 3D rotation:3D旋转 x轴中心     * @param centerY     the Y center of the 3D rotation:3D旋转 Y轴中心     * @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();        //让Camera根据动画播放的时间在Z轴进行一定的偏移,使视图有远离视角的感觉。        if (mReverse) {            // z的偏移会越来越大。这就会形成这样一个效果,view从近到远            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);        } else {            // z的偏移会越来越小。这就会形成这样一个效果,            //我们的View从一个很远的地方向我们移过来,越来越近,最终移到了我们的窗口上面            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));        }        //让视图围绕Y轴进行旋转,从而产生立体旋转的效果        camera.rotateY(degrees);        camera.getMatrix(matrix);        camera.restore();        //通过Matrix来确定旋转的中心点的位置。        matrix.preTranslate(-centerX, -centerY);        matrix.postTranslate(centerX, centerY);    }}

applyTransformation方法在旋转动画过程中不断调用,

interpolatedTime取值范围【0,1】,从0到1取值

Rotate3dFrameLayout:3D布局

public class Rotate3dFrameLayout extends FrameLayout {    private View childView1;    private View childView2;    private float mCenterX;    private float mCenterY;    private int Duration = 150;    private boolean mIsFirst;    public Rotate3dFrameLayout(@NonNull Context context) {        this(context, null);    }    public Rotate3dFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public Rotate3dFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        //子View的数量        int childCount = getChildCount();        Log.e("111", "childCount=========" + childCount);        if (childCount != 2) {            throw new IllegalArgumentException("Rotate3dFrameLayout的子View数量必须为2");        }        childView1 = getChildAt(0);        childView2 = getChildAt(1);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mCenterX = w / 2;        mCenterY = h / 2;        Log.e("111", "mCenterX=========" + mCenterX);        Log.e("111", "mCenterY=========" + mCenterY);    }    public void applyRotation(boolean isFirst) {        Rotate3dAnimation rotation = null;        mIsFirst = isFirst;        float mDepthZ = 300.0f;        if (mIsFirst) {            rotation = new Rotate3dAnimation(0, 90, mCenterX, mCenterY, mDepthZ, true);        } else {            rotation = new Rotate3dAnimation(0, -90, mCenterX, mCenterY, mDepthZ, true);        }        rotation.setDuration(Duration);        rotation.setFillAfter(true);        rotation.setInterpolator(new AccelerateDecelerateInterpolator());        rotation.setAnimationListener(new DisplayNextView());        startAnimation(rotation);    }    private final class DisplayNextView implements Animation.AnimationListener {        public void onAnimationStart(Animation animation) {        }        public void onAnimationEnd(Animation animation) {            post(new SwapViews());        }        public void onAnimationRepeat(Animation animation) {        }    }    private final class SwapViews implements Runnable {        @Override        public void run() {            Rotate3dAnimation rotation = null;            if (mIsFirst) {                childView1.setVisibility(View.GONE);                childView2.setVisibility(View.VISIBLE);                rotation = new Rotate3dAnimation(-90, 0, mCenterX, mCenterY, 310.0f, false);            } else {                childView1.setVisibility(View.VISIBLE);                childView2.setVisibility(View.GONE);                rotation = new Rotate3dAnimation(90, 0, mCenterX, mCenterY, 310.0f, false);            }            rotation.setDuration(Duration);//设置动画持续时间            rotation.setFillAfter(true);            rotation.setInterpolator(new AccelerateDecelerateInterpolator());//设置动画变化速度            startAnimation(rotation);        }    }}

父布局指定只能正反两个子布局。

布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <com.yxl.test.Rotate3dFrameLayout        android:id="@+id/container"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#00ff00">        <TextView            android:id="@+id/childView1"            android:layout_width="200dp"            android:layout_height="200dp"            android:layout_gravity="center"            android:layout_margin="20dp"            android:background="@drawable/bg1"            android:gravity="center"            android:text="红"            android:textColor="#000000"            android:textSize="45sp" />        <TextView            android:id="@+id/childView2"            android:layout_width="200dp"            android:layout_height="200dp"            android:layout_gravity="center"            android:layout_margin="20dp"            android:background="@drawable/bg2"            android:gravity="center"            android:text="蓝"            android:textColor="#000000"            android:textSize="45sp"            android:visibility="gone" />    </com.yxl.test.Rotate3dFrameLayout></LinearLayout>  

在Rotate3dFrameLayout中放置两个子布局:正反两面的两个布局。

MainActivityI

public class MainActivityI extends Activity {    private Rotate3dFrameLayout container;    private boolean isFirst = true;//默认第一面    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.rotate_layout);        container = ((Rotate3dFrameLayout) this.findViewById(R.id.container));        container.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                container.applyRotation(isFirst);                isFirst = !isFirst;            }        });    }}

参考:Android立体旋转动画实现与封装(支持以X、Y、Z三个轴为轴心旋转)