前言

京东到家APP的引导页做的可圈可点,插画+动效,简明生动地说明了APP最吸引用户的几个亮点(商品多,价格低,配送快...)。本文主要分析拆解这些动画效果,并完成一个高仿Demo,完整的Demo代码可在文章结尾获取。

先看一下京东到家APP引导页动画效果,如下:

功能分析

分析结果基于对APP进行反编译和我个人的理解(不然还能怎么办呢?我太难了,哈哈哈)

  • 浅浅的背景图+四个引导页面,每一个页面动画播放完成后自动滑动到下一个页面。实现:用ViewPager+4个View实现,每一个页面对应一个View,一个View包含一个LottieAnimationView,在页面中监听Lottie动画的播放,播放完成后自动切换到下一个页面,ViewPager使用的是Alibaba开源的UltraViewPager
背景图片 引导图1 引导图2 引导图3 引导图4
  • 页面滑动切换时有一个旋转动画效果,可自定义ViewPager中的PageTransformer接口实现此效果,Title有透明度渐变效果,用属性动画ObjectAnimator实现

  • 当滑动到最后一个页面时,出现一个带有“立即体验”文本的按钮,出现时从底部向上弹出并且透明度从0到1变化,当从最后一个页面向前滑动时,按钮从底部消失并且透明度从1到0变化,即位移+透明度变化动画,使用属性动画ObjectAnimator可以实现此效果

布局分析

使用uiautomatorviewer查看layout布局文件,如下所示:

  • 根布局为ConstraintLayout,子节点为ViewPager,xml文件如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white"> <com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" /> <com.tmall.ultraviewpager.UltraViewPager
android:id="@+id/viewpager"
android:layout_width="0.0dip"
android:layout_height="0.0dip"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> <com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> <ImageView
android:id="@+id/ivJump"
android:layout_width="46.0dip"
android:layout_height="0.0dip"
android:layout_marginRight="20.0dip"
android:background="@drawable/pdj_guide_jump"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="63:28.5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.07" /> <ImageView
android:id="@+id/iv_start"
android:layout_width="104.29999dip"
android:layout_height="30.669983dip"
android:background="@drawable/pdj_guide_button"
android:focusable="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/> </androidx.constraintlayout.widget.ConstraintLayout>
  • 引导页总共有四个页面,每一个页面中LottieAnimationView对应一个Lottie文件,xml文件如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"> <com.airbnb.lottie.LottieAnimationView
android:id="@+id/pdj_guide_lottie_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

资源分析

  • 资源文件放在了src/main/assets目录下,配置文件为LottieConfig.json,如下:
{
"radius": 2020,
"totalPageNum": 4,
"lottieBgName": "guide_lottie_bg",
"pageAnimTime": 350,
"buttonAnimTime": 350,
"lottieTitle": [
{
"lottieName": "title_lottie_0"
},
{
"lottieName": "title_lottie_1"
},
{
"lottieName": "title_lottie_2"
},
{
"lottieName": "title_lottie_3"
}
],
"lottieMain": [
{
"lottieName": "main_lottie_0"
},
{
"lottieName": "main_lottie_1"
},
{
"lottieName": "main_lottie_2"
},
{
"lottieName": "main_lottie_3",
"repeatInterval": {
"start": 0.288,
"end": 1
}
}
]
}
  • radius --定义PageTransformer时会用到,用于确定最大旋转角度
  • totalPageNum --引导页的数量
  • lottieBgName --背景图片对应的Lottie文件名
  • pageAnimTime --ViewPager各个页面之间切换的滑动时间
  • buttonAnimTime --最后一个页面"立即体验"按钮做位移和透明度动画的时长
  • lottieTitle --每个引导页标题对应的Lottie文件名
  • lottieMain -- 每个引导页内容对应的Lottie文件名

代码实现

基于以上分析,用代码实现就比较简单了,此处贴出部分实现代码

  • 加载本地Lottie zip文件,Lottie支持加载本地和远程json,zip文件,通常我们将Lottie文件放在src/main/assets目录下
 fun loadAssetsLottieZipFile(context: Context, lottieImageView:LottieAnimationView, fileName:String,repeatCount:Int= LottieDrawable.INFINITE,autoPlay:Boolean=true){
val lottieCompose= if(fileName.endsWith(".zip")){
LottieCompositionFactory.fromAssetSync(context, fileName).value
}
else{
LottieCompositionFactory.fromAssetSync(context, fileName.plus(".zip")).value
}
lottieImageView.progress=0.0f
lottieImageView.repeatCount=repeatCount
lottieImageView.setComposition(lottieCompose!!)
if(autoPlay){
lottieImageView.playAnimation()
} }
  • 添加圆点指示符
        viewpager.initIndicator()
viewpager.indicator.setOrientation(UltraViewPager.Orientation.HORIZONTAL)
.setNormalIcon(drawableToBitmap(ContextCompat.getDrawable(applicationContext, R.drawable.guide_white_dot)!!))
.setFocusIcon(drawableToBitmap(ContextCompat.getDrawable(applicationContext, R.drawable.guide_dark_dot)!!))
.setIndicatorPadding(ScreenHelper.dp2px(applicationContext, 5.0F))
.setMargin(0, 0, 0, ScreenHelper.dp2px(applicationContext, 20.0F))
viewpager.indicator.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)
viewpager.indicator.build()

其中drawableToBitmap对应的代码为:

    /**
* Drawable转换成Bitmap
*/
private fun drawableToBitmap(drawable: Drawable): Bitmap {
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
drawable.draw(canvas)
return bitmap
}
  • 自定义PageTransformer实现页面切换旋转效果

    • position < -1 时,旋转到最大角度,旋转中心为右下角;
    • -1 < position < 0 时,position 越靠近 0 ,旋转角度越小,旋转中心向下边缘中心靠拢;
    • 0 <= position <= 1 时,position 越靠近 0 ,旋转角度越小,旋转中心向下边缘中心靠拢;
    • position > 1 时,旋转到最大角度,旋转中心为左下角。

代码如下所示:

import android.content.Context
import android.view.View
import androidx.viewpager.widget.ViewPager
import com.kongpf.commonhelper.ScreenHelper
import kotlin.math.atan2 class GuideTransformer(context: Context, private val mRadius: Int) : ViewPager.PageTransformer {
private var mMaxRotate = 0f init {
if (mRadius > 0) {
mMaxRotate = (2.0 * Math.toDegrees(atan2((ScreenHelper.getScreenWidth(context) / 2).toDouble(), mRadius.toDouble()))).toFloat()
}
} override fun transformPage(page: View, position: Float) {
if (mRadius == 0) {
return
} when {
position < -1.0f -> {
page.rotation = -1.0f * mMaxRotate
page.pivotX = page.width.toFloat()
page.pivotY = page.height.toFloat()
}
position <= 1.0f -> {
if (position < 0.0f) {
page.pivotX = page.width * (0.5f + 0.5f * -position)
page.pivotY = page.height.toFloat()
page.rotation = position * mMaxRotate
} else {
page.pivotX = 0.5f * page.width * (1.0f - position)
page.pivotY = page.height.toFloat()
page.rotation = position * mMaxRotate
}
}
else -> {
page.rotation = mMaxRotate
page.pivotX = 0f
page.pivotY = page.height.toFloat()
}
}
}
}

完整代码地址

https://github.com/kongpf8848/Animation

高仿京东到家APP引导页炫酷动画效果的更多相关文章

  1. Android高级控件(四)——VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷

    Android高级控件(四)--VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷 是不是感觉QQ空间什么的每次新版本更新那炫炫的引导页就特别的激动,哈哈,其实他实现起来真的很简单很 ...

  2. android仿网易云音乐引导页、仿书旗小说Flutter版、ViewPager切换、爆炸菜单、风扇叶片效果等源码

    Android精选源码 复现网易云音乐引导页效果 高仿书旗小说 Flutter版,支持iOS.Android Android Srt和Ass字幕解析器 Material Design ViewPage ...

  3. 浅谈android中只使用一个TextView实现高仿京东,淘宝各种倒计时

    今天给大家带来的是只使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.近期公司一直加班也没来得及时间去整理,今天难得歇息想把这个分享给大家.只求共同学习,以及自己兴许 ...

  4. iOS - GitHub干货分享(APP引导页的高度集成 - DHGuidePageHUD - ②)

    距上一篇博客"APP引导页的高度集成 - DHGuidePageHUD - ①"的发布有一段时间了, 后来又在SDK中补充了一些新的内容进去但是一直没来得及跟大家分享, 今天来跟大 ...

  5. iOS - GitHub干货分享(APP引导页的高度集成 - DHGuidePageHUD - ①)

    好长时间没更新博客, 是时候来一波干货分享了;APP引导页话不多说每一个APP都会用到,分量不重但是不可缺少,不论是APP的首次安装还是版本的更新,首先展现给用户眼前的也就只有它了吧,当然这里讲的不是 ...

  6. GitHub干货分享(APP引导页的高度集成 - DHGuidePageHUD)

    每一个APP都会用到APP引导页,分量不重但是不可缺少,不论是APP的首次安装还是版本的更新,首先展现给用户眼前的也就只有它了,当然这里讲的不是APP引导页的美化而是APP引导页的高度集成,一行代码搞 ...

  7. [Android实例] app引导页(背景图片切换加各个页面动画效果)(申明:来源于网络)

    [Android实例] app引导页(背景图片切换加各个页面动画效果)(申明:来源于网络) 地址: http://www.eoeandroid.com/thread-918356-1-1.html h ...

  8. 使用CoordinatorLayout打造各种炫酷的效果

    使用CoordinatorLayout打造各种炫酷的效果 自定义Behavior -- 仿知乎,FloatActionButton隐藏与展示 NestedScrolling 机制深入解析 一步步带你读 ...

  9. 15个来自 CodePen 的酷炫 CSS 动画效果【下篇】

    CodePen 是一个在线的前端代码编辑和展示网站,能够编写代码并即时预览效果.你在上面可以在线分享自己的 Web 作品,也可以欣赏到世界各地的优秀开发者在网页中实现的各种令人惊奇的效果. 今天这篇文 ...

随机推荐

  1. SCSS variable for loop All In One

    SCSS variable for loop All In One @each $r: red; $g: green; $b: blue; $colors: ( 1: $r, 2: $g, 3: $b ...

  2. React Hooks: useRef All In One

    React Hooks: useRef All In One useRef https://reactjs.org/docs/hooks-reference.html#useref refs xgqf ...

  3. TweenMax & GSAP & SVG Animation

    TweenMax & GSAP & SVG Animation svg animation https://greensock.com/tweenmax GSAP https://ww ...

  4. components & slot

    components & slot vue https://github.com/vuejs/rfcs/blob/master/active-rfcs/0001-new-slot-syntax ...

  5. 微信小程序 API

    微信小程序 API https://developers.weixin.qq.com/miniprogram/dev/component/cover-view.html demo https://de ...

  6. Chrome 80 & SameSite & cookie

    Chrome 80 & SameSite & cookie chrome://settings/help https://developers.google.com/web/updat ...

  7. html fragment & html template & virtual DOM & web components

    html fragment & html template & virtual DOM https://developer.mozilla.org/en-US/docs/Web/API ...

  8. 去中心化预言机如何助力NGK DeFi 项目发展?

    早在 2014 年前后,协议智能合约就已经出现了,最初协议很笨重,包含了许多不同的部分,每个部分都是一个单独的智能合约,你需要在区块链本身的协议中添加不同的智能合约,这需要几个月甚至几年的时间,而之后 ...

  9. 冷饭新炒:理解JWT的实现原理和基本使用

    前提 这是<冷饭新炒>系列的第五篇文章. 本文会翻炒一个用以产生访问令牌的开源标准JWT,介绍JWT的规范.底层实现原理.基本使用和应用场景. JWT规范 很可惜维基百科上没有搜索到JWT ...

  10. 死磕Spring之IoC篇 - BeanDefinition 的解析阶段(XML 文件)

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...