Android NestedScrollView 在 viewpager 布局中不起作用
Android NestedScrollView doesn't work in layout with viewpager
这是我的布局:
当我在 viewPager 中滚动 recyclerView 时,我希望能够滚动布局的上半部分(followers/following 的名称、图像、文本视图...),所以我读到我可以使用 NestedScrollView 来实现它,所以我将 NestedScrollView 作为我的根布局:
NestedScrollView:
-----------------ConstraintLayout:
---------------------------------rest of the views as in picture above
我还在 NEstedScrollView 中添加了 android:fillViewport="true" 因为这解决了缺少视图寻呼机的问题。
所以问题是滚动视图不起作用,一切都与使用 nestedScrollView 之前相同,当我滚动 recyclerView 时,我布局的底部不会滚动屏幕。有谁知道为什么,我使用嵌套的 scrollView 是不是错了,我还没有找到任何可以解决我的问题的例子,而且文档真的很糟糕。
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 什么都没有滚动
你试过这个吗:
<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 as an NestedScrollView Attributes 是将内容的高度拉伸到视口边界。请查看官方文档以获得更好的解释:
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 的固定高度。之后你的整个布局滚动。但这不是一个合适的解决方案。
示例
set ViewPager height 500dp and check it.
我用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:
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
不使用屏幕边界来测量和布局。因此,它允许您将小部件移出屏幕 (screenshot) 并提供滚动功能。
在您的情况下,屏幕上没有小部件,因此您看不到结果,因为没有可滚动的内容。为了测试,我在 MainActivity
中添加了几行来拉伸上层布局:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
ConstraintLayout upperLayout = findViewById(R.id.top_container);
upperLayout .setMinWidth(size.x + 400);
我的git源代码示例:link(我删除了上层布局的触摸滚动)
希望对您有所帮助,祝您好运!
如您所知,NestedScrollView 有一个子视图,如果您希望布局具有滚动行为,则其子视图的高度必须为 wrap_content
。
在您的第一个布局中,您必须将 ConstraintLayout
的高度设置为 wrap_content
,但是如果出于任何原因(例如您想要将您的 ViewPager 绑定在布局的底部)您必须使用建议的答案(这意味着您必须使用 CoordinatorLayout
)但要考虑以下因素:
1- 你应该把你想要滚动的所有东西都放在 AppbarLayout
中。这个布局从 LinearLayout
扩展而来,所以你可以很容易地把你的东西放进去。根据你的问题,我认为你想滚动 ViewPager
上方的所有内容,但你可以根据需要进行更改。
(注意:实际上,我建议使用 CollapsingToolbar
作为 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>
我没有尝试过这段代码,但我很确定这对你有用:)
这是我的布局:
当我在 viewPager 中滚动 recyclerView 时,我希望能够滚动布局的上半部分(followers/following 的名称、图像、文本视图...),所以我读到我可以使用 NestedScrollView 来实现它,所以我将 NestedScrollView 作为我的根布局:
NestedScrollView:
-----------------ConstraintLayout:
---------------------------------rest of the views as in picture above
我还在 NEstedScrollView 中添加了 android:fillViewport="true" 因为这解决了缺少视图寻呼机的问题。 所以问题是滚动视图不起作用,一切都与使用 nestedScrollView 之前相同,当我滚动 recyclerView 时,我布局的底部不会滚动屏幕。有谁知道为什么,我使用嵌套的 scrollView 是不是错了,我还没有找到任何可以解决我的问题的例子,而且文档真的很糟糕。 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 什么都没有滚动
你试过这个吗:
<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 as an NestedScrollView Attributes 是将内容的高度拉伸到视口边界。请查看官方文档以获得更好的解释: 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 的固定高度。之后你的整个布局滚动。但这不是一个合适的解决方案。
示例
set ViewPager height 500dp and check it.
我用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:
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
不使用屏幕边界来测量和布局。因此,它允许您将小部件移出屏幕 (screenshot) 并提供滚动功能。
在您的情况下,屏幕上没有小部件,因此您看不到结果,因为没有可滚动的内容。为了测试,我在 MainActivity
中添加了几行来拉伸上层布局:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
ConstraintLayout upperLayout = findViewById(R.id.top_container);
upperLayout .setMinWidth(size.x + 400);
我的git源代码示例:link(我删除了上层布局的触摸滚动)
希望对您有所帮助,祝您好运!
如您所知,NestedScrollView 有一个子视图,如果您希望布局具有滚动行为,则其子视图的高度必须为 wrap_content
。
在您的第一个布局中,您必须将 ConstraintLayout
的高度设置为 wrap_content
,但是如果出于任何原因(例如您想要将您的 ViewPager 绑定在布局的底部)您必须使用建议的答案(这意味着您必须使用 CoordinatorLayout
)但要考虑以下因素:
1- 你应该把你想要滚动的所有东西都放在 AppbarLayout
中。这个布局从 LinearLayout
扩展而来,所以你可以很容易地把你的东西放进去。根据你的问题,我认为你想滚动 ViewPager
上方的所有内容,但你可以根据需要进行更改。
(注意:实际上,我建议使用 CollapsingToolbar
作为 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>
我没有尝试过这段代码,但我很确定这对你有用:)