使用滑动手势的运动布局 + SwipeRefreshLayout + RecyclerView 错误的向上滚动行为。

问题描述 投票:0回答:1

我使用MotionLayout来构建2个部分的UI--顶部有一些视图,底部有SwipeRefresh和RecyclerView。我也为MotionLayout做了一个单一的手势--SwipeRefresh在向上滑动时移动到顶部视图的上方。问题是当我将RecyclerView滚动到底部(顶部视图 "折叠"),然后再滚动到顶部时,MotionLayout开始反转我的过渡("扩展")--当RecyclerView没有完全滚动到顶部时,而不是先滚动RecyclerView。当我的SwipeRefresh正在更新或刷新时,它的工作是应该的。禁用它会导致刷新布局进度条消失而没有动画 - 这不是一个好的解决方案。有什么变通的办法吗?

布局xml要点

布局场景要点

android android-layout android-recyclerview android-animation android-motionlayout
1个回答
2
投票

我也有同样的问题,在浏览MotionLayout的官方bug修复历史时,想到了一个解决办法。你必须覆盖 onNestedPreScroll 方法的MotionLayout这样。

/**
 * The current version of motionLayout (2.0.0-beta04) does not honor the position
 * of the RecyclerView, if it is wrapped in a SwipeRefreshLayout.
 * This is the case for the PullRequest screen: When scrolling back to top, the motionLayout transition
 * would be triggered immediately instead of only as soon as the RecyclerView scrolled back to top.
 *
 * This workaround checks if the SwipeRefresh layout can still scroll back up. If so, it does not trigger the motionLayout transition.
 */
class SwipeRefreshMotionLayout : MotionLayout {

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
        if (target !is SwipeRefreshLayout) {
            return super.onNestedPreScroll(target, dx, dy, consumed, type)
        }

        val recyclerView = target.getChildAt(0)
        if (recyclerView !is RecyclerView) {
            return super.onNestedPreScroll(target, dx, dy, consumed, type)
        }

        val canScrollVertically = recyclerView.canScrollVertically(-1)
        if (dy < 0 && canScrollVertically) {
            // don't start motionLayout transition
            return;
        }

        super.onNestedPreScroll(target, dx, dy, consumed, type)
    }
}

用这个MotionLayout结合SwipeRefreshLayout对我来说很好用。 我还贴了这个。此处如果你想跟踪谷歌的bug修复。


0
投票

由于缺乏声誉,我不能对@muetzenflo的回答发表评论,但我在我的MotionLayout中试图禁用动画时挣扎了几个小时。我将isInteractionEnabled设置为 "false",但没有成功。最后我意识到,我使用了自定义的MotionLayout,可能应该检查它。只有当我在MotionLayout中添加了

if (!isInteractionEnabled) {
    return
}

作为onNestedPreScroll()中的第一个检查,禁用动画工作的目的。

© www.soinside.com 2019 - 2024. All rights reserved.