Android工具栏顶出转场动画的实现方法实例

前言

ndroid5.0之后新增了很多好看的转场动画,相比于以前的overridePendingTransition()丰富了很多,特别新增了共享元素跳转的方式。本文将给大家详细介绍关于Android工具栏顶出转场动画实现的相关资料,下面话不多说了,来一起看看详细的介绍吧

实现效果

为何做这个动画

起初对于这两个界面的转场动画打算简单使用android原生的共享元素动画,可是实现后发现效果并不是很好,在很多手机上流畅度太差。

以下在叙述时把转场前的页面称为A页面, 转场的目前页面称为B页面

实现原理

在A页面,把需要顶出的区域截取出来

val contentView = (context as Activity).window.decorView.findViewById<View>(android.R.id.content) ?: return null
var captureImage: Bitmap? = null
contentView.isDrawingCacheEnabled = true
captureImageFromView(contentView)
contentView.destroyDrawingCache()

在B页面,把A页面截取的图片用ImageView展示在顶部,并做上移动画。同时,取消按钮做出现的动画。
ImageView的上移动画非常简单:通过不断改变topMarigin来实现上移效果

 val captureImageUpAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
 addUpdateListener {
  val newTopMargin = captureImageStartLocationY * (animatedValue as Float)
  (captureView.layoutParams as LinearLayout.LayoutParams)?.apply {
   topMargin = -(newTopMargin.toInt())
  }
 }
}
val captureImageDownAnimator = ValueAnimator.ofFloat(1f, 0f).apply {
 addUpdateListener {
  val newTopMargin = captureImageStartLocationY * (animatedValue as Float)
  (captureView.layoutParams as LinearLayout.LayoutParams)?.apply {
   topMargin = -(newTopMargin.toInt())
  }
 }
}

取消按钮的出现动画,则是通过取消按钮左侧的框不断变小来实现的。

val rightBtnShowAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
 addUpdateListener {
  val animateWidth = (it.animatedValue as Float) * RIGHT_BTN_WIDTH
  flexingView.layoutParams = LinearLayout.LayoutParams(containerWidth - animateWidth.toInt(), UIUtil.dp2px(30f))
 }
}

下图大概描述了整个动画时如何实现的:

动画实现需要注意的点

页面A保存的截图如何传到B页面?

1、截图应该放到内存还是本地?

这个截图应该放在内存中,如果截图保存到本地。那么 I/O 占用的时间肯定会导致动画实现效果不好。

2、对于截取的图片需要压缩

对于不同分辨率的手机,截取出的图片的大小是不一样的。图片太大放在内存中是不合适的,因此在截取图片后对图片的大小做了压缩。

private fun captureFromView(view: View): Bitmap? {
 return translateToRgb555(view.drawingCache)
}

//为了压缩大小,同时保证图片宽高不变,直接将图片转成 RGB_565。
private fun translateToRgb555(srcBitmap: Bitmap): Bitmap? {
 try {
  /*传入bitmap参数,返回bitmap。*/
  val dataByte = ByteArrayOutputStream()
  srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, dataByte)
  val opts = BitmapFactory.Options()
  opts.inPreferredConfig = Bitmap.Config.RGB_565
  return BitmapFactory.decodeByteArray(dataByte.toByteArray(), 0, dataByte.size(), opts)
 } catch (e: Exception) {
  e.printStackTrace()
 } catch (e: OutOfMemoryError) {
  e.printStackTrace()
 }
 return null
}

经过上面的处理,大部分手机截图大小在0.2MB左右

3、B界面如何获取截取的图片?

放在intent中传给B

这样是有问题的,虽然android官方说intent中可以传递小于1MB的图片,但是国内各anroid厂商对framework做了不同的定制,有可能你的图片0.3MB就会出现崩溃,即TransactionTooLargeException

放在Fresco的缓存中?

尝试将图片放入Fresco缓存中,不过Fresco提供的接口十分不友好,(大概就不是给框架外使用的:

CloseableReference<V> cache(K key, CloseableReference<V> value);

放在全局静态变量中

不过需要注意的是在页面finish时,将这个变量置null,以免占用内存

覆盖系统原生转场动画

如果对于默认转场动画不做处理的话,效果就不是我们想要的,因此要取消默认的转场动画

需要把B页面的Theme的动画相关属性置null就可以了

<style name="NullAnimation" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@null</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@null</item>
</style>

不过这样后,在一些手机,比如华为,还是会有默认的转场动画,为了保险起见,在startActivity是最好这样

 context.overridePendingTransition(0, 0)

页面闪烁的问题

在覆盖了系统原生动画后,大部分手机效果都还是ok的,不过在一些手机上会出现闪屏的问题,比如华为 Mate10。在网上参考一些大家的解决方法:

 <item name="android:windowIsTranslucent">true</item>

即设置B页面的背景为透明的。

不过问题到这里还没有结束

windowIsTranslucent引发的崩溃问题

在设置windowIsTranslucent属性后,在Mate10进行测试,发现页面启动就崩溃:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.linkedin.android.XXXX.XXXX/com.linkedin.android.XXXX.XXXX.activity.LoginActivity}:
java.lang.IllegalStateException: Only fullscreen activities can request orientation

最后google找到了原因,原来 Android 8.0某SDK要求,如果界面是锁死方向的,那么是不允许设置这个属性的,不然会引发崩溃, 如果想知道详细细节可以看一下这篇文章:https://www.jb51.net/article/146945.htm

怎么解决呢?

前有山后有虎,脑壳子疼,最后决定取消B页面的锁屏属性,并且页面旋转时页面不做变化。

 <activity
  android:name=".activity.BActivity"
  android:exported="false"
  android:configChanges="orientation|keyboardHidden|screenSize"
  android:theme="@style/AnimationTheme">

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Android实用的Toast工具类封装

    大家好,Toast这个提示框大家都晓得,显示一段时间后自动消失,不能获得焦点.但是在使用中有些问题: 1)需要弹出一个新的Toast时,上一个Toast还没有显示完 2)可能重复弹出相同的信息 3)Toast具体有哪些用法不是很熟悉,用到时导出去找 4)app退出去了,Toast还在弹 等等一系列问题 下面封装了一个工具类,帮助大家管理Toast,基本上可以满足常用的需求,如果还满足不了,那就自定义了,呵呵~ import android.content.Context; import andr

  • Android AES加密工具类分享

    1.AES加密工具类 java不支持PKCS7Padding,只支持PKCS5Padding.我们知道加密算法由算法+模式+填充组成,下一篇介绍iOS和Android通用的AES加密,本篇文章使用PKCS5Padding加密方式. package com.example.aesdemo; import java.io.UnsupportedEncodingException; import javax.crypto.Cipher; import javax.crypto.spec.SecretK

  • Android 数据存储之 FileInputStream 工具类及FileInputStream类的使用

    安卓的三种本地的典型数据存储方式 SharedPreferences 以文件格式保存在本地存储中 SQL数据库 这篇文章就是讲解一下如何使用 SharedPreferences 保存文件.主要解释什么都写在注释里面的. IDE : Android Studio 参考文章:http://www.jb51.net/article/74215.htm 絮叨一下:本来文件操作这一块上周就想把其弄懂,然后继续进一步的学习.但是因为官方的 Android Training 之中的概念太过于繁杂.导致我认为存

  • android实用工具类分享(获取内存/检查网络/屏幕高度/手机分辨率)

    复制代码 代码如下: public class CommonUtil { public static boolean hasSDCard() { String status = Environment.getExternalStorageState();  return status.equals(Environment.MEDIA_MOUNTED); } /**  * 获取最大内存  *   * @return  */ public static long getMaxMemory() { r

  • android开发教程之实现toast工具类

    Android中不用再每次都写烦人的Toast了,直接调用这个封装好的类,就可以使用了! 复制代码 代码如下: package com.zhanggeng.contact.tools; /** * Toasttool can make you  use Toast more easy ;  *  * @author ZHANGGeng * @version v1.0.1 * @since JDK5.0 * */import android.content.Context;import andro

  • Android封装的http请求实用工具类

    复制代码 代码如下: import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.URLEncoder;import java.security.KeyStore;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Map.Entry; import org.apache.http

  • Android动画工具类的封装实战记录

    起因 最近在做一个组件化框架的封装,现在开发到一些常用工具类的封装了,突然意识到好像还没有做动画的工具类,于是开始着手开发之. 思路 既然要做动画,肯定是要做属性动画的工具类的封装了,由于补间动画和逐帧动画并不能改变目标动画主题的实际属性,在Android的开发中已经越来越少人去用这两个动画框架做开发了,而属性动画则相对的越来越广泛的使用在开发过程中了,于是这次的工具类的封装,只针对属性动画来封装. 属性动画对应的类叫做ObjectAnimator,主要就是用这个类来实现动画的一些基础设置,其具

  • android自动工具类TextUtils使用详解

    今天,简单讲讲如何使用android自动的工具类TextUtils. 简单列举部分用法: Log.d(TAG, "---------------------------------"); //字符串拼接 Log.d(TAG, TextUtils.concat("Hello", " ", "world!").toString()); //判断是否为空字符串 Log.d(TAG, TextUtils.isEmpty("H

  • Android开发中日期工具类DateUtil完整实例

    本文实例讲述了Android开发中日期工具类DateUtil.分享给大家供大家参考,具体如下: /** * 日期操作工具类. * @Project ERPForAndroid * @Package com.ymerp.android.tools * @author chenlin * @version 1.0 */ @SuppressLint("SimpleDateFormat") public class DateUtil { private static final String

  • Android工具栏顶出转场动画的实现方法实例

    前言 ndroid5.0之后新增了很多好看的转场动画,相比于以前的overridePendingTransition()丰富了很多,特别新增了共享元素跳转的方式.本文将给大家详细介绍关于Android工具栏顶出转场动画实现的相关资料,下面话不多说了,来一起看看详细的介绍吧 实现效果 为何做这个动画 起初对于这两个界面的转场动画打算简单使用android原生的共享元素动画,可是实现后发现效果并不是很好,在很多手机上流畅度太差. 以下在叙述时把转场前的页面称为A页面, 转场的目前页面称为B页面 实现

  • Android编程实现ImageView图片抛物线动画效果的方法

    本文实例讲述了Android编程实现ImageView图片抛物线动画效果的方法.分享给大家供大家参考,具体如下: 想实现抛物线动画,必须知道抛物线的方程,这时候数学其作用了,假如有如图的抛物线: 按照抛物线的方程特别,知道任何的三点可以确定一条抛物线,由已知抛物线的标注 方程为 y = ax² + bx + c:假设A1坐标为(0,0),A2坐标为(300,0),A3坐标为(150,300):联合解方程得知该抛物线的方程为 y = -1/75 x² + 4x:由此方程,我们可以确定抛物线x和y的

  • Android编程ProgressBar自定义样式之动画模式实现方法

    本文实例讲述了Android编程ProgressBar自定义样式之动画模式实现方法.分享给大家供大家参考,具体如下: 忘记在哪里看到的那位仁兄写的,就是通过用动画效果来实现的,现在顺便也把他写出来,希望那位仁兄不要见怪. 效果: 和之前的一样,在布局文件中: <ProgressBar android:id="@+id/progressBar3" android:layout_width="wrap_content" android:layout_height=

  • Android实现Activity界面切换添加动画特效的方法

    本文以实例形式展示了Android实现Activity界面切换添加动画特效的方法,对于Android程序设计人员来说有很好的参考借鉴价值.具体方法如下: 了解Android程序设计的人应该知道,在Android 2.0之后有了overridePendingTransition(),其中里面两个参数,一个是前一个activity的退出,另一个activity的进入. 现看看下面这段示例代码: @Override public void onCreate(Bundle savedInstanceSt

  • Android编程之界面跳动提示动画效果实现方法

    本文实例讲述了Android编程之界面跳动提示动画效果实现方法.分享给大家供大家参考,具体如下: 上一个效果图: 先上布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" a

  • Android判断后台服务是否开启的两种方法实例详解

    Android判断后台服务是否开启的两种方法实例详解 最近项目用到后台上传,就开启了一个服务service. 但是刚开始用这种方法,有些机型不支持:酷派不支持.然后又换了第二种判断方法. // public boolean isServiceWork(Context mContext, String serviceName) { // boolean isWork = false; // ActivityManager myAM = (ActivityManager) mContext // .

  • Android 自定义标题栏 显示网页加载进度的方法实例

    这阵子在做Lephone的适配,测试组提交一个bug:标题栏的文字较长时没有显示完全,其实这并不能算个bug,并且这个问题在以前其他机器也没有出现,只是说在Lephone的这个平台上显示得不怎么美观,因为联想将原生的标题栏UI进行了修改.修改的过程中遇到了一个难题,系统自带的那个标题栏进度总能够到达100%后渐退,但是我每次最后到100%那一段显示不全,尝试了用线程程序死了卡主了不说,还是一样的效果,后来同事一句话提醒了我用动画.确实是这样我猜系统的也是这样实现的,等进度到达100%后,用动画改

  • android实现一键锁屏和一键卸载的方法实例

    前言 本文主要介绍了关于android实现一键锁屏和一键卸载的相关内容,分享出来供大家参考学习,这两个功能也是大家在开发中会遇到的两个需求,下面话不多说了,来一起看看详细的介绍吧. 一.设备管理器操作步骤 1.创建类DeviceAdminReceiver的子类 如:com.itheima62.lockscreen.DeviceAdminSample 2.在清单文件中配置广播接收者 <receiver android:name="com.itheima62.lockscreen.Device

  • Android Flutter实现页面切换转场动画效果

    目录 前言 Hero 动画过程 Hero 基础示例 总结 前言 写了一篇基础的性能优化的内容,继续我们的动画相关的介绍.今天的主角是英雄 —— Hero 组件.Hero 组件非常适合从列表.概览页切换到详情页转场动画场合.因为可以将两个页面的组件串起来动画,体验上会觉得整个操作的连贯性非常好.下面是我们这篇要做的一个效果. 屏幕录制2021-11-09 下午9.39.49.gif Hero 动画过程 Hero 本质是是在不同的路由页面做了一个中转层,然后通过动画完成过渡,下面用4张图是官方演示的

  • Android中转场动画的实现与兼容性处理

    前言 在 Android 5.0 之前,我们已经有了 overridePendingTransition() 方法来实现一些转场效果.然而,在 Android 5.0 以后,转场效果更加炫酷. 比如下面的动画: 一.Android L 中的转场动画 实现转场动画只需三步: 在 res/ 目录下创建 transition 文件夹,在该文件夹下定义界面转场动画和共享元素的动画. 在 res/value/style 文件中为每个 Activity 指定转场动画的 style ,并在 AndroidMa

随机推荐