解决RecycleView动画问题记录
ak
发表于
2022-07-09 13:43
1034
bug解决
1、正常效果
我给RecycleView的添加了动画,正常情况是这样的(天气详情列表):
当点击一个城市会去加载天气详情列表,这个时候会启动进入的动画 是里面的Item从左边按顺序进来的一个效果
2、Bug情况
当我在动画还没播放结束时点击另一个城市,新加载的动画就出问题了,并不能正常运行
获得天气详情数据后的代码:
private fun initObserver() {
mState.weathers.observe(viewLifecycleOwner) {
Log.d(TAG, "initObserver: ${it.msg}")
if (it.code == 0) {
binding.weatherAdapter?.submitList(it.data) //提交数据列表给适配器
binding.rvWeather.scheduleLayoutAnimation() //启动动画
binding.imageView.startAnimation(imgEnterAnimation)
} else {
Toast.makeText(context, it.msg, Toast.LENGTH_SHORT).show()
}
}
}
我尝试了很多种方法去解决它,都没有效果:
- 在启动动画之前
clearAnimation()
- 在启动动画之前对动画
cancel()
,reset()
- 监听动画的开始和结束
3、解决方法
用submitList
的重载方法
public void submitList(@Nullable List<T> list, @Nullable final Runnable commitCallback) {
mDiffer.submitList(list, commitCallback);
}
这里有一个提交的回调,在回调里面启动动画即可
private fun initObserver() {
mState.weathers.observe(viewLifecycleOwner) {
Log.d(TAG, "initObserver: ${it.msg}")
if (it.code == 0) {
binding.weatherAdapter?.submitList(it.data) {
binding.rvWeather.scheduleLayoutAnimation()
}
binding.imageView.startAnimation(imgEnterAnimation)
} else {
Toast.makeText(context, it.msg, Toast.LENGTH_SHORT).show()
}
}
}
造成的原因是因为 submitList
会对改变了数据的Item调用notifyItem
通知刷新,由于新旧数据的比较是在子线程进行的,所以主线程会执行我启动动画的代码,在动画启动过程中,我们还没看到效果,就收到了数据比较完成后的通知刷新notifyItem
,于是出现了这样的bug
动画的使用
1、在res/anim下新建一个xml,adapter_enter_translate_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <alpha-->
<!-- android:duration="800"-->
<!-- android:fromAlpha="0.3"-->
<!-- android:toAlpha="1" />-->
<!-- <scale-->
<!-- android:duration="800"-->
<!-- android:fromXScale="0.0"-->
<!-- android:fromYScale="0.0"-->
<!-- android:toXScale="1.0"-->
<!-- android:toYScale="1.0" />-->
<translate
android:duration="300"
android:fromXDelta="-100%"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="0" />
</set>
2、加载并设置动画
private fun initView() {
val animation = AnimationUtils.loadAnimation(requireContext(), R.anim.adapter_enter_translate_anim)
val animationController = LayoutAnimationController(animation, 0.1f) //delay ->item间播放的延迟,300 * 0.1 = 30 毫秒
animationController.order = LayoutAnimationController.ORDER_NORMAL //item播放的顺序
binding.rvWeather.layoutAnimation = animationController
}
3、启动动画
adapter.scheduleLayoutAnimation()