当前位置: 首页 > 编程笔记 >

基于Android实现3D翻页效果

汪同
2023-03-14
本文向大家介绍基于Android实现3D翻页效果,包括了基于Android实现3D翻页效果的使用技巧和注意事项,需要的朋友参考一下

最近做了一个简单的3D效果翻页特效,先说说我的思路吧,首先我这个翻页效果并不是两个Activity之间的跳转,而是在同一个activity类切换不同的view而已。我现在的做法是单击一个button然后Gone当前的布局,然后把需要呈现的布局visible,在隐藏当前布局的时候启动动画,然后给动画添加监听,在动画结束时开始另外一个view的入场动画就行了。
下面来看下我的主页面的布局文件:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 android:id="@+id/container" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" > 
 
 <include 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 layout="@layout/layout2" /> 
 
 <include 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 layout="@layout/layout1" /> 
 
</FrameLayout> 

我这个布局文件使用<include>标签包含了另外2个布局文件,这些布局文件才是呈现数据的,下面是另外2个布局文件

layout1:

<?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:background="@drawable/test1" 
 android:orientation="vertical" 
 android:id="@+id/container1" 
 > 
 
 <Button 
 android:id="@+id/bt_towhile" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_gravity="center" 
 android:text="白色" /> 
 
</LinearLayout> 

layout2:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 android:id="@+id/container2" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="@drawable/test2" 
 android:orientation="vertical" > 
 
 <Button 
 android:id="@+id/bt_toblack" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_gravity="center" 
 android:text="黑色" /> 
 
</LinearLayout> 

我这里只是举个例子并没有放什么实际的类容,只是放了2个button,当我点击其中一个跳转到另外一个layout。

有了布局文件那我们就开始要实现功能了,我们的想法是点击按钮的时候开始一个动画等动画结束时再开启另外一个动画并隐藏和展示layout1和layout2。

下面是我写的一个动画工具类源码:

package com.test.view; 
 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.animation.Animation; 
import android.view.animation.DecelerateInterpolator; 
 
public class RotateAnimationUtil { 
 
 private ViewGroup context; 
 
 private View[] views; 
 
 public RotateAnimationUtil(ViewGroup context, View... views) { 
 super(); 
 this.context = context; 
 this.views = views; 
 } 
 
 /** 
 * 应用自定义的Rotate3DAnimation动画 
 * 
 * @param flag 
 *  当前控件的顺序坐标 
 * @param startDegress 
 *  开始的角度 
 * @param endDegress 
 *  结束的角度 
 */ 
 public void applyRotateAnimation(int flag, float startDegress, 
  float endDegress) { 
 final float centerX = context.getWidth() / 2.0f; 
 final float centerY = context.getHeight() / 2.0f; 
 
 Rotate3DAnimation rotate = new Rotate3DAnimation(startDegress, 
  endDegress, centerX, centerY, 310.0f, true); 
 rotate.setDuration(1000); 
 rotate.setFillAfter(false); 
 rotate.setInterpolator(new DecelerateInterpolator()); 
 
 rotate.setAnimationListener(new DisplayNextView(flag)); 
 context.startAnimation(rotate); 
 } 
 
 private final class DisplayNextView implements Animation.AnimationListener { 
 
 private final int mFlag; 
 
 private DisplayNextView(int flag) { 
  mFlag = flag; 
 } 
 
 public void onAnimationStart(Animation animation) { 
 
 } 
 
 // 动画结束 
 
 public void onAnimationEnd(Animation animation) { 
  context.post(new SwapViews(mFlag)); 
 } 
 
 public void onAnimationRepeat(Animation animation) { 
 
 } 
 } 
 
 /** 
 * 新开一个线程动画结束后再开始一次动画效果实现翻屏特效 
 * 
 * @author yangzhiqiang 
 * 
 */ 
 private final class SwapViews implements Runnable { 
 
 private final int mFlag; 
 
 public SwapViews(int mFlag) { 
  this.mFlag = mFlag; 
 } 
 
 public void run() { 
  final float centerX = context.getWidth() / 2.0f; 
  final float centerY = context.getHeight() / 2.0f; 
  Rotate3DAnimation rotation; 
  if (mFlag > -1) { 
  views[0].setVisibility(View.GONE); 
  views[1].setVisibility(View.VISIBLE); 
  views[1].requestFocus(); 
  rotation = new Rotate3DAnimation(270, 360, centerX, centerY, 
   310.0f, false); 
  } else { 
  views[1].setVisibility(View.GONE); 
  views[0].setVisibility(View.VISIBLE); 
  views[0].requestFocus(); 
  rotation = new Rotate3DAnimation(90, 0, centerX, centerY, 
   310.0f, false); 
  } 
  rotation.setDuration(1000); 
  rotation.setFillAfter(false); 
  rotation.setInterpolator(new DecelerateInterpolator()); 
  // 开始动画 
  context.startAnimation(rotation); 
 
 } 
 
 } 
 
} 

解释一下这个类的构造方法

public RotateAnimationUtil(ViewGroup context, View... views) { 
 super(); 
 this.context = context; 
 this.views = views; 
 } 

有2个参数,第一个参数就是我们的主布局页面的FrameLayout,第2个参数就是我们要进行动画切换的2个子layout,我这使用的是一个可变长参数只是为了方便而已。

public void applyRotateAnimation(int flag, float startDegress,float endDegress)方法第一个参数是标记当前是第是从哪个个layout跳转,因外我们必须知道当前开始跳转的layout才能推算角度。
下面是我自定义动画的源码:

package com.test.view; 
 
import android.graphics.Camera; 
import android.graphics.Matrix; 
import android.view.animation.Animation; 
import android.view.animation.Transformation; 
 
public class Rotate3DAnimation extends Animation { 
 
 private final float mFormDegress; 
 
 private final float mToDegress; 
 
 private final float mCenterX; 
 
 private final float mCenterY; 
 
 /** 
 * 控制z轴的一个常量值,主要是控制动画的升降距离 
 */ 
 private final float mDepthz; 
 
 /** 
 * 控制z轴是像上移动还是向下移动,从而实现升降效果 
 */ 
 private final boolean mReverse; 
 
 private Camera mCamera; 
 
 public Rotate3DAnimation(float formDegress, float toDegress, float centerX, 
  float centerY, float depthz, boolean reverse) { 
 super(); 
 this.mFormDegress = formDegress; 
 this.mToDegress = toDegress; 
 this.mCenterX = centerX; 
 this.mCenterY = centerY; 
 this.mDepthz = depthz; 
 this.mReverse = reverse; 
 } 
 
 @Override 
 public void initialize(int width, int height, int parentWidth, 
  int parentHeight) { 
 super.initialize(width, height, parentWidth, parentHeight); 
 mCamera = new Camera(); 
 } 
 
 /** 
 * interpolatedTime 取值范围是0-1之间当每次,当动画启动后会系统会不停的调用applyTransformation方法, 
 * 并改变interpolatedTime的值 
 */ 
 @Override 
 protected void applyTransformation(float interpolatedTime, Transformation t) { 
 final float formDegress = mFormDegress; 
 // 通过差点值计算出转变的角度 
 float degress = formDegress 
  + ((mToDegress - formDegress) * interpolatedTime); 
 final float centerX = mCenterX; 
 final float centerY = mCenterY; 
 final Camera camera = mCamera; 
 
 // 得到当前矩阵 
 Matrix matrix = t.getMatrix(); 
 // 报错当前屏幕的状态 
 camera.save(); 
 // 判断是降还是升 
 if (mReverse) { 
  // 正向改变Z轴角度 
  camera.translate(0.0f, 0.0f, mDepthz * interpolatedTime); 
 } else { 
  // 反向改变Z轴角度 
  camera.translate(0.0f, 0.0f, mDepthz * (1.0f - interpolatedTime)); 
 } 
 // 旋转Y轴角度 
 camera.rotateY(degress); 
 // 把当前改变后的矩阵信息复制给Transformation的Matrix 
 camera.getMatrix(matrix); 
 // 根据改变后的矩阵信息从新恢复屏幕 
 camera.restore(); 
 
 // 让动画在屏幕中间运行 
 matrix.preTranslate(-centerX, -centerY); 
 matrix.postTranslate(centerX, centerY); 
 } 
} 

如果你不需要沉降效果那么你把下面的代码删除掉即可:

if (mReverse) { 
  // 正向改变Z轴角度 
  camera.translate(0.0f, 0.0f, mDepthz * interpolatedTime); 
 } else { 
  // 反向改变Z轴角度 
  camera.translate(0.0f, 0.0f, mDepthz * (1.0f - interpolatedTime)); 
 } 

好了核心代码已经上完,下面是主界面代码:

package com.test.rotateanimation; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.widget.FrameLayout; 
import android.widget.LinearLayout; 
 
import com.test.view.RotateAnimationUtil; 
 
public class MainActivity extends Activity { 
 
 private FrameLayout container; 
 
 private LinearLayout container1; 
 
 private LinearLayout container2; 
 
 private RotateAnimationUtil rotateAnimationUtil; 
 
 private Button bt_towhile; 
 
 private Button bt_toblack; 
 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.activity_main); 
 initView(); 
 
 bt_towhile.setOnClickListener(new View.OnClickListener() { 
 
  @Override 
  public void onClick(View v) { 
  rotateAnimationUtil.applyRotateAnimation(1, 0, 90); 
  } 
 }); 
 bt_toblack.setOnClickListener(new View.OnClickListener() { 
 
  @Override 
  public void onClick(View v) { 
  rotateAnimationUtil.applyRotateAnimation(-1, 0, -90); 
  } 
 }); 
 
 // 设置当前View控件的缓存 
 container 
  .setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE); 
 } 
 
 private void initView() { 
 container = (FrameLayout) findViewById(R.id.container); 
 bt_toblack = (Button) findViewById(R.id.bt_toblack); 
 bt_towhile = (Button) findViewById(R.id.bt_towhile); 
 
 container1 = (LinearLayout) findViewById(R.id.container1); 
 container2 = (LinearLayout) findViewById(R.id.container2); 
 
 rotateAnimationUtil = new RotateAnimationUtil(container, container1, 
  container2); 
 } 
 
 @Override 
 public boolean onCreateOptionsMenu(Menu menu) { 
 getMenuInflater().inflate(R.menu.activity_main, menu); 
 return true; 
 } 
 
} 

下面是运行效果,剪切效果不好,呵呵.

 源码下载:http://xiazai.jb51.net/201606/yuanma/RotateAnimation(jb51.net).rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 本文向大家介绍Android实现3D翻转动画效果,包括了Android实现3D翻转动画效果的使用技巧和注意事项,需要的朋友参考一下 Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和 Transformation。 Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放

  • 本文向大家介绍Android使用animator实现fragment的3D翻转效果,包括了Android使用animator实现fragment的3D翻转效果的使用技巧和注意事项,需要的朋友参考一下 今天老师留的作业,使用俩个Fragment来实现3D翻转效果,遇到了一点点的问题,于是在网上进行了查找,但是发现有些博主的代码不正确,对其他人进行了误导,在网上使用属性动画实现3D效果非常少,所以经过

  • 本文向大家介绍Bootstrap实现翻页效果,包括了Bootstrap实现翻页效果的使用技巧和注意事项,需要的朋友参考一下 Bootstrap之翻页。 优点: 支持局部刷新; 只要是列表,都可以加载该组件; 支持动态数据绑定; 当然还有绝对的简单实用。 效果图 最后一页时: 最开始一页时: 实现 ①、翻页组件的布局 pageNum:第几页 rel:要刷新哪一个div的id urlParas:其他参

  • 本文向大家介绍Android使用手势实现翻页效果,包括了Android使用手势实现翻页效果的使用技巧和注意事项,需要的朋友参考一下 本程序的手势检测思路就是把Activity的TouchEvent交给GestureDetector处理,本程序使用了一个ViewFlipper组件,ViewFlipper可使用动画控制多个组件之间的切换效果。 本实例程序通过GestureDetector来检测用户的手

  • 本文向大家介绍基于jquery.page.js实现分页效果,包括了基于jquery.page.js实现分页效果的使用技巧和注意事项,需要的朋友参考一下 基于jquery.page.js的一款简单的分页效果,供大家参考,具体内容如下 调用方法如下: pageCount:总页数 current:当前页 以下是jquery.page.js源代码: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望

  • 本文向大家介绍Android实现阅读APP平移翻页效果,包括了Android实现阅读APP平移翻页效果的使用技巧和注意事项,需要的朋友参考一下 自己做的一个APP需要用到翻页阅读,网上看过立体翻页效果,不过bug太多了还不兼容。看了一下多看阅读翻页是采用平移翻页的,于是就仿写了一个平移翻页的控件。效果如下: 在翻页时页面右边缘绘制了阴影,效果还不错。要实现这种平移翻页控件并不难,只需要定义一个布局