Android 中的动画有很多,除了在一个界面上使用帧动画、属性动画将一个或多个 View 进行动画处理以外,还可以用于两个界面之间过渡、跳转。在 Android 5.0 之前,我们已经有了 overridePendingTransition() 方法来实现一些转场效果。然而,在 Android 5.0 以后,转场效果更加炫酷。 比如下面的动画:

本篇文章,主要就是解说如何实现上述的效果。主要内容包括:Android 5.0+ 的转场动画

Android 4.X 模拟实现 Android 5.0+ 转场效果。

Android 5.0+ 中的转场动画

实现转场动画只需三步:在 res/ 目录下创建 transition 文件夹,在该文件夹下定义界面转场动画和共享元素的动画。

在 res/value/style 文件中为每个 Activity 指定转场动画的 style ,并在 AndroidManifest.xml 文件中为每个 Activity 设置对应的 android:theme。

在 Activity 调用 startActivity() 切换动画前,使用 ActivityOptionsCompat 来创建转场动画时的共享对象。

下面就来对这三步进行详细讲解。

定义转场动画

在 res/ 目录下创建了 transition 资源文件夹后,就可以在该文件夹下对每一种动画进行定义。

一般来说,对 Activity 定义一个过渡动画可以写成下面的形式:

其中, 是动画效果的名称,Android 5.0(API 级别 21)支持这些进入与退出转换:分解(explode):从场景中心移入或移出视图。

滑动(slide):从场景边缘移入或移出视图。

淡入淡出(fade):通过调整透明度在场景中增添或移除视图。

而每一种动画效果,都有额外的属性。比如滑动 slide,可以使用 android:slideEdge="top" 设置滑动的方向;淡入淡出(fade)可以使用 android:fadingMode="fade_in" 设置具体是淡入(fade_in)还是淡出(fade_out)等。

标签里面定义需要转场(或者不需要转场)的目标 id ,这个 id 可以使系统自带的,也可以是我们自己视图中的 view 的 id,每一个 id 需要单独在  标签中定义,android:targetId 表示目标 ID 需要进行过渡转换的 view,而 android:excludeId 表示我们不需要该 ID 的 view 进行过渡转场。上面的那段代码的意思是说,除了状态栏和导航栏以外所有的 view,都执行 explode 动画。

如果我们想要在同一个过渡状态中实现两种或多种动画效果怎么办?也简单,将根标签替换为 ,然后定义每一种动画效果,最后记得在根标签中使用 android:transitionOrdering 注明这几种动画的演示顺序,sequential 表示顺序执行,而 together 表示同时执行。比如像下面的代码:

这段代码的意思就很简单了,该 xml 定义了两个过渡动画,并且同时执行。第一个动画是针对 id 为 cardView 的 view 进行滑动,第二个动画将除了状态栏、导航栏和 cardview 以外的 view,进行淡入淡出。

为每个 Activity 定义转场样式

这里的每一种动画,指的是在进行界面跳转过渡时,两个界面的状态。比如对于 Activity A 和 Activity B 这两个界面,可能的状态如下:界面 A 跳转至界面 B :这时界面 A 是 退出(exit )过渡状态,而对应的界面B是进入(enter)过渡状态。

界面 B 返回到界面 A :这时界面 A 是重新进入(reenter)过渡,而对应的界面B则是返回(return)过渡。

一般来说,所有的 Activity 过渡动画都可以定义成如下的形式:

true

@transition/explode

@transition/explode

@transition/change_image_transform

@transition/change_image_transform

当然,你可以不用写全,比如在我的 Demo 中一个界面的转场动画文件如下:

false

true

true

false

@transition/detail_enter

调用 ActivityOptionsCompat

转场动画是在两个界面的跳转返回时发生的,所以,当使用 intent 跳转界面时,需要调用 ActivityOptionsCompat来指定动画的运行。

一般来说,调用 ActivityOptionsCompat 的模板代码如下:// 创建一个包含过渡动画信息的 ActivityOptions 对象ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, view, getString(R.string.image_transition_name));// 使用 Intent 跳转界面,并传递共享对象信息Intent intent = new Intent(this, DetailActivity.class);

startActivity(intent, optionsCompat.toBundle());

ActivityOptionsCompat 是在support v4 包里面的,其实它是 ActivityOptions 的一个兼容(ActivityOptions是API 16引入的)。

然后,我们需要在第二个 Activity 中,将转场的图片获取并显示到界面中就可以了。

多个共享元素的过渡实现

有时候我们需要让多个元素产生动画效果,可以使用 Pair 来实现:ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));

手动实现一个转场动画

现在市面上,Android 5.0 以下的手机系统还有一定的市场份额,所以为了照顾这些用户,我们只能手动实现一下共享元素的转场动画效果。

实现的思路也比较简单,大概的步骤如下:确定第一个界面的共享元素,将其信息传递个第二个界面

第二个界面接收信息,开始的时候将界面设置为透明,并只显示共享元素。

将第二个界面的共享元素进行动画处理。

那么我们开始一步步实现上面的步骤。

获取共享元素位置信息

在第一个界面中,我们需要获取到共享元素的位置信息,并将其传递给下一个界面。于是乎,我们可以在第一个界面元素点击事件中,这么写:public void imageClick(View view) {

Intent intent = new Intent(AnimeActivity.this, AnimeDetailActivity.class);    // 创建一个 rect 对象来存储共享元素位置信息

Rect rect = new Rect();    // 获取元素位置信息

view.getGlobalVisibleRect(rect);    // 将位置信息附加到 intent 上

intent.setSourceBounds(rect);

CustomImage customImage = (CustomImage) view;

intent.putExtra(AnimeDetailActivity.EXTRA_IMAGE, customImage.getImageId());

startActivity(intent);    // 屏蔽 Activity 默认转场效果

overridePendingTransition(0, 0);

}

其中,getGlobalVisibleRect() 方法的含义是,获取 可见的状态栏高度+可见的标题栏高度+Rect左上角到标题栏底部的距离,如果标题栏被隐藏了,那么可见标题栏高度为0。

接下来,就在在第二个界面接收位置信息并将该图片展示出来了。

模拟转场动画

在第二个界面中,我们需要做如下的操作:获取上共享元素信息。

计算共享元素缩放比例和位移距离。

调用动画,完成模拟转场效果。

我将上面三个步骤的代码如下,你也可以下载我完整的 Demo 来查看。private void initial() {    // 获取上一个界面传入的信息

mRect = getIntent().getSourceBounds();

mRescourceId = getIntent().getExtras().getInt(EXTRA_IMAGE);    // 获取上一个界面中,图片的宽度和高度

mOriginWidth = mRect.right - mRect.left;

mOriginHeight = mRect.bottom - mRect.top;    // 设置 ImageView 的位置,使其和上一个界面中图片的位置重合

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mOriginWidth, mOriginHeight);

params.setMargins(mRect.left, mRect.top - getStatusBarHeight(), mRect.right, mRect.bottom);

mImageView.setLayoutParams(params);    // 设置 ImageView 的图片和缩放类型

mImageView.setImageResource(mRescourceId);

mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);    // 根据上一个界面传入的图片资源 ID,获取图片的 Bitmap 对象。

BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(mRescourceId);

Bitmap bitmap = bitmapDrawable.getBitmap();    // 计算图片缩放比例和位移距离

getBundleInfo(bitmap);    // 创建一个 Pallette 对象

mImagePalette = Palette.from(bitmap).generate();    // 使用 Palette 设置背景颜色

mContainer.setBackgroundColor(

mImagePalette.getVibrantColor(ContextCompat.getColor(this, android.R.color.black)));

}

在12行,通过设置 Margin 的形式来确定图片的位置,需要注意的是,由于状态栏是在父控件 FramLayout 之外的,因此我们要将 Rect.top 的值减去状态栏的高度,这样才是相对于屏幕的绝对位置。然后,getBundleInfo() 方法的代码如下:private void getBundleInfo(Bitmap bitmap) {    // 计算图片缩放比例,并存储在 bundle 中

if (bitmap.getWidth() >= bitmap.getHeight()) {

mScaleBundle.putFloat(SCALE_WIDTH, (float) mScreenWidth / mOriginWidth);

mScaleBundle.putFloat(SCALE_HEIGHT, (float) bitmap.getHeight() / mOriginHeight);

} else {

mScaleBundle.putFloat(SCALE_WIDTH, (float) bitmap.getWidth() / mOriginWidth);

mScaleBundle.putFloat(SCALE_HEIGHT, (float) mScreenHeight / mOriginHeight);

}    // 计算位移距离,并将数据存储到 bundle 中

mTransitionBundle.putFloat(TRANSITION_X, mScreenWidth / 2 - (mRect.left + (mRect.right - mRect.left) / 2));

mTransitionBundle.putFloat(TRANSITION_Y, mScreenHeight / 2 - (mRect.top + (mRect.bottom - mRect.top) / 2));

}

动画处理

最后我们需要使用动画来模拟转场效果,代码如下:private void runEnterAnim() {

mImageView.animate()

.setInterpolator(DEFAULT_INTERPOLATOR)

.setDuration(DURATION)

.scaleX(mScaleBundle.getFloat(SCALE_WIDTH))

.scaleY(mScaleBundle.getFloat(SCALE_HEIGHT))

.translationX(mTransitionBundle.getFloat(TRANSITION_X))

.translationY(mTransitionBundle.getFloat(TRANSITION_Y))

.start();

}

很简单,至此,入场动画效果基本模拟完毕。

而退场动画就更简单了,直接上代码:private void runExitAnim() {

mImageView.animate()

.setInterpolator(DEFAULT_INTERPOLATOR)

.setDuration(DURATION)

.scaleX(1)

.scaleY(1)

.translationX(0)

.translationY(0)

.withEndAction(new Runnable() {                  @Override

public void run() {

finish();

overridePendingTransition(0, 0);

}

})

.start();

}

当然,这只是简单的模拟,如果想要和 Android 5.0+ 的转场效果相同,还需要做很多的动画处理。

android 转场动画 监听,Android 中的转场动画及兼容处理相关推荐

  1. android u盘挂载监听,Android SD卡及U盘插拔状态监听及内容读取

    本篇是通过系统方法来对sd卡及U盘插拔监听及数据获取,Android盒子端开发,有系统权限,当然,这个比较简单,知道具体方法,可以通过反射来实现. 先贴上效果图: 获取外置存储设备并监听插拔状态 获取 ...

  2. android 帧动画监听,Android 动画(View动画,帧动画,属性动画)详细介绍

    0. 前言 Android动画是面试的时候经常被问到的话题.我们都知道Android动画分为三类:View动画.帧动画和属性动画. 先对这三种动画做一个概述: View动画是一种渐进式动画,通过图像的 ...

  3. android rxbus 一个页面监听,Android RxBus的使用

    RxBus的核心功能是基于Rxjava的,在RxJava中有个Subject类,它继承Observable类,同时实现了Observer接口,因此Subject可以同时担当订阅者和被订阅者的角色,这里 ...

  4. android 后台键盘按键监听,android键盘的监听

    android 键盘监听 从知乎上看到的一种解决方案,目前还没发现有什么坑. public class SoftKeyBroadManager implements ViewTreeObserver. ...

  5. android按钮怎么事件监听,android 通过监听edittext实现button的点击事件

    如果你没有接第三方的输入设备,那么点击按钮只需找到你的button然后:button.performClick(); 就可以了 那么如果你用到第三方输入法,有些时候监听就没有这么好使了: 以下场景为: ...

  6. 【微信小程序】 模拟帧动画图片 模拟音频播放gif动画 监听音频播放状态 css3 @keyframes 动画 背景图片设置

    没有播放时isPlaying为false,当点击时,开始播放,调用循环动画,再点击时,就停止. 图片 wxml 判断是否正在播放 通过 isPlaying 来判断. <!-- 音频 --> ...

  7. android定义两个监听,Android中的2个手指旋转手势监听器

    我试图找出使图像旋转的最佳方法,用户的手指向左或向右拖动,以及旋转角度. float x1 = lastEvent[0] - lastEvent[1]; float y1 = lastEvent[2] ...

  8. android 摇一摇监听,Android摇一摇功能实现(摇一摇监听)

    近期项目中要求增加摇一摇功能,搜了相关帖子,自己整理一套代码,发个博客保留一份. 解析:Android中摇一摇主要通过[SensorManager]实现,想了解可以查一下. 上期的不够完善 更新了一下 ...

  9. [Android]Fragment自定义动画、动画监听以及兼容性包使用

    Fragment是Android在API 11之后加入的一个组件,对提高Android开发中的布局合理性和布局效率都有很大作用,尤其是在Android平板等大屏幕设备的开发中,Fragment的引入能 ...

最新文章

  1. python三种基本控制结构_Python学习手册之控制结构(一)
  2. addeventlistener不支持ajax_十万个Web前端面试题之AJAX、axios、fetch的区别
  3. 今天学习啦所谓的高级语言啦
  4. 逻辑回归(Logistic Regression, LR)又称为逻辑回归分析,是分类和预测算法中的一种。通过历史数据的表现对未来结果发生的概率进行预测。例如,我们可以将购买的概率设置为因变量,将用户的
  5. KVC的底层实现原理
  6. class.forname找不到类_自媒体情感类文章素材怎么找?
  7. Java 算法 礼物分配
  8. python安装rarfile模块_python模块整理7-zipfile模块
  9. tcc-transation源码分析与思考
  10. 如何在Android文本视图周围添加边框?
  11. Nginx 作为Http代理服务器配置
  12. AllWinner--R329
  13. Android APK加密原理与演示
  14. 调试一个开源的车牌识别算法遇到的总结
  15. 2021技术人的百宝黑皮书
  16. Nginx服务优化与防盗链
  17. 【Unity入门计划】基本概念(8)-瓦片地图 TileMap 01
  18. SQL Server阻塞与锁
  19. iOS逆向-支付宝基金之统计实时收益
  20. python语言的优缺点论文_GAN 论文大汇总

热门文章

  1. 阿里国际站装修尺寸是多少1920像素模板阿里巴巴全屏代码装修教程优化美化店铺工具
  2. grep 或 egrep 或awk 过滤两个或多个关键词|使用grep匹配“与”或者“或”模式
  3. 杂项-Mac关闭系统更新提示(macOS10.15.2可用)
  4. JeeSite4 一些前端资料 - 来自作者ThinkGem
  5. 第一行代码:知晓当前是哪个界面
  6. zlib简单使用说明(转)
  7. GEC6818 移植 rtl8723bu wifi驱动
  8. TDM阅读笔记,在推荐系统的应用
  9. Gazebo载入模型问题汇总
  10. z370完美黑苹果_完工!搞掂i5-8600K 华硕PRIME Z370-P GTX 1060黑苹果安装