Kotlin之下拉重新整理與上拉載入控制元件優化
阿新 • • 發佈:2019-01-02
引言
繼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分的路程
實現的方法有:負指函式還有偷懶的縮放
負指數:
縮放:
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
}