效果如下(gif1):

怎么做呢?文章有点长,看官请静下心来好好看看。碰到不懂的地方查查API。

Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和 Transformation。

Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放等等。

而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画的,而alpha值是用来做alpha动画的,

要实现3D旋转动画我们需要继承自Animation类来实现,我们需要重载getTransformation和applyTransformation,

在getTransformation中Animation会根据动画的属性来产生一系列的差值点,然后将这些差值点传给applyTransformation,

这个函数将根据这些点来生成不同的Transformation。下面是具体实现:

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;

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();

}

//生成Transformation

@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();

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);

}

}

其中包括了旋转的开始和结束角度,中心点、是否扭曲、和一个Camera,这里我们主要分析applyTransformation函数,

其中第一个参数就是通过getTransformation函数传递的差指点,然后我们根据这个差值通过线性差值算法计算出一个中间角度degrees,

Camera类是用来实现绕Y轴旋转后透视投影的,因此我们首先通过t.getMatrix()取得当前的矩阵,然后通过camera.translate来对

矩阵进行平移变换操作,camera.rotateY进行旋转。这样我们就可以很轻松的实现3D旋转效果了。

看过以上文章的会知道作者接下来是贴上了API上的代码,那个代码实现的是图片和listview的旋转。那如果我们想实现的是

文章开头处的两张图片旋转怎么做呢?首先列出布局文件:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

android:id="@+id/rl"

tools:context=".MainActivity" >

android:layout_width="50dp"

android:layout_height="50dp"

android:layout_marginLeft="103dp"

android:layout_marginTop="135dp"

android:id="@+id/fl" >

android:id="@+id/imageView1"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:scaleType="fitXY"

android:src="@drawable/contrary" />

先不要奇怪为什么要有一个看似无用的FrameLayout布局。我们先看看Activity的代码:

public class MainActivity extends Activity {

ImageView img;

ViewGroup mContainer;

private boolean which=false;//which用于区别当前图片的状态,为false表示点击前显示的是问号,为true表示是蔬菜

private static final int IMAGE1 = R.drawable.contrary;

private static final int IMAGE2 = R.drawable.fruit11;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

img=(ImageView)findViewById(R.id.imageView1);

mContainer = (ViewGroup) findViewById(R.id.fl);//找到FrameLayout

img.setClickable(true);

img.setFocusable(true);

img.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO 点击图片后的事件

if(!which)

{

applyRotation(0,0,-90);//左旋90度

}

else

{

applyRotation(0,0,90);//右旋90度

}

}});

}

/*

* 应用变换的方法,里面将会使用之前写好的Rotate3d类

*/

private void applyRotation(int position, float start, float end) {

// Find the center of the container

//获取FrameLayout的x、y值。这样图片在翻转的时候会以这个x、y值为中心翻转。

//这就是为什么我要用FrameLayout的原因。如果直接使用的是父容器RelativeLayout将会以RelativeLayout的中心为轴心

//翻转。由于我的图片不是处于RelativeLayout的中心,翻转时就会有差错.效果可以看看下面的图片。

//当然,有时候你就想要那样的效果。你也可以在自行调整centerX和centerY的值来达到你想要的效果

final float centerX = mContainer.getWidth() / 2.0f;

final float centerY = mContainer.getHeight() / 2.0f;

final Rotate3d rotation =

new Rotate3d(start, end, centerX, centerY, 310.0f, true);

rotation.setDuration(1000); //可设置翻转的时间,以ms为单位

rotation.setFillAfter(true);

rotation.setInterpolator(new AccelerateInterpolator());

rotation.setAnimationListener(new DisplayNextView());

mContainer.startAnimation(rotation); //开始翻转前90度

}

/*

* 这个类用于监听前90度翻转完成

*/

private final class DisplayNextView implements Animation.AnimationListener {

private DisplayNextView() {

}

public void onAnimationStart(Animation animation) {

}

public void onAnimationEnd(Animation animation) {

//前90度翻转完成后,根据图片的状态翻转剩下的90度

if(!which)

{

img.setImageResource(IMAGE2);

mContainer.post(new SwapViews(0));

}

else

{

img.setImageResource(IMAGE1);

mContainer.post(new SwapViews(1));

}

}

public void onAnimationRepeat(Animation animation) {

}

}

/**

* 这个类用于翻转剩下的90度

*/

private final class SwapViews implements Runnable {

private final int mdirection;

//我把API的例子改了,这里用一个方向变量来指明剩下的90度应该怎么翻转。

public SwapViews(int direction) {

mdirection=direction;

}

public void run() {

final float centerX = mContainer.getWidth() / 2.0f;

final float centerY = mContainer.getHeight() / 2.0f;

Rotate3d rotation;

if(mdirection==0)

{

rotation = new Rotate3d(90, 0, centerX, centerY, 310.0f, false);

which=true;//待翻转完成后,修改图片状态

}

else

{

rotation = new Rotate3d(-90, 0, centerX, centerY, 310.0f, false);

which=false;

}

rotation.setDuration(1000);

rotation.setFillAfter(true);

rotation.setInterpolator(new DecelerateInterpolator());

mContainer.startAnimation(rotation); //开始翻转余下的90度

}

}

}

是来废话一下整个执行过程吧:第一次点击后,由which变量,在点击事件里设置左旋90度,图片开始旋转。旋转到90度(已经看不到“问号”这张图片了)后,旋转结束进入监听处理函数onAnimationEnd。这个函数里又由which变量知道是第一次点击,所以余下的90度应当显示的是“蔬菜”这张图片了。设置好图片后使用线程类SwapViews进行接下来90度的旋转,并修改which变量,这样就完成了一次点击动作。依此类推……

代码中提到的如果以父容器RelativeLayout为中心的翻转效果如下(gif2):

我们再来关注一下角度问题。细心的朋友应该已经知道:applyRotation(0,0,-90);是完成左旋0到90度

rotation = new Rotate3d(90, 0, centerX, centerY, 310.0f, false);是完成左旋90度到180度,

而applyRotation(0,0,90);完成右旋0到90度 rotation = new Rotate3d(-90, 0, centerX, centerY, 310.0f, false);是完成90度到180度

那角度为什么要这么设置呢?为什么不是applyRotation(0,0,-90);rotation = new Rotate3d(-90, -180, centerX, centerY, 310.0f, false);

和applyRotation(0,0,90);rotation = new Rotate3d(90, 180, centerX, centerY, 310.0f, false);。好,我们来看看这么设置的效果你就会明白了(gif3):

关键在于角度是以顺时针规定的。好好想想吧,这一点只可意会,很难表达出来。也可以下载源码去自己试试。

好了,就说到这里,效果千千万,看你想怎么做了。欢迎指正!

android局部翻转动画,android实现图片翻转动画相关推荐

  1. android局部布局替换,Android 局部布局替换的实现方式

    最近再搞远程视频的功能,其中要实现加载视频.加载视频失败.加载成功的局部布局替换,查阅相关资料,找到一种投机取巧的方式. 首先分别写这三种效果的子布局,分别为 top_remotetreate.xml ...

  2. html翻转切换div效果,图片翻转效果

    图片翻转效果 * { margin: 0; padding: 0;} ul { list-style-type: none;} body { font: 14px "Microsoft Ya ...

  3. android+动画+锯齿,Android_rotate--animation 动画旋转两图片,消除动画锯齿现象 android 开发:动画旋转两图片 - 下载 - 搜珍网...

    Android+动画旋转两图/ Android+动画旋转两图/.classpath Android+动画旋转两图/.project Android+动画旋转两图/.settings/ Android+ ...

  4. android局部布局刷新,Android RecyclerView 局部刷新分析

    前情回顾 之前写的 PowerAdapter 和 SelectPowerAdapter 从创建到现在,已经两年多,期间发生了翻天覆地的变化.一开始,我把 SwipeRefreshLayout 和 Re ...

  5. android局部布局刷新,Android之RecyclerView的局部刷新

    局部更新方法 1.使用Diffutil进行数据的比较 [Android]详解7.0带来的新工具类:DiffUtil 1.1一个相对完整的例子 Android高性能列表:RecyclerView + D ...

  6. mr图像翻转的原因_CSS图片翻转例子

    /*entire container, keeps perspective*/ /** * [perspective: number|none;] * 属性定义 3D 元素距视图的距离,以像素计.该属 ...

  7. android局部布局替换,android – 子片段替换父片段根布局

    我有一个5个片段的viewpager,其中一个我希望通过按钮点击完全替换它.我也希望能够通过后退按钮隐藏子片段. 这里的片段布局: 当我尝试像这样替换contacts_layout时: ImportC ...

  8. android播放mp3旋转动画,Android进阶之仿抖音的音乐旋转效果

    原标题:Android进阶之仿抖音的音乐旋转效果 原文:https://myml666.github.io (源码下载见文末) 这次是实现一个仿抖音的音乐旋转自定义View,先看一下效果 效果图 实现 ...

  9. android局部翻转动画,android 围绕中心旋转动画

    本文主要介绍Android中如何使用rotate实现图片不停旋转的效果.Android 平台提供了两类动画,一类是 Tween 动画,即通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果 ...

最新文章

  1. linux快捷上传下载文件
  2. FPGA之道(40)HDL的语法结构
  3. linux设备驱动——andriod平台wlan驱动
  4. AWK命令进行字符串替换-图解两个例子(转)
  5. 又到一年“粽子节”,快来测测你包的粽子颜值几分
  6. 哪些SQL语句会引起全表扫描
  7. IDEA中单元测试使用Scanner控制台无法输入
  8. HDU1427 速算24点
  9. python怎么打开h5文件_h5文件python
  10. unity 编辑器模式下修改屏幕分辨率
  11. 下载安装linux RedHat
  12. C语言程序_更改文件名后缀
  13. 102分布式电商项目 - JVM调优(理论篇)
  14. 跳槽进阿里了,面试阿里P6也没那么难。
  15. 高洛峰2015年新版视频发布
  16. Tableau 读书笔记
  17. python爬虫+抖音分享链接=可直接下载视频链接
  18. HTML——携程旅游案例
  19. layer遮罩层 简单的遮罩层
  20. ios 判断应该用pop返回还是dismis返回

热门文章

  1. ORB—点局部特征原理
  2. 企业级微信小程序改名
  3. python实现64卦的转换
  4. android小屏手机,2019年,期待一款小屏手机
  5. macOS 关闭蓝牙发现
  6. 五步法搞定BI业务需求梳理
  7. parted给nvme ssd分区
  8. 数控车床纵向进给系统设计CAD图与说明书 伺服 课程设计
  9. 《速通机器学习》-第七章 集成学习
  10. 怎么用vue2实现上一题下一题的答题功能