Разрешить NestedScrollView полностью прокручивать внутри нижнего листа с пользовательским поведением

#android #android-coordinatorlayout #bottom-sheet #android-jetpack

#Android #android-coordinatorlayout #нижний лист #android-jetpack

Вопрос:

У меня есть нижний лист с дочерним NestedScrollView. Я хочу прокрутить весь NestedScrollView до самого низа, не сдвигая нижний лист вверх.

Если пользователь хочет, чтобы нижний лист поднимался полностью, он не должен использовать привязку никаким другим способом.

Теперь, когда я использую start прокрутку вниз, после прокрутки всего содержимого я хочу, чтобы нижний лист скрывался при следующем действии прокрутки.

Поскольку поведение нижней таблицы по умолчанию не допускает этого, я создал свое собственное пользовательское поведение и переопределил onNestedScroll () и onNestedPreScroll().

Есть две проблемы, с которыми я сталкиваюсь:

1: Nestedscrollview частично прокручивается и останавливается, потому что по отношению к нижнему листу он видит, что больше нет содержимого для прокрутки. Я должен сдвинуть лист вверх, чтобы увидеть остальное содержимое. Означает, что я не могу увидеть последний элемент внутри NestedScrollView, не разворачивая лист.

2: Как я могу определить, прокручивается ли NestedScrollChild вверх или вниз. Потому что я хочу, чтобы нижний лист перехватывал события, как только scrollview закончит прокручивать свое содержимое. Я попробовал onNestedPreScroll, но, похоже, это не обязательно срабатывает каждый раз, когда прокручивается дочерний элемент. Является ли подключение прослушивателя к scrollview единственным решением?

Ссылка, чтобы увидеть проблему в GIFhttps://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)
}
  

}

Я хочу, чтобы подобное поведение, если кто-то может помочь, действительно было бы оценено.

введите описание изображения здесь

Комментарии:

1. Вы нашли решение для этого?

2. У меня точно такая же проблема. Что вы сделали, чтобы это исправить?

3. Вы нашли решение для этого?

Ответ №1:

У меня была почти такая же проблема, хотя макет был немного другим, и поведение заключалось в том, чтобы вообще не перехватывать вложенную прокрутку. Поскольку ответа по-прежнему нет, я думаю, стоит поделиться своим опытом здесь.

Итак, мой макет был следующим:

 <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>
  

И в итоге я пришел к следующему подходу:

  1. Запретить BottomSheet принимать вложенную прокрутку:
 class FullNestedScrollBottomSheetBehavior<V: View>(
  context: Context,
  attrs: AttributeSet?
): BottomSheetBehavior<V>(context, attrs) {
  override fun onStartNestedScroll(...) = false
}
  
  1. Динамически изменять высоту родительского элемента вложенного элемента прокрутки (в моем случае это a, ViewPager который содержит NestedScrollView и RecyclerView ) в соответствии с реальной высотой BottomSheet видимой части:
 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
    }
  })
}
  
  1. Поскольку 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
}
  

Я думаю, что предоставленное решение может быть хорошим советом для реализации точного поведения, требуемого в вопросе.