![](/img/trans.png)
[英]RecyclerView inside ViewPager inside NestedScrollView - doesn't work well
[英]Android NestedScrollView doesn't work in layout with viewpager
當我在 viewPager 中滾動 recyclerView 時,我希望能夠滾動布局的上半部分(帶有名稱、圖像、跟隨者的文本視圖...),所以我讀到我可以使用 NestedScrollView 來實現它,所以我把 NestedScrollView作為我的根布局:
NestedScrollView:
-----------------ConstraintLayout:
---------------------------------rest of the views as in picture above
我還在 NEstedScrollView 中添加了 android:fillViewport="true" 因為這解決了缺少視圖尋呼機的問題。 所以問題是滾動視圖不起作用,一切都與使用 nestedScrollView 之前相同,當我滾動 recyclerView 時,布局的底部不會滾動屏幕。 有誰知道為什么,我使用嵌套的滾動視圖是否錯誤,我還沒有找到任何可以解決我的問題的示例,而且文檔非常糟糕。 我的布局的 XML 代碼:
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme"
android:minHeight="?attr/actionBarSize"
android:elevation="4dp"
android:id="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:title="UserName"
app:layout_constraintEnd_toEndOf="parent"/>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profile_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="8dp"
app:srcCompat="@drawable/ic_profile_24dp"
tools:src="@drawable/ic_profile_24dp"
app:civ_border_color="@color/primaryLightColor"
app:civ_border_width="1dp" android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/title" android:layout_marginStart="8dp"
app:layout_constraintStart_toStartOf="parent" android:layout_marginLeft="8dp"/>
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp" android:layout_marginRight="8dp"
app:layout_constraintStart_toEndOf="@+id/profile_image" android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="@+id/profile_image"
app:layout_constraintTop_toTopOf="@+id/profile_image"
tools:text="Short description "/>
<TextView
android:id="@+id/questions_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/questions"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/profile_image" app:layout_constraintStart_toStartOf="parent"
android:layout_marginLeft="8dp" android:layout_marginStart="8dp"
app:layout_constraintHorizontal_bias="0.5" app:layout_constraintEnd_toStartOf="@+id/followers_label"/>
<TextView
android:id="@+id/questions_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="18sp"
android:textStyle="bold"
tools:text="0"
app:layout_constraintTop_toBottomOf="@+id/questions_label"
app:layout_constraintEnd_toEndOf="@+id/questions_label"
app:layout_constraintStart_toStartOf="@+id/questions_label"/>
<TextView
android:id="@+id/followers_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/followers"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/profile_image"
app:layout_constraintStart_toEndOf="@+id/questions_label" android:layout_marginStart="8dp"
android:layout_marginLeft="8dp" android:layout_marginEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/following_label" android:layout_marginRight="8dp"
app:layout_constraintHorizontal_bias="0.5"/>
<TextView
android:id="@+id/following_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/following"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/profile_image" android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginRight="8dp"
app:layout_constraintStart_toEndOf="@+id/followers_label" app:layout_constraintHorizontal_bias="0.5"/>
<TextView
android:id="@+id/followers_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="18sp"
android:textStyle="bold"
tools:text="0"
app:layout_constraintEnd_toEndOf="@+id/followers_label"
app:layout_constraintStart_toStartOf="@+id/followers_label"
app:layout_constraintTop_toBottomOf="@+id/followers_label"/>
<TextView
android:id="@+id/following_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="18sp"
android:textStyle="bold"
tools:text="0"
app:layout_constraintEnd_toEndOf="@+id/following_label"
app:layout_constraintStart_toStartOf="@+id/following_label"
app:layout_constraintTop_toBottomOf="@+id/following_label"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/primaryLightColor"
app:tabMode="fixed" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/followers_number"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
編輯:建議后的代碼:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme"
android:minHeight="?attr/actionBarSize"
android:id="@+id/title"
tools:title="UserName"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profile_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginStart="@dimen/spacing_normal"
android:layout_marginLeft="@dimen/spacing_normal"
android:layout_marginTop="@dimen/spacing_normal"
app:civ_border_color="@color/secondaryDarkColor"
app:civ_border_width="1dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_profile_24dp"
tools:src="@drawable/ic_profile_24dp" />
<com.google.android.material.textview.MaterialTextView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/description"
android:layout_marginEnd="@dimen/spacing_normal"
android:layout_marginRight="@dimen/spacing_normal"
android:layout_marginLeft="@dimen/spacing_normal"
android:layout_marginStart="@dimen/spacing_normal"
app:layout_constraintStart_toEndOf="@+id/profile_image"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="@+id/profile_image"
app:layout_constraintTop_toTopOf="@+id/profile_image"
tools:text="Short description "/>
<include
layout="@layout/qff_layout"
android:id="@+id/qff_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small"
app:layout_constraintTop_toBottomOf="@+id/profile_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/primaryLightColor"
app:tabMode="fixed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qff_layout"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
這里有什么問題,沒有任何意義,除了 ViewPager 沒有任何滾動
如您所知,NestedScrollView有一個孩子,如果您想要布局的滾動行為,則其孩子的身高必須為wrap_content
。
在第一個布局中,必須將ConstraintLayout
的高度設置為wrap_content
但是如果出於某種原因(例如,要將ViewPager綁定到布局的底部)希望使布局成為match_parent
,則必須使用建議的答案(表示您必須使用CoordinatorLayout
),但要考慮以下因素:
1-您應該將要滾動的所有內容放入AppbarLayout
。此布局是從LinearLayout
擴展而來的,因此您可以輕松地將其放入其中。 從您的問題來看,我認為您想將所有內容滾動到ViewPager
但是您可以根據需要進行更改。
(注意:實際上,我建議將CollapsingToolbar
用作AppbarLAyout
的子AppbarLAyout
,然后將其放入其中,但是對於您的問題,這也很好用)
2-在AppbarLayout
內容根目錄中添加app:layout_scrollFlags="scroll"
屬性
3-添加app:layout_behavior="@string/appbar_scrolling_view_behavior"
屬性到你的兄弟姐妹AppbarLayout
。 在您的問題中,可以在NestedScrollView
使用此屬性。
這是我的代碼:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
app:layout_scrollFlags="scroll"//I forget too add this, so I edit my answer
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll"
android:orientation="vertical">
<View
android:id="@+id/profile_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@dimen/spacing_normal"
android:layout_marginLeft="@dimen/spacing_normal"
android:layout_marginEnd="@dimen/spacing_normal"
android:layout_marginRight="@dimen/spacing_normal"
app:layout_constraintBottom_toBottomOf="@+id/profile_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/profile_image"
app:layout_constraintTop_toTopOf="@+id/profile_image"
tools:text="Short description " />
<include
layout="@layout/qff_layout"
android:id="@+id/qff_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/profile_image" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#559735"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qff_layout"
app:tabMode="fixed" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
我沒有嘗試過這段代碼,但是我很確定這對您有用:)
在NestedScrollView中放
app:layout_behavior="@string/appbar_scrolling_view_behavior"
您是否嘗試過這個:
<CoordinatorLayout>
...<AppbarLayout>
......<Toolbar/>
...</AppbarLayout>
...<NestedScrollView> (set height and weight to match parent, then set fillViewPort="true" and for the last give layout_behavior="@string/appbar_scrolling_view_behavior")
......<ConstraintLayout> (change height to wrap_content because you don't need to set match parent, its already handled by nestedscrollview as a parent)
.........(All Child Components)
......</ConstraintLayout>
...</NestedScrollView>
</CoordinatorLayout>
根據官方文檔,FillViewPort作為NestedScrollView的屬性是將內容的高度擴展到視口邊界。 請檢查官方文檔以獲取更好的解釋: NestedScrollView-FillViewPort
更新:根據您當前的代碼,我進行了一些更改,請檢查一下。
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme"
android:minHeight="?attr/actionBarSize"
android:id="@+id/title"
tools:title="UserName"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profile_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginStart="@dimen/spacing_normal"
android:layout_marginLeft="@dimen/spacing_normal"
android:layout_marginTop="@dimen/spacing_normal"
app:civ_border_color="@color/secondaryDarkColor"
app:civ_border_width="1dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_profile_24dp"
tools:src="@drawable/ic_profile_24dp" />
<com.google.android.material.textview.MaterialTextView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/description"
android:layout_marginEnd="@dimen/spacing_normal"
android:layout_marginRight="@dimen/spacing_normal"
android:layout_marginLeft="@dimen/spacing_normal"
android:layout_marginStart="@dimen/spacing_normal"
app:layout_constraintStart_toEndOf="@+id/profile_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/profile_image"
app:layout_constraintTop_toTopOf="@+id/profile_image"
tools:text="Short description "/>
<include
layout="@layout/qff_layout"
android:id="@+id/qff_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small"
app:layout_constraintTop_toBottomOf="@+id/profile_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/primaryLightColor"
app:tabMode="fixed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qff_layout"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
您的內容適合您的顯示區域。 這就是它發生的原因。 為此,您必須設置ViewPager的固定高度。 之后,整個布局滾動。 但這不是一個適當的解決方案。
例
設置ViewPager高度500dp並檢查。
我將HorizontalScrollView
用作上部布局的容器:
<ConstraintLayout>
<Toolbar/>
<HorizontalScrollView>
<ConstraintLayout android:id="@+id/top_container">
<!-- your upper widgets here -->
</ConstraintLayout>
</HorizontalScrollView>
<TabLayout/>
<ViewPager/>
</ConstraintLayout>
當用戶滾動ViewPager
,它將回調ViewPager.OnPageChangeListener.onPageScrolled() 。 您可以重寫它,以通過HorizontalScrollView.setScrollX()方法以編程方式滾動上部布局,該方法繼承自基本View
類:
class ScrollListener implements ViewPager.OnPageChangeListener {
private ViewGroup scrollView;
ScrollListener(ViewGroup scrollView) {
this.scrollView = scrollView;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
scrollView.setScrollX(scrollView.getWidth() * position + positionOffsetPixels);
}
// the interface requires to override 2 more methods:
@Override
public void onPageSelected(int position) {}
@Override
public void onPageScrollStateChanged(int state) {}
}
然后在MainActivity
,必須通過ViewPager.addOnPageChangeListener()將此偵聽器設置為ViewPager
:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewGroup scrollView = findViewById(R.id.top_scroll);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.addOnPageChangeListener(new ScrollListener(scrollView));
viewPager.setAdapter(new MyAdapter(getApplicationContext(), 3));
}
注意:此代碼將壓縮上部布局,因為HorizontalScrollView
不使用屏幕邊界進行度量和布局。 因此,它允許您將小部件置於屏幕之外( 屏幕截圖 ),並具有滾動功能。
在您的情況下,屏幕上沒有小部件,因此您不會看到結果,因為沒有任何可滾動的內容。 為了進行測試,我在MainActivity
添加了幾行以拉伸上部布局:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
ConstraintLayout upperLayout = findViewById(R.id.top_container);
upperLayout .setMinWidth(size.x + 400);
我的git源代碼示例 : 鏈接 (我通過觸摸移除了滾動的上部布局)
希望這有幫助,祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.