抬头仰望星空,是否能发现自己的渺小。

伪斜杠青年

人们总是混淆了欲望和理想

NestedScrollView 仿照 H5 锚点实现

因为一些原因,需要在原生仿照一个 H5 的锚点效果,很不幸的是,在一个迭代后,效果又被砍掉了,不过实现还是记录下。

由于 tab 点击以及 pager 滑动的联动代码并不优雅,需要处理那些抖动问题,那些除了代码不美观倒不是什么难题,主要记录下 ScrollView 中 View 的查找以及根据 ID 的 View 定位,当然这些也都是网络上现成可以 Copy 到的。

fun NestedScrollView.findNearestView(ids: Array<Int>): Int {
    val parentLocation = IntArray(2)
    getLocationOnScreen(parentLocation)
    val parentY = parentLocation[1]
    var pos = 0
    for (index in ids.indices) {
        val viewId = ids[index]
        val moveToView = findViewById<View>(viewId)
        val viewLocation = IntArray(2)
        moveToView.getLocationOnScreen(viewLocation)
        val childY = viewLocation[1]
        if (parentY > childY) {
            pos = index
        } else {
            break
        }
    }
    return pos
}
fun NestedScrollView.scrollToView(viewId: Int, offset: Int) {
    val moveToView = findViewById<View>(viewId)
    moveToView ?: return
    val parentLocation = IntArray(2)
    getLocationOnScreen(parentLocation)
    val viewLocation = IntArray(2)
    moveToView.getLocationOnScreen(viewLocation)
    val moveViewY = viewLocation[1] - parentLocation[1]
    val needScrollY = (moveViewY - offset)
    if (moveViewY == 0) return
    smoothScrollBy(0, needScrollY)
}

然后嵌套在 CoordinatorLayout 与 AppBarLayout 中出现的头部无法滑动的问题,主要靠这个解决:

/**
 * 解决 AppBarLayout 底部滑动后 头部无法滑动问题
 */private fun updateAppBarStatus() {
    val params: CoordinatorLayout.LayoutParams =
        mBinding.appBarLayout.layoutParams as CoordinatorLayout.LayoutParams
    val behavior = params.behavior as AppBarLayout.Behavior
    behavior.setDragCallback(object : AppBarLayout.Behavior.DragCallback() {
        override fun canDrag(@NonNull appBarLayout: AppBarLayout): Boolean = true
    })
}

在滚动后调用一次 updateAppBarStatus 更新一下状态即可。

这些东西也显得相对原始,现在用的场合并不多了,随之而来的是更多的更为复杂的多状态协调以及元素共享页面,不过目前还没有遇到那种需求。

以上。

参考:https://github.com/taixiang/tabScroll


本站由以下主机服务商提供服务支持:

0条评论

发表评论