Android利用Camera实现中轴3D卡牌翻转效果

在Android系统API中,有两个Camera类:

  • android.graphics.Camera
  • android.hardware.Camera

第二个应用于手机硬件中的相机相关的操作,本文讲述的是利用第一个Camera类实现中轴3D转换的卡牌翻转效果,开始之前,先看一下Android系统中的坐标系:

对应于三维坐标系中的三个方向,Camera提供了三种旋转方法:

  • rotateX()
  • rotateY()
  • rotateX()

调用这三种方法,传入旋转角度参数,即可实现视图沿着坐标轴旋转的功能。本文的中轴3D旋转效果就是让视图沿着Y轴旋转的。

系统API Demos中已经为我们提供了一个非常好用的3D旋转动画的工具类:
Rotate3dAnimation.java:

package com.feng.androidtest;

import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.Transformation;

/**
 * An animation that rotates the view on the Y axis between two specified angles.
 * This animation also adds a translation on the Z axis (depth) to improve the effect.
 */
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;

 /**
  * Creates a new 3D rotation on the Y axis. The rotation is defined by its
  * start angle and its end angle. Both angles are in degrees. The rotation
  * is performed around a center point on the 2D space, definied by a pair
  * of X and Y coordinates, called centerX and centerY. When the animation
  * starts, a translation on the Z axis (depth) is performed. The length
  * of the translation can be specified, as well as whether the translation
  * should be reversed in time.
  *
  * @param fromDegrees the start angle of the 3D rotation
  * @param toDegrees the end angle of the 3D rotation
  * @param centerX the X center of the 3D rotation
  * @param centerY the Y center of the 3D rotation
  * @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();

  Log.i("interpolatedTime", interpolatedTime+"");
  camera.save();
  if (mReverse) {
   camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
  } else {
   camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
  }
  camera.rotateY(degrees);
  camera.getMatrix(matrix);
  camera.restore();

  matrix.preTranslate(-centerX, -centerY);
  matrix.postTranslate(centerX, centerY);
 }
}

可以看出, Rotate3dAnimation 总共做了两件事:在构造函数中赋值了旋转动画所需要的参数,以及重写(override)父类Animation中的applyTransformation()方法,下面分类阐述一下:

  • fromDegrees与toDegrees
  • 视图旋转的开始角度和结束角度,当toDegree处于90倍数时,视图将变得不可见。
  • centerX与centerY
  • 视图旋转的中心点。
  • depthZ
  • Z轴移动基数,用于计算Camera在Z轴移动距离
  • reverse
  • boolean类型,控制Z轴移动方向,达到视觉远近移动导致的视图放大缩小效果。
  • applyTransformation()
  • 根据动画播放的时间 interpolatedTime (动画start到end的过程,interpolatedTime从0.0变化到1.0),让Camera在Z轴方向上进行相应距离的移动,实现视觉上远近移动的效果。然后调用 rotateX()方法,让视图围绕Y轴进行旋转,产生3D立体旋转效果。最后再通过Matrix来确定旋转的中心点的位置。

activity_main.xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:background="@android:color/white" >

 <Button
  android:id="@+id/btn_open"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_margin="16dp"
  android:onClick="onClickView"
  android:text="打开"
  android:textColor="@android:color/black"
  android:textSize="16sp" />

 <RelativeLayout
  android:id="@+id/rl_content"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_below="@id/btn_open"
  android:layout_marginTop="16dp"
  android:background="@android:color/black">

  <ImageView
   android:id="@+id/iv_logo"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:contentDescription="@null"
   android:src="@drawable/ic_qrcode"
   android:scaleType="centerInside"/>

  <TextView
   android:id="@+id/tv_desc"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:padding="16dp"
   android:text="我们。"
   android:textColor="@android:color/white"
   android:textSize="18sp"
   android:visibility="gone"/>
 </RelativeLayout>

</RelativeLayout>

布局中配置了卡牌正面的图片控件,卡牌背面的文本控件,以及他们的parent容器,也就是本文中的旋转动画的执行对象。

MainActivity.java文件:

package com.feng.androidtest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.androidtest.R;

public class MainActivity extends Activity {

 private RelativeLayout mContentRl;
 private ImageView mLogoIv;
 private TextView mDescTv;
 private Button mOpenBtn;

 private int centerX;
 private int centerY;
 private int depthZ = 400;
 private int duration = 600;
 private Rotate3dAnimation openAnimation;
 private Rotate3dAnimation closeAnimation;

 private boolean isOpen = false;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  mContentRl = (RelativeLayout) findViewById(R.id.rl_content);
  mLogoIv = (ImageView) findViewById(R.id.iv_logo);
  mDescTv = (TextView) findViewById(R.id.tv_desc);
  mOpenBtn = (Button) findViewById(R.id.btn_open);

 }

 /**
  * 卡牌文本介绍打开效果:注意旋转角度
  */
 private void initOpenAnim() {
  //从0到90度,顺时针旋转视图,此时reverse参数为true,达到90度时动画结束时视图变得不可见,
  openAnimation = new Rotate3dAnimation(0, 90, centerX, centerY, depthZ, true);
  openAnimation.setDuration(duration);
  openAnimation.setFillAfter(true);
  openAnimation.setInterpolator(new AccelerateInterpolator());
  openAnimation.setAnimationListener(new AnimationListener() {

   @Override
   public void onAnimationStart(Animation animation) {

   }

   @Override
   public void onAnimationRepeat(Animation animation) {

   }

   @Override
   public void onAnimationEnd(Animation animation) {
    mLogoIv.setVisibility(View.GONE);
    mDescTv.setVisibility(View.VISIBLE);

    //从270到360度,顺时针旋转视图,此时reverse参数为false,达到360度动画结束时视图变得可见
    Rotate3dAnimation rotateAnimation = new Rotate3dAnimation(270, 360, centerX, centerY, depthZ, false);
    rotateAnimation.setDuration(duration);
    rotateAnimation.setFillAfter(true);
    rotateAnimation.setInterpolator(new DecelerateInterpolator());
    mContentRl.startAnimation(rotateAnimation);
   }
  });
 }

 /**
  * 卡牌文本介绍关闭效果:旋转角度与打开时逆行即可
  */
 private void initCloseAnim() {
  closeAnimation = new Rotate3dAnimation(360, 270, centerX, centerY, depthZ, true);
  closeAnimation.setDuration(duration);
  closeAnimation.setFillAfter(true);
  closeAnimation.setInterpolator(new AccelerateInterpolator());
  closeAnimation.setAnimationListener(new AnimationListener() {

   @Override
   public void onAnimationStart(Animation animation) {

   }

   @Override
   public void onAnimationRepeat(Animation animation) {

   }

   @Override
   public void onAnimationEnd(Animation animation) {
    mLogoIv.setVisibility(View.VISIBLE);
    mDescTv.setVisibility(View.GONE);

    Rotate3dAnimation rotateAnimation = new Rotate3dAnimation(90, 0, centerX, centerY, depthZ, false);
    rotateAnimation.setDuration(duration);
    rotateAnimation.setFillAfter(true);
    rotateAnimation.setInterpolator(new DecelerateInterpolator());
    mContentRl.startAnimation(rotateAnimation);
   }
  });
 }

 public void onClickView(View v) {
  //以旋转对象的中心点为旋转中心点,这里主要不要再onCreate方法中获取,因为视图初始绘制时,获取的宽高为0
  centerX = mContentRl.getWidth()/2;
   centerY = mContentRl.getHeight()/2;
   if (openAnimation == null) {
   initOpenAnim();
   initCloseAnim();
  }

   //用作判断当前点击事件发生时动画是否正在执行
  if (openAnimation.hasStarted() && !openAnimation.hasEnded()) {
   return;
  }
  if (closeAnimation.hasStarted() && !closeAnimation.hasEnded()) {
   return;
  }

  //判断动画执行
  if (isOpen) {
   mContentRl.startAnimation(closeAnimation);

  }else {

   mContentRl.startAnimation(openAnimation);
  }

  isOpen = !isOpen;
  mOpenBtn.setText(isOpen ? "关闭" : "打开");
 }
}

代码中已对核心的地方做了注释解释,主要弄清楚 rotate3dAnimation构造参数中的 fromDegrees和toDegrees、depthZ、reverse参数,同时在动画中设置了速度插播器,如动画的前半程使用加速器 AccelerateInterpolator,后半程使用减速器 DecelerateInterpolator,使动画体验更加人性化。

以上就是本文的全部内容,希望对大家的学习Android软件编程有所帮助。

(0)

相关推荐

  • Android 屏幕实现上下翻转

    Android 屏幕实现上下翻转 通常我们的应用只会设计成横屏或者竖屏,锁定横屏或竖屏的方法是在manifest.xml文件中设定属性android:screenOrientation为"landscape"或"portrait": <activity android:name="com.example.kata1.MainActivity" android:label="@string/app_name" androi

  • Android ViewFlipper翻转视图使用详解

    简介 ViewFlipper是Android自带的一个多页面管理控件且可以自动播放!它和ViewPager有所不同,ViewPager继承自ViewGroup,是一页一页的,可以带动画效果,可以兼容低版本:而ViewFlipper继承ViewAnimator,是一层一层的,切换View的时候可以设置动画效果,是Android 4.0才引入的新控件.使用场景和ViewPager基本一样,在很多时候都是用来实现进入应用后的引导页或者用于图片轮播显示. 常用方法 setInAnimation:View

  • Android实现卡片翻转动画

    最近项目上用到了卡片的翻转效果,大致研究了下,也参考了网上的一些Demo,简单实现如下: activity_main.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/card_main_container&

  • Android实现Flip翻转动画效果

    本文实例讲述了Android实现Flip翻转动画效果的方法,分享给大家供大家学习借鉴. 具体实现代码如下: LinearLayout locationLL = (LinearLayout) findViewById(R.id.locationLL); LinearLayout baseLL = (LinearLayout) findViewById(R.id.baseLL); private void flipit() { Interpolator accelerator = new Accel

  • Android图片翻转动画简易实现代码

    下面给大家分享一个有趣的动画:这里比较适合一张图片的翻转,如果是多张图片,可以参考APIDemo里的例子,就是加个ArrayAdapter,还是简单的,也可以自己发挥修改,实现自己想要的.这里的代码基本上可以直接运行项目了. 在main.xml里加个ImageView,如 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http:/

  • Android实现图片反转、翻转、旋转、放大和缩小

    ********************************************************************** android 实现图片的翻转 ********************************************************************** Resources res = this.getContext().getResources(); img = BitmapFactory.decodeResource(res, R.

  • Android实现文字翻转动画的效果

    本文实现了Android程序文字翻转动画的小程序,具体代码如下: 先上效果图如下: 要求: 沿Y轴正方向看,数值减1时动画逆时针旋转,数值加1时动画顺时针旋转. 实现动画的具体细节见"RotateAnimation.Java".为方便查看动画旋转方向,可以将RotateAnimation.DEBUG值设置为true即可.
 RotateAnimation参考自APIDemos的Rotate3DAnimation
 RotateAnimation的构造函数需有三个参数,分别说明动画组件的

  • Android动画之3D翻转效果实现函数分析

    Android中的翻转动画效果的实现,首先看一下运行效果如上图所示. Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和 Transformation. Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放等等.而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画的,而alpha值是用来做alpha动画的,要实现3D旋转动画

  • Android利用Camera实现中轴3D卡牌翻转效果

    在Android系统API中,有两个Camera类: android.graphics.Camera android.hardware.Camera 第二个应用于手机硬件中的相机相关的操作,本文讲述的是利用第一个Camera类实现中轴3D转换的卡牌翻转效果,开始之前,先看一下Android系统中的坐标系: 对应于三维坐标系中的三个方向,Camera提供了三种旋转方法: rotateX() rotateY() rotateX() 调用这三种方法,传入旋转角度参数,即可实现视图沿着坐标轴旋转的功能.

  • Unity3D利用DoTween实现卡牌翻转效果

    利用Unity的UGUI制作了2D卡牌翻转的效果,如果是sprite对象的话,原理应该也是一样的,以下是效果图 图1 卡牌翻转效果 关于DoTween DoTween是一款十分强大且好用的动画效果插件,有免费版和收费版,免费版就可以满足大部分需求了,在Unity Assets Store里就可以下载,在本效果里就用了DoTween的旋转功能. 设计思路 创建一个空物体,空物体下有两个image对象,一个是正面,一个是背面.假设我们从正面开始,则初始状态下正面的旋转角度为(0,0,0) (0,0,

  • 利用Vue实现卡牌翻转的特效

    目录 前言 实现 鼠标移入选中效果 卡片翻转效果 完整代码 结语 前言 今天是正月初九,也是活动的倒数第二天,复工都三天了,而我三篇春节文章还没写完,实在是太混了!这次带来的是一个春节抽福卡页面,采用卡牌翻转的形式. 实现 以下所有的实现都是基于Vue2 来编写的. (别骂了,我这就去学 Vue3 鼠标移入选中效果 从上面的效果图可以看到,当鼠标移动到某张福卡的时候,这张福卡就会放大,其余未被选中的卡片就会缩小且变得模糊.这样的视觉效果是通过 CSS 和 JS 一起控制的. 其实只用 css 也

  • Unity实现卡牌翻动效果

    本文实例为大家分享了Unity实现卡牌翻动效果展示的具体代码,供大家参考,具体内容如下 事实上这是项目需要,我改的一个代码,实际上就是利用unity的一些基础属性实现其效果.啥也不多说了,先上原代码: /// Credit Mrs. YakaYocha /// Sourced from - https://www.youtube.com/channel/UCHp8LZ_0-iCvl-5pjHATsgw /// Please donate: https://www.paypal.com/cgi-b

  • Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载

    首先给大家展示靓照,对效果图感兴趣的朋友可以继续往下阅读哦. ViewPager这个小demo实现的是可以左右循环滑动图片,下面带索引,滑到最后一页在往右滑动就要第一页,第一页往左滑动就到最后一页,上面是效果图,用美女图片是我一贯的作风,呵呵  1.    首先看一些layout下的xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=&qu

  • Unity3D UGUI实现缩放循环拖动卡牌展示效果

    本文实例为大家分享了Unity3D UGUI实现缩放循环拖动卡牌展示的具体代码,供大家参考,具体内容如下 需求:游戏中展示卡牌这种效果也是蛮酷炫并且使用的一种常见效果,下面我们就来实现以下这个效果是如何实现. 思考:第一看看到这个效果,我们首先会想到UGUI里面的ScrollRect,当然也可以用ScrollRect来实现缩短ContentSize的width来自动实现重叠效果,然后中间左右的卡牌通过计算来显示缩放,这里我并没有用这种思路来实现,我提供另外一种思路,就是自己去计算当前每个卡牌的位

  • JS实现六边形3D拖拽翻转效果的方法

    效果图 实例代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv=&q

  • Unity实现游戏卡牌滚动效果

    最近项目中的活动面板要做来回滚动卡牌预览效果,感觉自己来写的话,也能写,但是可能会比较耗时,看到Github上有开源的项目,于是就借用了,Github的资源地址,感谢作者的分享. 本篇博客旨在告诉大家如何利用这个插件. 插件的核心在于工程中的6个脚本,以下是六个脚本的源码: DragEnhanceView.cs using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.EventSys

  • Android利用ViewPager实现可滑动放大缩小画廊效果

    画廊在很多的App设计中都有,如下图所示: 该例子是我没事的时候写的一个小项目,具体源码地址请访问https://github.com/AlexSmille/YingMi. 该画廊类似封面的效果,滑到中间的图片会慢慢变大,离开的View会慢慢的缩小,同时可设置滑动监听和点击监听. 网上有很多例子都是通过Gallery实现的,而上例的实现是通过ViewPager实现,解决了性能优化的问题,今天特此把它抽出来,封装一下,以便以后的方便使用.最终实现的效果如下: 使用方式 布局中添加该自定义控件 <R

  • Android利用CountDownTimer实现点击获取验证码倒计时效果

    本文实例为大家分享了Android点击获取验证码倒计时的具体代码,供大家参考,具体内容如下 package com.loaderman.countdowntimerdemo; import android.os.Bundle; import android.os.CountDownTimer; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TextV

随机推荐