基于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

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

(0)

相关推荐

  • Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果

    本文实例讲述了Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果.分享给大家供大家参考,具体如下: 1. 滚动加载 listView.setOnScrollListener(new OnScrollListener() { //添加滚动条滚到最底部,加载余下的元素 @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == OnScro

  • Android通过手势实现答题器翻页效果

    本文实例为大家分享了Android答题器翻页功能,主要使用ViewFilpper和GestureDetector来实现,供大家参考,具体内容如下 1.效果图 2.实现思路 把Activity的TouchEvent事件交个GestureDetector来处理,然后使用ViewFilpper使用动画控制多个组件的之间的切换效果.手势的一个Api就不详细说了,大家如果不了解可以查一下. 3.实现的步骤 1).构建手势检测器 2).准备数据 3).为ViewFilpper添加子控件. 4).初始化Ani

  • Android实现阅读APP平移翻页效果

    自己做的一个APP需要用到翻页阅读,网上看过立体翻页效果,不过bug太多了还不兼容.看了一下多看阅读翻页是采用平移翻页的,于是就仿写了一个平移翻页的控件.效果如下: 在翻页时页面右边缘绘制了阴影,效果还不错.要实现这种平移翻页控件并不难,只需要定义一个布局管理页面就可以了.具体实现上有以下难点: 1.循环翻页,页面的重复利用. 2.在翻页时过滤掉多点触碰. 3.采用setAdapter的方式设置页面布局和数据. 下面就来一一解决这几个难点.首先看循环翻页问题,怎么样能采用较少的页面实现这种翻页呢

  • Android利用悬浮按钮实现翻页效果

    今天给大家分享下自己用悬浮按钮点击实现翻页效果的例子. 首先,一个按钮要实现悬浮,就要用到系统顶级窗口相关的WindowManager,WindowManager.LayoutParams.那么在AndroidManifest.xml中添加权限: <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 然后,我们要对WindowManager,WindowManager.Layout

  • Android程序开发ListView+Json+异步网络图片加载+滚动翻页的例子(图片能缓存,图片不错乱)

    例子中用于解析Json的Gson请自己Google下载 主Activity: package COM.Example.Main; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import COM.Example.Main.R; import COM.Example.Main.stringG

  • Android使用手势实现翻页效果

    本程序的手势检测思路就是把Activity的TouchEvent交给GestureDetector处理,本程序使用了一个ViewFlipper组件,ViewFlipper可使用动画控制多个组件之间的切换效果. 本实例程序通过GestureDetector来检测用户的手势动作,并根据手势动作来控制ViewFlipper包含的View组件的切换,从而实现翻页效果. activity_main.xml布局界面代码: <?xml version="1.0" encoding="

  • android ViewPager实现滑动翻页效果实例代码

    实现ViewPager的滑动翻页效果可以使用ViewPager的setPageTransformer方法,如下: import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.View; public class ReadViewPager extends ViewPager { public ReadV

  • android自定义控件创建翻页接口详细代码

    本文分享的这个类的目的是为在看书翻页时,需要进行的动作提供接口,利用android自定义控件创建翻页接口,具体内容如下 BookPage.java package com.horse.util; import java.text.DecimalFormat; import java.util.Vector; import com.horse.bean.Chapter; import android.graphics.Bitmap; import android.graphics.Canvas;

  • 解析Android中实现滑动翻页之ViewFlipper的使用详解

    1)View切换的控件-ViewFlipper介绍 ViewFilpper类继承于ViewAnimator类.而ViewAnimator类继承于FrameLayout. 查看ViewAnimator类的源码可以看出此类的作用主要是为其中的View切换提供动画效果.该类有如下几个和动画相关的方法. setInAnimation:设置View进入屏幕时候使用的动画.该方法有两个重载方法,即可以直接传入Animation对象,也可以传入定义的Animation文件的resourceID. setOut

  • android中图片翻页效果简单的实现方法

    复制代码 代码如下: public class PageWidget extends View {    private Bitmap foreImage;    private Bitmap bgImage;    private PointF touchPt;    private int screenWidth;    private int screenHeight;    private GradientDrawable shadowDrawableRL;    private Gra

随机推荐