实现3D旋转(源码)

package yy.android.roate;

import android.app.Activity;
import android.os.Bundle;

import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;

import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;

public class Y3DActivity extends Activity {
    private ViewGroup layoutmain;//第一页面
    private ViewGroup layoutnext;//第二页面
    
    private Button btn_MainLast;//两个页面的四个按钮
    private Button btn_MainNext;
    private Button btn_NextLast;
    private Button btn_NextNext;
    
    private Rotate3D lQuest1Animation;//动画,一次点击按钮会触发两个动画播放
    private Rotate3D lQuest2Animation;
    private Rotate3D rQuest1Animation;
    private Rotate3D rQuest2Animation;
    private int mCenterX = 160;        // 320x480X中心位置,旋转时需要用到
    private int mCenterY = 240;        // 320x480Y中心位置
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initAnimation();//初始化动画
        initMain();//初始化第一个页面
    }
    //初始化第一个页面
    private void initMain(){
        setContentView(R.layout.main);

        layoutmain = (LinearLayout)findViewById(R.id.layout_main);
        btn_MainLast = (Button)findViewById(R.id.main_last);
        btn_MainNext = (Button)findViewById(R.id.main_next);
        
        btn_MainLast.setOnClickListener(listener);
        btn_MainNext.setOnClickListener(listener);
    }
    //初始化第二个页面
    private void initNext(){
        setContentView(R.layout.next);

        layoutnext = (LinearLayout)findViewById(R.id.layout_next);
        btn_NextLast = (Button)findViewById(R.id.next_last);
        btn_NextNext = (Button)findViewById(R.id.next_next);
        
        btn_NextLast.setOnClickListener(listener);
        btn_NextNext.setOnClickListener(listener);
    }
    
    private View.OnClickListener listener = new View.OnClickListener() {
        public void onClick(View v) {
            switch (v.getId()) {
            //整个过程是这样的:当第一个页面按上一页时,当前页面向左转90度,(0,-90)
            //这时初始化第二个页面的布局,然后使用动画使它从右到左旋转到当前页面,(90,0)
            case R.id.main_last:    // 当前页是第一页,上一页  
                 // 当前页向左旋转(0,-90)
                layoutmain.startAnimation(lQuest1Animation);    
                initNext();
                 // 下一页向左旋转(90, 0)
                layoutnext.startAnimation(lQuest2Animation);    
                break;
            case R.id.main_next:    // 下一页
                //0,90
                layoutmain.startAnimation(rQuest1Animation);    
                initNext();
                //-90,0
                layoutnext.startAnimation(rQuest2Animation);    
                break;
            case R.id.next_last://当前页是第二页,上一页
                //0,-90
                layoutnext.startAnimation(lQuest1Animation);
                initMain();
                //90,0
                layoutmain.startAnimation(lQuest2Animation);
                break;
            case R.id.next_next://同理
                layoutnext.startAnimation(rQuest1Animation);
                initMain();
                layoutmain.startAnimation(rQuest2Animation);
                break;
            }
        }
    };
    public void initAnimation() {
         // 获取旋转中心  
        DisplayMetrics dm = new DisplayMetrics();
        dm = getResources().getDisplayMetrics();
        mCenterX = dm.widthPixels / 2;
        mCenterY = dm.heightPixels / 2;
    
        // 定义旋转方向  
        int duration = 1000;//动画时间
        // 下一页的【question1】旋转方向(从0度转到-90,参考系为水平方向为0度)  
        lQuest1Animation = new Rotate3D(0,-90, mCenterX, mCenterY);    
        lQuest1Animation.setFillAfter(true);//当动画执行完后,控件将停留在执行结束的状态
        //lQuest1Animation.setFillBefore(true);
        lQuest1Animation.setDuration(duration);

         // 下一页的【question2】旋转方向(从90度转到0,参考系为水平方向为0度)(起始第一题)  
        lQuest2Animation = new Rotate3D(90, 0, mCenterX, mCenterY);        
        lQuest2Animation.setFillAfter(true);
        //lQuest1Animation.setFillBefore(true);
        lQuest2Animation.setDuration(duration);

          // 上一页的【question1】旋转方向(从0度转到90,参考系为水平方向为0度)  
        rQuest1Animation = new Rotate3D(0, 90, mCenterX, mCenterY);        
        rQuest1Animation.setFillAfter(true);
        //lQuest1Animation.setFillBefore(true);
        rQuest1Animation.setDuration(duration);

        // 上一页的【question2】旋转方向(从-90度转到0,参考系为水平方向为0度)  
        rQuest2Animation = new Rotate3D(-90, 0, mCenterX, mCenterY);    
        rQuest2Animation.setFillAfter(true);
        //lQuest1Animation.setFillBefore(true);
        rQuest2Animation.setDuration(duration);
    }
}

package yy.android.roate;

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

public class Rotate3D extends Animation {
    private float fromDegree;    //旋转启始角度
    private float toDegree;        //旋转终止角度
    private float mCenterX;        //旋转中心
    private float mCenterY;        //旋转中心
    private Camera mCamera;
    //初始化
    public Rotate3D(float fromDegree, float toDegree, float centerX, float centerY) {
        this.fromDegree = fromDegree;
        this.toDegree = toDegree;
        this.mCenterX = centerX;
        this.mCenterY = centerY;
    }
    @Override//动画初始化
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();//创建一个摄像头
    }

    @Override//在动画播放期间,且interpolatedTime为1.0前不断调用
    //参数一:0.0-0.1时间,它会从0.0逐渐变成0.1.参数二:是代表动画要变换的动作,可以从它获得当前的变化矩阵matrix
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float FromDegree = fromDegree;
        //旋转角度,随着时间的变化,从初始角度逐渐变为目标角度
        float degrees = FromDegree + (toDegree - fromDegree) * interpolatedTime;
        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Matrix matrix = t.getMatrix(); //获得当前的转换矩阵

        if (degrees <= -76.0f) {
            degrees = -90.0f;
            mCamera.save();//保存
            mCamera.rotateY(degrees);//旋转,这样是当前页面垂直于屏幕所以就看不见了
            mCamera.getMatrix(matrix);//获得摄像头当前的转换矩阵,然后在赋给matrix
            mCamera.restore();//恢复
        } else if (degrees >= 76.0f) {//同理
            degrees = 90.0f;
            mCamera.save();
            //mCamera.translate(0, 0,centerX);
             mCamera.rotateY(degrees);
             //mCamera.translate(0, 0,-centerX );
            mCamera.getMatrix(matrix);
            mCamera.restore();
        } else {//当没转的临界角76度时,都是执行以下动作
            mCamera.save(); //保存
            mCamera.translate(0, 0,centerX);//向Z轴方向移动160,也就是一半X的距离,用来设置摄像头的高度    
            mCamera.rotateY(degrees);//沿Y轴方向旋转,degrees是随着时间慢慢趋向距目标值的
            mCamera.translate(0, 0,-centerX );
            //获得摄像头当前的转换矩阵,然后在赋给matrix,不用这句的话,前面都所有动作时无效的
            mCamera.getMatrix(matrix);
            mCamera.restore();//恢复
        }//为什么要把摄像头设置成Z方向为X方向的一半,是因为要达到正方形的旋转效果,而一切
        
         //设置翻转中心点  
        matrix.preTranslate(-centerX, -centerY);//平移到(-320,-480)坐标处
        matrix.postTranslate(centerX, centerY);//
    }  
}
/

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Rotate 3D</string>
    <string name="txt_main">第一页  \n\Android 3D</string>
    <string name="txt_next">第二页  \n\宇智波YI</string>
</resources>

///

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout_main"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"            
    android:orientation="vertical">
    
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:textColor="#ff0000"
        android:text="@string/txt_main"/>            

    <LinearLayout
        android:layout_marginTop="5dip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
          android:layout_gravity="center" >            
        <Button
            android:id="@+id/main_last"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上一頁"/>
        <Button
            android:id="@+id/main_next"
            android:layout_marginLeft="50dip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="下一頁"/>
    </LinearLayout>           
</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout_next"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"            
    android:orientation="vertical">
    
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:textColor="#ff0000"
        android:text="@string/txt_next"/>            

    <LinearLayout
        android:layout_marginTop="5dip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
          android:layout_gravity="center" >            
        <Button
            android:id="@+id/next_last"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上一頁"/>
        <Button
            android:id="@+id/next_next"
            android:layout_marginLeft="50dip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="下一頁"/>
    </LinearLayout>         
</LinearLayout>

///可以参考: Rotate3dAnimation这个工具类!!!
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值