gpt4 book ai didi

android - 允许 NestedScrollView 在具有自定义行为的 BottomSheet 内完全滚动

转载 作者:行者123 更新时间:2023-12-04 23:41:03 33 4
gpt4 key购买 nike

我有一个带有子 NestedScrollView 的 Bottom Sheet 。我想将整个 NestedScrollView 一直滚动到底部,而不要将 Bottom Sheet 向上滑动。

如果用户希望 Bottom Sheet 一直向上,他们必须使用 anchor ,别无他法。

现在,当使用开始向下滚动时,在滚动整个内容后,我希望 Bottom Sheet 在下一个滚动操作时隐藏。

由于默认的 Bottom Sheet 行为不允许我创建自己的自定义行为并覆盖 onNestedScroll() 和 onNestedPreScroll()。

我面临两个问题:

1 :Nestedscrollview 部分滚动并停止,因为相对于 Bottom Sheet ,它看到没有更多内容要滚动。我必须向上滑动表格才能看到其余内容。意味着如果不展开工作表,我看不到 NestedScrollView 中的最后一项。

2:如何检测 NestedScrollChild 是向上滚动还是向下滚动。因为我希望 BottomSheet 在 ScrollView 完成滚动其内容后拦截事件。我试过 onNestedPreScroll 但似乎每次滚动 child 时都不一定会触发它。将监听器附加到 ScrollView 是唯一的解决方案吗?

链接以查看 GIF 中的问题
https://photos.app.goo.gl/RPmDFEtR9TbGHrau6

下面是我的布局和行为类。

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
/>
</com.google.android.material.appbar.AppBarLayout>

-->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bottom_sheet_background_shaded"
android:elevation="10dp"
app:behavior_hideable="false"
app:behavior_peekHeight="35dp"
app:behavior_fitToContents="false"
app:layout_behavior="com.pyus13.bottomsheetsample.MyBottomSheetBehaviour">

<ImageView
android:id="@+id/anchor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="1dp"
android:src="@drawable/bottom_sheet_anchor_holder"
app:layout_constraintBottom_toTopOf="@+id/main_container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

<androidx.core.widget.NestedScrollView
android:id="@+id/main_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:clipToPadding="false"
android:elevation="5dp"
android:gravity="center"
android:paddingTop="20dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/anchor">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<Button
android:id="@+id/change_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Title 1"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Title 2"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Page 3"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Page 4"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Page 5"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Change Title"/>


</LinearLayout>

</androidx.core.widget.NestedScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

我的行为课:
class MyBottomSheetBehaviour<V : View> @JvmOverloads constructor(
context: Context? = null, attrs: AttributeSet? = null) : BottomSheetBehavior<V>(context, attrs) {

private var isScrollingDown = false


override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
if (state == STATE_COLLAPSED || state == STATE_HALF_EXPANDED) {
return false
}
return super.onInterceptTouchEvent(parent, child, event)
}

override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {
Log.d("Scroll", "OnNestedScroll EVent $child $target $axes $type")
if (state == STATE_COLLAPSED || state == STATE_HALF_EXPANDED) {
if (target.canScrollVertically(1) || target.canScrollVertically(-1)) {
return false
}
}
return super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type)
}

override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
isScrollingDown = dy > 0
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
}

}

如果有人可以提供帮助,我想要这样的行为,我将不胜感激。

enter image description here

最佳答案

不过,我遇到了几乎相同的问题,布局有点不同,而且行为是根本不拦截嵌套滚动。由于仍然没有答案,我认为值得在这里分享我的经验。
所以,我的布局如下:

<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<LinearLayout
android:id="@+id/bottomSheetLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:backgroundTint="@color/colorPrimary"
android:orientation="vertical"
app:layout_behavior=".view.FullNestedScrollBottomSheetBehavior"
app:behavior_hideable="false"
app:behavior_peekHeight="@dimen/bottom_sheet_min_height"
>

<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/anchorImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="-4dp"
android:layout_gravity="center"
android:paddingTop="4dp"
android:src="@drawable/ic_baseline"
android:tint="@android:color/white"
/>

<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabLayout"
app:tabTextColor="#b2ffffff"
app:tabIconTint="@color/selector_status_tab"
app:tabRippleColor="#42ffffff"
app:tabSelectedTextColor="@android:color/white"
app:tabIndicatorColor="@android:color/white"
>
...
</com.google.android.material.tabs.TabLayout>

<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
/>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
我最终采用了以下方法:
  • 禁止BottomSheet接受嵌套滚动:
  • class FullNestedScrollBottomSheetBehavior<V: View>(
    context: Context,
    attrs: AttributeSet?
    ): BottomSheetBehavior<V>(context, attrs) {
    override fun onStartNestedScroll(...) = false
    }
  • 根据 ViewPager 的实际高度动态更改嵌套滚动元素的父级高度(在我的情况下,它是 NestedScrollView ,其中包含 RecyclerViewBottomSheet )的可见部分:
  • override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
    override fun onStateChanged(bottomSheet: View, newState: Int) {}
    override fun onSlide(bottomSheet: View, slideOffset: Float) {
    val height = view.height - bottomSheet.top - anchorImage.height + 4.dp - tabLayout.height
    val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height)
    viewPager.layoutParams = params
    }
    })
    }
  • 由于onSlide()在您拖动 BottomSheet 之前不会调用, 上面的逻辑应该复制成 onViewCreated() :
  • override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    view.post {
    val h = view.height - bottomSheetLayout.top - anchorImage.height + 4.dp - tabLayout.height
    val p = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, h)
    viewPager.layoutParams = p
    }
    // here goes the code from the second point
    }
    我认为提供的解决方案可能是实现问题中所需的确切行为的一个很好的技巧。

    关于android - 允许 NestedScrollView 在具有自定义行为的 BottomSheet 内完全滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55409691/

    33 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com