引言
继Kotlin之下拉刷新与上拉加载控件之后,总感觉使用起来体验不是很好且没有增加footerView,这次统一在这里优化。
优化的方面有:增加滑动阻尼、增加footerView等
正文
FooterView
之前由于LinearLayout无法滑动显示出FooterView所以并没有处理,便暂时搁置了。在完成了与ViewPager完美结合的顺滑引导条系列后想到了scrollTo方法,可以通过手势将LinearLayout进行上移。
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
startY = ev.rawY
}
MotionEvent.ACTION_MOVE -> {
if (currentState != STATE_LOADING) {
val offset = startY - ev.rawY
if (offset > 0) {
changeState(STATE_DROP_UP)
footerView.setVisibleHeight(offset)
lastY = offset
return true
}
changeState(STATE_NORMAL)
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
lastY = 0f
if (currentState == STATE_DROP_UP) {
var toState = STATE_NORMAL
if (footerView.isEnought()) {
toState = STATE_LOADING
}
changeState(toState)
}
}
}
这里与HeaderView做了类似的处理,唯一不同的是滑动距离的正负值。由于屏幕坐标原点在左上角,向右向下为正向,下拉时event.rawY是逐渐增加的,所以上滑做了减数与被减数的换位。
至此与HeaderView思路一致,控制LinearLayout滑动的是在FooterView中加了回调,通知RefreshRecyclerView在其内部的FooterView高度变化了多少。
interface OnAttachViewHeightChangeListener {
fun onHeightChange(height: Int)
}
footerView.onAttachViewHeightChangeListener = object : AttachView.OnAttachViewHeightChangeListener {
override fun onHeightChange(height: Int) {
scrollTo(0, height)
}
}
AttachView
由于footerView和headerView有相同的方法,因此删除了之前的HeaderView和FooterView,所有统一继承于AttachView
/**
* Created by mr.lin on 2018/1/16.
* RefreshRecyclerView 的附加view
*/
abstract class AttachView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : FrameLayout(context, attrs, defStyleAttr) {
var viewHeight = CommonUtils.dpTopx(50f)
var onAttachViewHeightChangeListener: OnAttachViewHeightChangeListener? = null
abstract fun setVisibleHeight(height: Float)
abstract fun isEnought(): Boolean
abstract fun start()
abstract fun end()
abstract fun cancel()
interface OnAttachViewHeightChangeListener {
fun onHeightChange(height: Int)
}
}
阻尼
简单而言就是让手势的滑动有拉力的感觉,并不是拉一根线而是一根皮筋。
思路:正常的手势滑动 1 -> 5 ->20 ->50
增加阻尼的滑动 1 -> 2 ->5 ->20
数值往后越变大,与前面的差值变化越小,就会感觉明明使了100分的力度结果只走了50分的路程
实现的方法有:负指函数还有偷懒的缩放
负指数:
http://blog.csdn.net/ivan_zgj/article/details/50664780
缩放:
override fun setVisibleHeight(height: Float) {
var offset = height
if (offset > width) {
offset = width.toFloat()
}
val params = layoutParams
params.height = (offset * 0.4).toInt()//阻尼
layoutParams = params
}