Android: 滚动整个带有 ListView 的片段
Android: Scroll whole fragment with ListView inside
我的片段布局文件中有以下结构:
- ScrollView
- ConstraintLayout
- CardView
- *some stuff here*
- CardView
- ListView
- *list header*
- *list items generated with a custom adapter*
如果我删除外部 ScrollView
,我可以看到 ListView
的全部内容,如果它比剩余的 space 大,则第二个 CardView
,我可以滚动它。第一个 CardView
保持不变,但第二个的内容可以滚动。
但是,我想滚动整个片段。我希望第二个 CardView
展开并包含整个 ListView
,如果我向上或向下滚动,第一个也会移动。
我尝试了几种高度设置组合。没有必要向您展示我的实际布局 XML,因为它一团糟。我想要一个干净的石板。有可能实现吗?
编辑:
我知道 ListView
本身就是一个滚动容器,但我认为滚动整个容器是很常见的,所以我不明白为什么让它工作这么难。
好的,结合多个答案后,我有了我需要的解决方案。
第一个
我需要使用 NestedScrollView
而不是常规的 ScrollView
。
解决了两个滚动容器(ScrollView
和ListView
)之间的冲突。
参考:
注意:我的列表内容是动态的,因此它可能太短而无法填充剩余的 space。我必须在 NestedScrollView
上设置 android:fillViewport="true"
。如果列表比剩余的space长,则不会造成任何麻烦。
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:id="@+id/card1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- NOTE: constraints properties are missing from here for easier reading -->
<!-- card content here -->
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/card2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- NOTE: constraints properties are missing from here for easier reading -->
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- NOTE: this will change in step 3 -->
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
第二
按照上述步骤将使 ListView
折叠到其第一个项目的高度。为了解决这个问题,我需要从 ListView
创建一个子类并覆盖它的 onMeasure()
方法,这样它就可以在运行时计算出正确的高度。
参考:
NonScrollListView.java
package my.package.name
import ...
public class NonScrollListView extends ListView {
// NOTE: right click -> create constructors matching super
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
第三
我需要在布局 XML.
中使用自定义视图而不是常规 ListView
layout.xml摘录
<my.package.name.NonScrollListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
这样我就成功了。即使我点击 ListView
区域,两张卡片也会一起滚动。
我不知道它是否会导致非常长的列表出现性能问题,因为我的最多包含几十个项目,但我在低端 Galaxy A20e 上没有问题。
我的片段布局文件中有以下结构:
- ScrollView
- ConstraintLayout
- CardView
- *some stuff here*
- CardView
- ListView
- *list header*
- *list items generated with a custom adapter*
如果我删除外部 ScrollView
,我可以看到 ListView
的全部内容,如果它比剩余的 space 大,则第二个 CardView
,我可以滚动它。第一个 CardView
保持不变,但第二个的内容可以滚动。
但是,我想滚动整个片段。我希望第二个 CardView
展开并包含整个 ListView
,如果我向上或向下滚动,第一个也会移动。
我尝试了几种高度设置组合。没有必要向您展示我的实际布局 XML,因为它一团糟。我想要一个干净的石板。有可能实现吗?
编辑:
我知道 ListView
本身就是一个滚动容器,但我认为滚动整个容器是很常见的,所以我不明白为什么让它工作这么难。
好的,结合多个答案后,我有了我需要的解决方案。
第一个
我需要使用 NestedScrollView
而不是常规的 ScrollView
。
解决了两个滚动容器(ScrollView
和ListView
)之间的冲突。
参考:
注意:我的列表内容是动态的,因此它可能太短而无法填充剩余的 space。我必须在 NestedScrollView
上设置 android:fillViewport="true"
。如果列表比剩余的space长,则不会造成任何麻烦。
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:id="@+id/card1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- NOTE: constraints properties are missing from here for easier reading -->
<!-- card content here -->
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/card2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- NOTE: constraints properties are missing from here for easier reading -->
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- NOTE: this will change in step 3 -->
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
第二
按照上述步骤将使 ListView
折叠到其第一个项目的高度。为了解决这个问题,我需要从 ListView
创建一个子类并覆盖它的 onMeasure()
方法,这样它就可以在运行时计算出正确的高度。
参考:
NonScrollListView.java
package my.package.name
import ...
public class NonScrollListView extends ListView {
// NOTE: right click -> create constructors matching super
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
第三
我需要在布局 XML.
中使用自定义视图而不是常规ListView
layout.xml摘录
<my.package.name.NonScrollListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
这样我就成功了。即使我点击 ListView
区域,两张卡片也会一起滚动。
我不知道它是否会导致非常长的列表出现性能问题,因为我的最多包含几十个项目,但我在低端 Galaxy A20e 上没有问题。