前言:准备实现一个刷新获取数据的功能,刷新的时候遇到了空白圈圈保留,于是开始查看SwipeRefreshLayout的源码并想了好几种方式去修复,最终采用反射
(第一次使用反射可能用的很糟糕,还请指点一下…)我的这个刷新比较明显,没有遮挡
(问题如下)
(已解决)
①:如果内嵌套一个滑动控件,滑动时向上滑动(停止滑动的操作)会保留一个白色的圈圈
即mCricleView (CircleImageView私有类)
可以发现但凡使用官方的SwiperRefreshLayout+内嵌套滑动控件就会导致此问题(比如
哔哩
哔哩)主界面滑动刷新如果突然停止并上滑一段距离,就会有白色圈圈保留,但是呢这个圈圈给TabLayout挡住了,只会有一层阴影是可以看的到(并不明显)
②:思路,获取mCircleView私有属性(但是CircleImageView作为私有类)即使获取也没法
强转
。
③换个思路,通过反射获取进度条缩放动画的函数以及参数(动画事件)并且拦截触摸事件
在松手时调用动画强制取消,并且还得判断进度条旋转的数值是否到达临界值。
package com.crow.laser.view.component import android.content.Context import android.util.AttributeSet import android.view.MotionEvent import android.view.animation.Animation.AnimationListener import androidx.swiperefreshlayout.widget.CircularProgressDrawable import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import java.lang.reflect.Method /************************* * @Machine: RedmiBook Pro 15 Win11 * @Path: app/src/main/java/com/crow/laser/view/customviews * @Time: 2022/11/20 20:02 * @Author: Crow * @Description: CustomSwiper 使用时全部反射属性仅作一次延迟初始化,减少在启动时的开销 * @formatter:off **************************/ class CustomSwipeRefresh : SwipeRefreshLayout { constructor(context: Context) : super(context) constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) // 通过反射获取父类 private val superClazz by lazy { javaClass.superclass } // 反射获取父类进度条 private val mProgress: CircularProgressDrawable by lazy { superClazz.getDeclaredField("mProgress").apply { isAccessible = true }.get(this) as CircularProgressDrawable } // 反射获取ScaleDownMethod private val mScaleDownFunc: Method by lazy { superClazz.getDeclaredMethod("startScaleDownAnimation", AnimationListener::class.java).apply { isAccessible = true } } // 反射获取动画监听 private val mRefreshListener: AnimationListener by lazy { superClazz.getDeclaredField("mRefreshListener").apply { isAccessible = true }.get(this) as AnimationListener } // -0.125f是进度条拖动到顶部的一个临界值 经过调试打印得到的。 override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { if ((ev?.action == MotionEvent.ACTION_UP) and (mProgress.progressRotation == -0.125f)) { mScaleDownFunc.invoke(this, mRefreshListener) } return super.dispatchTouchEvent(ev) } }
转载可以,麻烦附上原链接..谢谢。