Android BottomSheetBehavior 只允许向上拖动

Android BottomSheetBehavior allow only drag up

我正在尝试构建一个 bottomSheetBehavior 以允许用户仅使用向下拖动手势关闭 bottomSheet。要打开它,他将单击一个按钮。

所以我弄清楚了他是如何通过这个 禁用拖动 up/down 的。

现在我只需要停用向上拖动手势?

这是我创建的行为:

class LockedBottomSheetBehavior<V : View>(context: Context, attrs: AttributeSet) :
    BottomSheetBehavior<V>(context, attrs) {

    companion object {
        fun <V : View> from(view: V): LockedBottomSheetBehavior<*> {
            val params = view.layoutParams as? CoordinatorLayout.LayoutParams
                ?: throw IllegalArgumentException("The view is not a child of CoordinatorLayout")
            return params.behavior as? LockedBottomSheetBehavior<*>
                ?: throw IllegalArgumentException(
                    "The view is not associated with BottomSheetBehavior")
        }
    }

    override fun onInterceptTouchEvent(
        parent: CoordinatorLayout,
        child: V, event: MotionEvent
    ) = false

    override fun onTouchEvent(
        parent: CoordinatorLayout,
        child: V,
        event: MotionEvent
    ) = false

    override fun onStartNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        directTargetChild: View,
        target: View,
        axes: Int,
        type: Int) = false

    override fun onNestedPreScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        dx: Int,
        dy: Int,
        consumed: IntArray,
        type: Int) {
    }

    override fun onStopNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        type: Int) {
    }

    override fun onNestedPreFling(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        velocityX: Float,
        velocityY: Float
    ) = false
}

所以我在 Behavior 中添加了一个 if 语句,以防止手势状态折叠。


override fun onInterceptTouchEvent(
    parent: CoordinatorLayout,
    child: V, event: MotionEvent
): Boolean {
    if (this.state == STATE_EXPANDED) {
        super.onInterceptTouchEvent(parent, child, event)
        return true
    } else {
        return false
    }
}

override fun onTouchEvent(
    parent: CoordinatorLayout,
    child: V,
    event: MotionEvent
): Boolean {
    if (this.state == STATE_EXPANDED) {
        super.onTouchEvent(parent, child, event)
        return true
    } else {
        return false
    }
}

override fun onStartNestedScroll(
    coordinatorLayout: CoordinatorLayout,
    child: V,
    directTargetChild: View,
    target: View,
    axes: Int,
    type: Int): Boolean {
    if (this.state == STATE_DRAGGING) {
        super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type)
        return true
    } else {
        return false
    }


}

override fun onNestedPreScroll(
    coordinatorLayout: CoordinatorLayout,
    child: V,
    target: View,
    dx: Int,
    dy: Int,
    consumed: IntArray,
    type: Int) {
    if (this.state == STATE_DRAGGING) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
    }
}

override fun onStopNestedScroll(
    coordinatorLayout: CoordinatorLayout,
    child: V,
    target: View,
    type: Int) {
    if (this.state == STATE_DRAGGING || this.state == STATE_EXPANDED) {
        super.onStopNestedScroll(coordinatorLayout, child, target, type)
    }
}

override fun onNestedPreFling(
    coordinatorLayout: CoordinatorLayout,
    child: V,
    target: View,
    velocityX: Float,
    velocityY: Float
) = false

但它永远不会达到拖动手势。

按照

的回答

他添加了一个锁定的变量来知道我们是否应该激活拖动手势(在自定义行为中)。

class LockedBottomSheetBehavior<V : View>(context: Context, attrs: AttributeSet) :
    BottomSheetBehavior<V>(context, attrs) {

    private var mLocked = true

    fun setLocked(locked: Boolean) {
        mLocked = locked
    }

    override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
        var handled = false

        if (!mLocked) {
            handled = super.onInterceptTouchEvent(parent, child, event)
        }
        return handled
    }

    override fun onTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
        var handled = false

        if (!mLocked) {
            handled = super.onTouchEvent(parent, child, event)
        }
        return handled
    }

    override fun onStartNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        directTargetChild: View,
        target: View,
        axes: Int,
        type: Int) : Boolean {
        var handled = false

        if (!mLocked) {
            handled = super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type)
        }
        return handled
    }

    override fun  onNestedPreScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        dx: Int,
        dy: Int,
        consumed: IntArray,
        type: Int) {
        if (!mLocked) {
            super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
        }
    }

    override fun onStopNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        type: Int) {
        if (!mLocked) {
            super.onStopNestedScroll(coordinatorLayout, child, target, type)
        }
    }

    override fun onNestedPreFling(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        var handled = false

        if (!mLocked) {
            handled = super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY)
        }
        return handled
    }

}

然后如果bottomSheet的状态改变了,我们激活或者不激活行为手势。

所以在我的例子中,我只想在 bottomSheet 为 STATE_EXPANDED 时激活手势,并在 STATE_COLLAPSED.

时停用它

所以这是我在 Kotlin 中的 bottomSheet 行为版本,允许用户仅将其向下拖动,并禁用向上拖动手势。

bottomSheetBehavior.setBottomSheetCallback(object: BottomSheetBehavior.BottomSheetCallback() {
    override fun onSlide(bottomSheet: View, slideOffset: Float) {
        Log.d("CAMERA ACTIVITY", "SLIDE, ${this@apply.state}")
    }

    override fun onStateChanged(bottomSheet: View, newState: Int) {
        if (newState == BottomSheetBehavior.STATE_EXPANDED) {
            Log.d("CAMERA ACTIVITY", "STATE CHANGED, ${this@apply.state}")
            (bottomSheetBehavior as LockedBottomSheetBehavior).setLocked(false)
        } else if (newState == BottomSheetBehavior.STATE_COLLAPSED){
            (bottomSheetBehavior as LockedBottomSheetBehavior).setLocked(true)
        }

    }
})