开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1天,点击查看活动详情
相信每个Android开发者都使用过loading加载框,甚至自己也会封装一个全局弹窗,用于网络请求来提高用户体验。网络上也有不少第三方库,这里记录一下本人自己封装和使用加载框遇到的问题。
1. 初期使用Dialog+ProgressBar或者Dialog+ImageView,其实都是通过xml动画使图片重复旋转达到效果。网络请求开始则显示Dialog,网络请求结束关闭Dialog,注意视图的回收。
class ProgresDialog(context: Context) : Dialog(context, R.style.dialog_progress) {
private var rotateAnimation: Animation? = null
private var lin: LinearInterpolator? = null
override fun show() {
super.show()
findViewById<View>(R.id.iv).startAnimation(rotateAnimation)
}
override fun dismiss() {
findViewById<View>(R.id.iv).clearAnimation()
super.dismiss()
}
init {
if (rotateAnimation == null) rotateAnimation =
AnimationUtils.loadAnimation(context, R.anim.rotate_anim)
if (lin == null) lin = LinearInterpolator()
rotateAnimation!!.interpolator = lin
setContentView(R.layout.dialog_porgress)
setCanceledOnTouchOutside(false)
}
}
布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_gravity="center"
android:layout_width="120dp"
android:layout_height="80dp"
android:background="@drawable/dialog_shape_bg"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:visibility="gone"
android:layout_marginTop="5dp"
android:layout_width="35dp"
android:layout_height="35dp"
android:indeterminate="true"
android:indeterminateBehavior="repeat"
android:indeterminateDrawable="@drawable/loading_ani" />
<ImageView
android:id="@+id/iv"
android:src="@mipmap/icon_loading"
android:layout_marginTop="5dp"
android:layout_width="35dp"
android:layout_height="35dp"/>
</LinearLayout>
</FrameLayout>
这里需要注意xml属性设置,结束角度为359°,否则动画不自然,其他属性根据自己想要的效果配置即可。
动画部分:
<rotate xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="359"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1800"
android:repeatCount="-1">
</rotate>
</rotate>
这种组装模式局限性很大,只能实现一些简单动画,毕竟是靠图片配合的补间动画。但往往现在的app都是定制的加载动画,所以第一种方式并不能满足我们的需求。下面介绍下后期使用的loading动画效果。
2.进阶版Dialog+LottieAnimation,可以轻松实现复杂动画,解放程序员的双手,是一大福利啊!当然动画素材还得靠美工或者自己寻找喜欢的素材(对美工要求比较高,能够制作导出动画的gson文件)。这里贴下自己用过的免费素材地址
布局几乎不变,将图片或者ProgressBar替换为视图LottieAnimationView即可,配置相当方便,具体使用方式参考Github示例
class ProgresDialog(context: Context) : Dialog(context, R.style.dialog_progress){
private var animationView: LottieAnimationView
override fun show() {
super.show()
animationView.playAnimation()
}
override fun dismiss() {
animationView.cancelAnimation()
super.dismiss()
}
init {
setContentView(R.layout.dialog_porgress)
animationView = findViewById(R.id.animation_view)
setCanceledOnTouchOutside(false)
}
}
布局:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<com.lihang.ShadowLayout
android:layout_gravity="center"
app:hl_cornerRadius="5dp"
app:hl_layoutBackground="#7C7B7B"
android:layout_width="130dp"
android:layout_height="wrap_content">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="130dp"
android:layout_height="120dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_speed="1"
app:lottie_fileName="loading.json" />
</com.lihang.ShadowLayout>
</LinearLayout>
替换为LottieAnimationView后使用起来的动画很是酷炫,相当完美(想象一下,如果没有它的出现,实现同样动画效果不得要程序员的老命啊)。担心网络json加载慢的可以像我一样将json直接放在本地,xml中直接引用即可。毕竟网络加载提示的地方几乎每个页面都有,这样也可减少资源消耗。
就在我美滋滋的在沸点摸鱼的时候,测试突然发消息过来说我的加载框翻车了......
What?加载框居然跑到屏幕左上角去了,也不是所有机型都会复现,就那么一款机型必现。查看布局也没任何问题,生命周期也没问题。也是试过了各种方案总会在那款机子上复现,最后终于发现是progresDialog.hide()的锅。只需要将它修改为dismiss()后便一切恢复正常。
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
//监听加载弹窗
viewModel.loadEvent.collectLatest{
if (it){
progresDialog.show()
}else{
progresDialog.hide()
}
}
}
}
查看hide源码发现只是做了一个隐藏操作,而dismiss相当于回收视图。至于为什么会出现在左上角也是不得而知,怀疑是父布局测量问题,有没有大神知道的帮小弟解惑呀?
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1天,点击查看活动详情