Android 滑动效果进阶篇(五)—— 3D旋转
前面介绍了利用Android自带的控件,进行滑动翻页制作效果,现在我们通过代码实现一些滑动翻页的动画效果。
Animation实现动画有两个方式:帧动画(frame-by-frame animation)和补间动画(tweened animation)
本示例通过继承Animation自定义Rotate3D,实现3D翻页效果。效果图如下:
1、Rotate3D(Animation)
首先,自定义Animation的3D动画类Rotate3D
- public class Rotate3D extends Animation {
- private float fromDegree; // 旋转起始角度
- private float toDegree; // 旋转终止角度
- private float mCenterX; // 旋转中心x
- private float mCenterY; // 旋转中心y
- 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
- protected void applyTransformation(float interpolatedTime, Transformation t) {
- final float FromDegree = fromDegree;
- float degrees = FromDegree + (toDegree - fromDegree) * interpolatedTime; // 旋转角度(angle)
- 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);
- mCamera.restore();
- } else if (degrees >= 76.0f) {
- degrees = 90.0f;
- mCamera.save();
- mCamera.rotateY(degrees);
- mCamera.getMatrix(matrix);
- mCamera.restore();
- } else {
- mCamera.save();
- mCamera.translate(0, 0, centerX); // 位移x
- mCamera.rotateY(degrees);
- mCamera.translate(0, 0, -centerX);
- mCamera.getMatrix(matrix);
- mCamera.restore();
- }
- matrix.preTranslate(-centerX, -centerY);
- matrix.postTranslate(centerX, centerY);
- }
- }
然后,实例化Rotate3D的旋转方向
- public void initAnimation() {
- // 获取旋转中心
- DisplayMetrics dm = new DisplayMetrics();
- dm = getResources().getDisplayMetrics();
- mCenterX = dm.widthPixels / 2;
- mCenterY = dm.heightPixels / 2;
- // 定义旋转方向
- int duration = 1000;
- lQuest1Animation = new Rotate3D(0, -90, mCenterX, mCenterY); // 下一页的【question1】旋转方向(从0度转到-90,参考系为水平方向为0度)
- lQuest1Animation.setFillAfter(true);
- lQuest1Animation.setDuration(duration);
- lQuest2Animation = new Rotate3D(90, 0, mCenterX, mCenterY); // 下一页的【question2】旋转方向(从90度转到0,参考系为水平方向为0度)(起始第一题)
- lQuest2Animation.setFillAfter(true);
- lQuest2Animation.setDuration(duration);
- rQuest1Animation = new Rotate3D(0, 90, mCenterX, mCenterY); // 上一页的【question1】旋转方向(从0度转到90,参考系为水平方向为0度)
- rQuest1Animation.setFillAfter(true);
- rQuest1Animation.setDuration(duration);
- rQuest2Animation = new Rotate3D(-90, 0, mCenterX, mCenterY); // 上一页的【question2】旋转方向(从-90度转到0,参考系为水平方向为0度)
- rQuest2Animation.setFillAfter(true);
- rQuest2Animation.setDuration(duration);
- }
2、Activity
首先,定义两个布局文件,用于旋转的画面切换
main.xml
- <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">
- ...
- </LinearLayout>
next.xml
- <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">
- ...
- </LinearLayout>
限于篇幅,完整布局文件请详见源码 ^_^
然后,初始化两个旋转的布局文件资源
- 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);
- }
最后,设置布局文件中的按钮监听事件,响应3D旋转动画和方向
- private View.OnClickListener listener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.main_last: // 上一页
- layoutmain.startAnimation(lQuest1Animation); // 当前页向左旋转(0,-90)
- initNext();
- layoutnext.startAnimation(lQuest2Animation); // 下一页向左旋转(90, 0)
- break;
- case R.id.main_next: // 下一页
- layoutmain.startAnimation(rQuest1Animation); // 当前页向右旋转(0,90)
- initNext();
- layoutnext.startAnimation(rQuest2Animation); // 下一页向右旋转(-90, 0)
- break;
- case R.id.next_last:
- layoutnext.startAnimation(lQuest1Animation);
- initMain();
- layoutmain.startAnimation(lQuest2Animation);
- break;
- case R.id.next_next:
- layoutnext.startAnimation(rQuest1Animation);
- initMain();
- layoutmain.startAnimation(rQuest2Animation);
- break;
- }
- }
- };
Android 滑动效果进阶篇(五)—— 3D旋转的更多相关文章
- Android 滑动效果进阶篇(六)—— 倒影效果
上篇介绍了使用Animation实现3D动画旋转翻页效果,现在介绍图片倒影实现,先看效果图 本示例主要通过自定义Gallery和ImageAdapter(继承自BaseAdapter)实现 1.倒影绘 ...
- Android 滑动效果入门篇(二)—— Gallery
Gallery 是Android官方提供的一个View容器类,继承于AbsSpinner类,用于实现页面滑动效果. 从上面的继承关系可以看出,AbsSpinner类继承自AdapterView,因此我 ...
- Android 滑动效果入门篇(一)—— ViewFlipper
ViewFilpper 是Android官方提供的一个View容器类,继承于ViewAnimator类,用于实现页面切换,也可以设定时间间隔,让它自动播放.又ViewAnimator继承至于Frame ...
- Android 滑动效果高级篇(八)—— 自定义控件
自定义控件,较常用View.ViewGroup.Scroller三个类,其继承关系如下: 本示例自定义控件,实现一个Gallery效果,并添加了一个显示View个数和位置的bar条,效果图: 自定义控 ...
- Android 滑动效果基础篇(四)—— Gallery + GridView
Android系统自带一个GridView和Gallery两个控件,GridView网格显示,Gallery单个浏览,两者结合起来可以真正实现Gallery浏览图片效果. 本示例通过GridView和 ...
- Android 滑动效果基础篇(三)—— Gallery仿图像集浏览
Android系统自带一个Gallery浏览图片的应用,通过手指拖动时能够非常流畅的显示图片,用户交互和体验都很好. 本示例就是通过Gallery和自定义的View,模仿实现一个仿Gallery图像集 ...
- Android 滑动效果高级篇(七)—— 华丽翻页效果
By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处 之前看到像ipad上的ibook的模拟书籍翻页的特效感觉很炫,在android上也有像laputa和ireader ...
- 十六、Android 滑动效果汇总
Android 滑动效果入门篇(一)—— ViewFlipper Android 滑动效果入门篇(二)—— Gallery Android 滑动效果基础篇(三)—— Gallery仿图像集浏览 And ...
- Android 滑动效果汇总
Android 滑动效果入门篇(一)—— ViewFlipper Android 滑动效果入门篇(二)—— Gallery Android 滑动效果基础篇(三)—— Gallery仿图像集浏览 And ...
随机推荐
- 【转载】ACM总结——dp专辑
感谢博主—— http://blog.csdn.net/cc_again?viewmode=list ---------- Accagain 2014年5月15日 动态规划一 ...
- Spring Bean基本管理--bean注入方式汇总
依赖注入方式:Spring支持两种依赖注入方式,分别是属性注入和构造函数注入.还有工厂方法注入方式. 依赖注入还分为:注入依赖对象可以采用手工装配或自动装配,在实际应用开发中建议使用手工装配,因为自动 ...
- Matlab编程实例(3) 函数向左或向右平移N点 左移右移
%函数移动 close all; clear all; dir=input('请输入平移方向,“1”为向左,“2”为向右'); if dir~=1&&dir~=2;%输入控制 e ...
- strcasecmp在VS2010中提示未定义标识符
分析: strcasecmp(*,*)是用来比较字符串,定义在string.h头文件中,但是在windows下即使添加string.h头文件,依然会报错. 解决: 添加 #if defined(_MS ...
- 【和我一起学python吧】python 中的函数
一.函数的定义: Python中使用def关键字定义函数,函数包括函数名称和参数,不需要定义返回类型,Python能返回任何类型: #没有返回值的函数,其实返回的是None def run(name) ...
- 结合Vim ghostscript 将源代码文件转换成语法高亮的pdf格式文档
step 1: 安装ghostscript (debian 环境, 其他环境自行google) sudo apt-get install ghostscript step 2: 用Vim生成ps文件 ...
- 安装CPqD/ofdissector遭遇的错误
为了安装支持openflow1.3的wireshark插件,在下载了ofdissector.git,并进入了其src目录后,执行scons install,出现如下错误: util/FieldMana ...
- leetcode—Plus one
1.题目描述 Given a number represented as an array of digits, plus one to the number. 2.解法分析 不要被常规思路限制住 ...
- HttpComponents 学习的两个重要文档
httpcore-tutorial-simplified-chinese httpclient-tutorial-simplified-chinese
- -bash: ./radar.sh: /bin/sh^M: bad interpreter: 没有那个文件或目录
运行shell脚本时,报下面这个错误: -bash: ./radar.sh: /bin/sh^M: bad interpreter: 没有那个文件或目录 错误分析: 因为操作系统是windows, ...