gpt4 book ai didi

android - AppBar 不使用嵌套的 ViewPager2 滚动

转载 作者:行者123 更新时间:2023-12-05 00:18:27 25 4
gpt4 key购买 nike

我有一个 View 层次结构,如下图所示。
View hierarchy
我得到了奇怪的滚动行为,例如,

  • 如果我从区域 1 滚动(缓慢拖动或甩动)AppBar随之崩塌。这可以。
  • 但如果我从区域 2 慢慢拖出 AppBar不崩溃。它留在那里,RecyclerView在它下面。但是,它可以很好地处理。
  • activity_challenge_detail.xml
    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:id="@+id/swipeRefresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".challengedetail.ChallengeDetailActivity">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
    android:id="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black">

    <com.google.android.material.appbar.CollapsingToolbarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:contentScrim="@color/black"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_scrollFlags="scroll|exitUntilCollapsed">

    <androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/header"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_collapseMode="parallax"
    app:layout_collapseParallaxMultiplier="0.2">

    <FrameLayout
    android:id="@+id/challengeBannerFrame"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:foreground="@drawable/banner_gradient"
    app:layout_constraintDimensionRatio="H,1:1"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <ImageView
    android:id="@+id/challengeBanner"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:contentDescription="@string/challenge_banner"
    android:scaleType="centerCrop"
    tools:src="@tools:sample/avatars" />
    </FrameLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.appcompat.widget.Toolbar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minHeight="@dimen/dp16"
    app:layout_collapseMode="pin">

    <com.company.widget.StatusBarSpacer
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
    </androidx.appcompat.widget.Toolbar>
    </com.google.android.material.appbar.CollapsingToolbarLayout>

    <androidx.appcompat.widget.Toolbar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    app:contentInsetEnd="0dp"
    app:contentInsetStart="0dp"
    app:layout_collapseMode="pin">

    <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent">

    <com.google.android.material.tabs.TabLayout
    android:id="@+id/switchingTabsBar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp0"
    android:background="@drawable/switching_tab_bg"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintDimensionRatio="4"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:tabBackground="@drawable/active_tab_selector"
    app:tabIconTint="@color/black"
    app:tabIndicator="@drawable/active_tab_indicator"
    app:tabIndicatorColor="@color/yellow_500"
    app:tabMode="fixed"
    app:tabRippleColor="@null" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.appcompat.widget.Toolbar>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager2.widget.ViewPager2
    android:id="@+id/challengeDetailsViewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    fragment_challenge_post.xml
    <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/gradient_challenge_post"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".challengedetail.fragment.ChallengePostFragment">
    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/challengePostRecyclerView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.0"
    tools:itemCount="1"
    tools:listitem="@layout/list_item_post" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    list_item_post.xml
    <com.google.android.material.card.MaterialCardView
    android:id="@+id/cardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardBackgroundColor="@color/white"
    app:cardCornerRadius="@dimen/dp16"
    app:cardElevation="@dimen/dp0"
    app:strokeColor="@color/gray_f5"
    app:strokeWidth="@dimen/dp1">

    <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="@dimen/dp16">

    <com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/userImageView"
    android:layout_width="@dimen/dp48"
    android:layout_height="@dimen/dp48"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:scaleType="centerCrop"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:shapeAppearanceOverlay="@style/ShapeAppearance.userProfileImage"
    tools:src="@tools:sample/avatars" />

    <TextView
    android:id="@+id/userNameText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:lineSpacingExtra="5sp"
    android:textAppearance="@style/Inter.Semi.16"
    app:layout_constraintStart_toEndOf="@+id/userImageView"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="@tools:sample/full_names" />

    <TextView
    android:id="@+id/timestampText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:lineSpacingExtra="7sp"
    android:textAppearance="@style/Inter.Regular.14"
    app:layout_constraintStart_toEndOf="@+id/userImageView"
    app:layout_constraintTop_toBottomOf="@+id/userNameText"
    tools:text="2 hrs ago" />

    <com.company.widget.NestedScrollableHost
    android:id="@+id/viewPagerHost"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/userImageView"
    tools:layout_constraintDimensionRatio="1:1">

    <androidx.viewpager2.widget.ViewPager2
    android:id="@+id/postImagesViewPager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
    </com.company.widget.NestedScrollableHost>
    </androidx.constraintlayout.widget.ConstraintLayout>
    </com.google.android.material.card.MaterialCardView>
    我已经尝试过其他问题的解决方案以及包装嵌套的 ViewPager2NestedScrollableHost类(class)。但它似乎没有用。有任何想法吗?

    最佳答案

    要解决此问题,您需要几个步骤:

  • 包裹外层ViewPager2NestedScrollView ,当然也可以将滚动行为传递给它:
    所以在 activity_challenge_detail.xml :
    <androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <androidx.viewpager2.widget.ViewPager2
    android:id="@+id/challengeDetailsViewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent />

    </androidx.core.widget.NestedScrollView>
  • 禁用内部RecyclerView的嵌套滚动两者的ViewPagers : 并且由于它不可访问,您可以使用 java 反射来实现 RecyclerView可通过 ViewPager2 中的字段定义访问类(class):
    Kotlin :
  •     fun ViewPager2.getRecyclerView(): RecyclerView? {
    try {
    val field = ViewPager2::class.java.getDeclaredField("mRecyclerView")
    field.isAccessible = true
    return field.get(this) as RecyclerView
    } catch (e: NoSuchFieldException) {
    e.printStackTrace()
    } catch (e: IllegalAccessException) {
    e.printStackTrace()
    }
    return null
    }

    val recyclerView = viewPager.getRecyclerView()
    recyclerView?.isNestedScrollingEnabled = false
    java
        public static RecyclerView getRecyclerView(ViewPager2 viewPager) {
    try {
    Field field = ViewPager2.class.getDeclaredField("mRecyclerView");
    field.setAccessible(true);
    return (RecyclerView) field.get(viewPager);
    } catch (NoSuchFieldException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    }
    return null;
    }

    RecyclerView recyclerView = getRecyclerView(viewPager);
    if (recyclerView != null)
    recyclerView.setNestedScrollingEnabled(false);
    预习:
  • 黑色区域是AppBarLayout
  • 灰色区域是ViewPager2
  • 紫色区域为ViewPager


  • 更新:
    感谢@Ankur Gupta 和@SimpleAndroid:
    There is a nice trick而不是反射来获得 RecyclerViewViewPager2 ,并相应地禁用嵌套滚动:
    viewPager.children.find { it is RecyclerView }?.let {
    (it as RecyclerView).isNestedScrollingEnabled = false
    }

    关于android - AppBar 不使用嵌套的 ViewPager2 滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67778630/

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