Android过渡动画,发现掘金小秘密(1),android开发基础机构




<?xml version="1.0" encoding="utf-8"?>




`

  1. 构建多个Pair对象,并传递给makeSceneTransitionAnimation()函数,启动Activity

ivImage.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val imagePair=Pair<View,String>(ivImage,"activityTransform") val textPair=Pair<View,String>(ivImage,"textTransform") val bundle = ActivityOptions.makeSceneTransitionAnimation(this, imagePair,textPair).toBundle() startActivity(Intent(this, SecondActivity::class.java), bundle) } else { startActivity(Intent(this, SecondActivity::class.java)) } }

这里主要是通过将共享视图和transitionName属性的值包装到Pair对象,其他操作和一个共享元素的操作步骤并无区别。

「效果图:」

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

「深坑提醒」

有时从RecyclerView界面进入到详情页,由于详情页加载延迟,可能出现没有效果。例如ImageView从网络加载图片,可能A界面到B界面没效果,B回到A界面有效果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 解决步骤:

  1. setContentView后添加下面代码,延迟加载过渡动画。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { postponeEnterTransition() }

  1. 在共享元素视图加载完毕,或者图片加载完毕后调用下面代码,开始加载过渡动画。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { startPostponedEnterTransition() }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 例如我是在Glide加载完再调用:

Glide.with(mContext) .asBitmap() .load(value?.avatar ?: "") .listener(object : RequestListener<Bitmap> { override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { animatorCallback?.invoke()//回调开始加载过渡动画 return false } override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean { animatorCallback?.invoke()//回调开始加载过渡动画 return false } }) .apply(RequestOptions.circleCropTransform()) .placeholder(R.mipmap.ic_default) .error(R.mipmap.ic_default) .into(authorBinding!!.ivAvatar)

大家也可以考虑下面代码:

shareElement.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { shareElement!!.viewTreeObserver.removeOnPreDrawListener(this) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { animatorCallback?.invoke() } return true } })

二)、进入过渡与退出过渡动画

与共享元素相反的,就是Activity进入与退出过渡动画,两个Activity之间在没有共享的视图情况下进行动画切换。下面先看三种动画效果图:「爆炸式效果」「淡入淡出式效果」「滑动式效果」

  • 「爆炸式」:将视图移入场景中心或从中移出;
  • 「滑动式」:将视图从场景的其中一个边缘移入或移出;
  • 「爆炸式」:通过更改视图的不透明度,在场景中添加视图或从中移除视图;

第一个界面采用Fade淡入淡出效果,第二个界面采用了Explode爆炸效果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 前后两个界面都采用了Slide滑入滑出效果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 利用Android现有的过渡框架,实现起来是很简单的,步骤如下:

  1. ActivityonCreate()方法中调用 setContentView()前设置启用窗口过渡属性;

window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)

  1. 创建过渡效果对象SlideExplodeFade;

val slide=Slide() slide.slideEdge=Gravity.START slide.duration=300//效果时长,一般Activity切换时间很短,不建议设置过长

如果是Slide效果,可以设置slideEdge属性来指定滑动方向,默认是Gravity.BOTTOM

  1. 将过渡效果设置给window相关属性,设置;

//退出当前界面的过渡动画 window.exitTransition = slide //进入当前界面的过渡动画 window.enterTransition = slide //重新进入界面的过渡动画 window.reenterTransition = slide

  1. 调用第二个Activity界面,使用过渡效果。

startActivity( Intent(this, SecondActivity::class.java), ActivityOptions.makeSceneTransitionAnimation(this).toBundle())

那么ActivityOnCreate()方法看起来是这样子的。

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS) window.allowEnterTransitionOverlap=false Slide().apply { duration = 300 excludeTarget(android.R.id.statusBarBackground, true) excludeTarget(android.R.id.navigationBarBackground, true) }.also { window.exitTransition = it window.enterTransition = it window.reenterTransition = it } } setContentView(R.layout.activity_first) ivContent.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { startActivity( Intent(this, SecondActivity::class.java), ActivityOptions.makeSceneTransitionAnimation(this).toBundle() ) } } }

上面代码中调用 了excludeTarget()方法将状态栏和导航栏排除在过渡动画效果之外。否则会跟着一起起动画效果,不是很美观。

正常情况,退出与进入过渡动画会有一小段交叉的过程,而window.allowEnterTransitionOverlap=false就是禁止交叉,只有退出过渡动画结束后才会再显示进入过渡动画。

如果第二个Activityfinish掉后,回到第一个Activity界面也想有过渡效果,就不要手动调用finish(),可以调用finishAfterTransition ()方法。

三)、兼容Android 5.0前

如果Android 5.0前也想要有切换动画怎么办?

  1. res/anim文件夹下创建想要的效果:

<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="@android:integer/config_longAnimTime" />

  1. 在启动Activity后调用overridePendingTransition()方法。

val intent = Intent(this, TestActivity2::class.java) startActivity(intent) overridePendingTransition(R.anim.fade_in, R.anim.fade_out)

overridePendingTransition()方法第一个参数为下一个界面进入动画,第二个参数为当前界面退出动画。

到这里,Activity的切换使用过渡动画基本就结束了。有朋友可能会问,只有Activity切换才能应用过渡效果么?

二、布局变化过渡动画

在上一节要理解一个概念:场景。布局的显示与隐藏可以理解分别为一个场景,过渡动画就是解决场景切换带来的生硬视觉感受。Activity切换过渡动画指在两个Activity之间,而布局变化过渡动画,是指同个Activity之间View的变化过渡动画。

一)、手动创建Scene

手动创建场景的话,需要我们自己创建起始和结束场景,利用现有的过渡效果来达到两个场景的切换。默认情况下,当前界面就是起始场景。

  1. 创建起始场景和结束场景的xml布局。起始场景和结束场景需要有相同根元素,例如下面代码idflConatentFrameLayout布局。

<?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:orientation="vertical"> <TextView android:id="@+id/tvText" android:text="内容过渡动画" android:gravity="center" android:textSize="18sp" android:layout_width="match_parent" android:layout_height="50dp"/> <FrameLayout android:id="@+id/flContent" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp"> <include layout="@layout/layout_first_scene"/> </FrameLayout> </LinearLayout>

初始视图,第一个场景,布局layout_first_scene.xml

<?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:orientation="vertical"> <TextView android:id="@+id/tvFirst" android:textSize="18sp" android:layout_marginTop="100dp" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal|top" android:text="感谢大家阅读文章" /> </LinearLayout>

第二个场景,布局layout_second_scene.xml

<?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:orientation="vertical"> <TextView android:textSize="18sp" android:layout_marginTop="100dp" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal|top" android:text="我是新小梦\n欢迎大家点赞支持一下" /> </LinearLayout>

  1. 创建起始场景和结束场景。

val firstScene = Scene.getSceneForLayout(flContent, R.layout.layout_first_scene, this) val secondScene = Scene.getSceneForLayout(flContent, R.layout.layout_sencod_scene, this)

默认情况下,过渡动画应用整个场景,如果场景某个View不参加,可以通过过渡效果对象removeTarget()方法进行移除。

Slide(Gravity.TOP).removeTarget(tvNoJoin)

  1. 点击时,进行场景过渡。

tvText.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (isFirst) { TransitionManager.go(secondScene, Slide(Gravity.TOP)) }else{ TransitionManager.go(firstScene, Slide(Gravity.TOP)) } isFirst=!isFirst } }

TransitionManager.go()第一个参数表示结束场景,第二个参数表示当前场景退出时过渡效果,当前场景就是初始场景。

「效果图:」

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

二)、系统自动创建Scene

这种情况,我们调用TransitionManager.beginDelayedTransition(sceneRoot)函数时,系统会自动记录当前sceneRoot节点下所有要进行动画的视图作为起始节点,下一帧中再次记录sceneRoot子节点下所有 起始场景进行动画状态的视图作为结束场景。这种一般用来改变视图的属性,然后进行动画过渡,如View的宽高。

「栗子」

定义只有一个正方形的View,通过改变正方形的宽高为原来的2倍,来看看动画效果。

  1. activity_text.xml布局文件,定义idsceneRoot的根节点,也是场景的根节点。

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/sceneRoot" android:background="@color/colorPrimary"> <View android:id="@+id/vSquare" android:layout_width="100dp" android:layout_height="100dp" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:background="@color/white" /> </RelativeLayout>

  1. TestActivityOnCreate方法中调用下面代码,将正方形的宽高设置200dp。

vSquare.setOnClickListener { TransitionManager.beginDelayedTransition(sceneRoot) vSquare.layoutParams.apply { width = dp2px(200f, this@TestActivity) height = dp2px(200f, this@TestActivity) }.also { vSquare.layoutParams = it } }

「效果图:」

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三、过渡动画效果

上面的动画效果,都是采用系统内置的,那具体有哪些动画效果,或支持自定义么?

过渡效果类都继承自Transition类,Transition类持有场景切动画的相关信息,子类的主要作用是捕获属性值(例如起始值和结束值)和如何演奏动画。从这里也可以看出,过渡动画也是属性动画的一个扩展与应用。

一)、内置过渡动画

系统支持将任何扩展Visibility类的过渡作为进入或退出过渡,内置继承自Visibility的类有ExplodeSlideFade;支持共享元素过渡的有:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后,面试前该准备哪些资源复习?

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一下我面试期间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《Android开发七大模块核心知识笔记》

面试字节两轮后被完虐,字节面试官给你的技术面试指南,请查收

面试字节两轮后被完虐,字节面试官给你的技术面试指南,请查收

《960全网最全Android开发笔记》

面试字节两轮后被完虐,字节面试官给你的技术面试指南,请查收

《379页Android开发面试宝典》

历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

(img-3a7sek6k-1712442475046)]

《379页Android开发面试宝典》

历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值