【发布时间】:2023-03-02 22:13:02
【问题描述】:
我有一个 3 页的 viewpager,每个页面可能包含也可能不包含 recyclerview。 recyclerview 中的项目数量因用户而异。我在这个问题之后制作了一个自定义视图寻呼机:
How to wrap the height of a ViewPager to the height of its current Fragment?。
我现在面临的问题有两点:
1. 在切换选项卡时,会为每个片段调用 requestLayout()。所以当recyclerview包含很多项目时,切换时会有延迟,因为它是一次又一次地测量选项卡。并且 recyclerview 中的项目是动态的,这意味着它在滚动行为上有加载更多项目。
2. 当recyclerview 没有item 时,会显示一个textview 来指示没有item。因为 viewpager 包装了内容,所以我似乎无法将 textview 在片段中居中。所以当没有recyclerview时,我需要viewpager填满整个高度。
这是我的 CustomViewPager 代码:
public class CustomViewPager extends ViewPager {
private int currentPagePosition = 0;
Context context;
public CustomViewPager(@NonNull Context context) {
super(context);
this.context = context;
}
public CustomViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
View child = getChildAt(currentPagePosition);
if(child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
if(heightMeasureSpec != 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void measureCurrentView(int position) {
currentPagePosition = position;
requestLayout();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return false;
}
}
这是我的 viewpager 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="250dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="#F8F8F8"
android:id="@+id/header"/>
<com.google.android.material.tabs.TabLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/tabs">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1ST"
/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2ND"
/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3RD"
/>
</com.google.android.material.tabs.TabLayout>
<com.example.smilee.adapters.CustomViewPager
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/items"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tabs"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
这是每个片段的布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@android:color/white">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyclerview"
android:nestedScrollingEnabled="false"
android:visibility="gone"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="No items to show."
android:fontFamily="@font/medium"
android:textColor="#777"
android:textSize="15dp"
android:gravity="center"
android:id="@+id/noItemText"
android:includeFontPadding="false"
android:visibility="visible"/>
</androidx.constraintlayout.widget.ConstraintLayout>
如何做到这一点?
无论recyclerview中的项目数如何,如何快速切换选项卡,如果recyclerview不可用,如何通过填充整个高度来居中textview?希望你能帮忙。问候。
【问题讨论】:
-
您考虑过使用 ViewPager2 吗?它应该与 RecyclerView 一起玩得更好,因为垂直 RecyclerView(ViewPager2 基于 RecyclerView)内的水平 RecyclerView 是一种常见模式,它旨在处理这种情况。
-
但是它会根据内容改变它的高度吗?
-
我不确定你的意思。一些图表可能会有所帮助
-
我的意思是,viewpager 的高度会根据其子项(动态高度)而变化。假设我有 3 个标签。第一个选项卡可能包含一个 recyclerview 和 1000 个项目。第二个可能包含一个 recyclerview 和只有 3 个项目。因此,当我从第一个选项卡切换到第二个选项卡时,第二个选项卡会占用包含 1000 个项目的第一个选项卡的高度,还是只会占用包含 3 个项目的回收视图的高度?希望你能理解。
-
哦,我明白了。为什么你有一个嵌套的滚动视图?在滚动视图中使用 RecyclerView 通常是个坏主意,因为它会完全禁用所有回收(它必须立即布置列表中的每个项目),因此如果您有多个垂直页面的项目,可能会导致您滞后。在上面的代码中,滚动视图似乎不是很有用
标签: java android android-fragments android-recyclerview android-viewpager