如何根据ScrollView中的项设置ListView的高度

7

我正在尝试在scrollView中添加listView

问题是我无法编程方式设置ListView的高度并正确地重新绘制ScrollView,因为其下方的项目仍然处于旧位置,未能跟随高度变化。

XML

<ScrollView
    android:id="@+id/movie_detail_scroll_view"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/movie_detail"
        style="?android:attr/textAppearanceLarge"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipChildren="false">
        ...........
        <ListView
            android:id="@+id/trails_list_view"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_below="@+id/movie_videos_container"
            android:choiceMode="none"/>
        <include
            android:id="@+id/movie_reviews_container"
            layout="@layout/partial_movie_reviews"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/trails_list_view"/>
        ............
    </RelativeLayout>
</ScrollView>

我用来调整ListView大小的方法:

/**
 * Sets ListView height dynamically based on the height of the items.
 *
 * @param listView to be resized
 * @return true if the listView is successfully resized, false otherwise
 */
public static boolean setListViewHeightBasedOnItems(ListView listView, ViewGroup container) {

    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter != null) {

        int numberOfItems = listAdapter.getCount();

        // Get total height of all items.
        int totalItemsHeight = 0;
        for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
            View item = listAdapter.getView(itemPos, null, listView);
            item.measure(0, 0);
            totalItemsHeight += item.getMeasuredHeight();
        }

        // Get total height of all item dividers.
        int totalDividersHeight = listView.getDividerHeight() * (numberOfItems - 1);

        // Set list height.
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalItemsHeight + totalDividersHeight;
        listView.setLayoutParams(params);
        listView.requestLayout();

        //redraw the container layout.
        container.requestLayout();

        return true;

    } else {
        return false;
    }

}

结果: enter image description here 即使我重新绘制ScrollView,也无法去除这个空白区域,我该怎么办?

1
你确定ListView是做这件事最简单的方法吗?如果列表非常短,LinearLayout可能是更快的解决方案。 - John Bennedict Lorenzo
我会尝试使用LinearLayout。 - humazed
你尝试过修改ListView中的layout_height吗? - Pooya
不,我已经切换到了具有水平方向的RecycleView,这是我的新布局,也许你会发现它很有用。https://github.com/humazed/PopularMovies/blob/master/app/src/main/res/layout/fragment_movie_details.xml - humazed
请问您能否提供ListView中项目的布局? - Abraham Mathew
显示剩余4条评论
6个回答

4

这对于聊天功能是百分之百有效的,即使元素的高度不同。

public static boolean setListViewHeightBasedOnItems(ListView listView) {

    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter != null) {

        int numberOfItems = listAdapter.getCount();

        // Get total height of all items.
        int totalItemsHeight = 0;
        for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
            View item = listAdapter.getView(itemPos, null, listView);
            float px = 500 * (listView.getResources().getDisplayMetrics().density);
            item.measure(View.MeasureSpec.makeMeasureSpec((int) px, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            totalItemsHeight += item.getMeasuredHeight();
        }

        // Get total height of all item dividers.
        int totalDividersHeight = listView.getDividerHeight() *
                (numberOfItems - 1);
        // Get padding
        int totalPadding = listView.getPaddingTop() + listView.getPaddingBottom();

        // Set list height.
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalItemsHeight + totalDividersHeight + totalPadding;
        listView.setLayoutParams(params);
        listView.requestLayout();
        //setDynamicHeight(listView);
        return true;

    } else {
        return false;
    }

}

我使用自定义适配器来实现这个功能。你可以根据需要更改参数(数字500)= 500 *(listView.getResources()。getDisplayMetrics()。density); - Andrij Kan
但是500是什么? - user2847219
更改您需要的500。我使用320。它适用于联想A7000和小米。 - Andrij Kan
还有另一种选项,不需要创建两个列表。只需在标题中放置所需的所有内容即可。 - Andrij Kan
对我来说,即使使用自定义适配器也能正常工作..做得好,兄弟。 - Sharon Joshi
我有一点担心我的项目时间表,因为这个子ListView的高度问题。突然间我发现了您的答案,它起到了魔法般的作用。非常感谢。 - Avijit

0
将您的滚动视图设置如下:
<ScrollView
 android:id="@+id/movie_detail_scroll_view"
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:fillViewport="true">

仍然存在相同的问题。 - humazed

0

尝试使用ListView

android:layout_height="wrap_content"

同时不要删除:

android:fillViewport="true"

从滚动视图中


仍然存在相同的问题。 - humazed
如果我使用android:layout_height="wrap_content",它只会显示一个项目。 - humazed
即使我删除了android:fillViewport="true",请在评论中添加您的编辑,并仅在其有效时编辑答案,以便我能够看到您的消息。 - humazed

0

转换为线性

        <LinearLayout
            android:id="@+id/movie_detail"
            style="?android:attr/textAppearanceLarge"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:clipChildren="false">
                     ...........
             <ListView
                android:id="@+id/trails_list_view"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@+id/movie_videos_container"
                android:choiceMode="none"/>
            <include
                android:id="@+id/movie_reviews_container"
                layout="@layout/partial_movie_reviews"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                />
                  ............
    </LinearLayout>
</ScrollView>

0

我建议使用RecyclerView代替ListView

1. ListView

使用NestedScrollview而不是Scrollview

<android.support.v4.widget.NestedScrollView

将固定高度替换为wrap_content,将android:layout_height="200dp"替换为android:layout_height="wrap_content"

计算列表视图的动态高度

public void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        // pre-condition
        return;
    }

    int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);

        if(listItem != null){
            // This next line is needed before you call measure or else you won't get measured height at all. The listitem needs to be drawn first to know the height.
            listItem.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
            listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
            totalHeight += listItem.getMeasuredHeight();

        }
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
}

2. RecyclerView

public class MaxHeightRecyclerView extends RecyclerView {
    private int mMaxHeight;

    public MaxHeightRecyclerView(Context context) {
        super(context);
    }

    public MaxHeightRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize(context, attrs);
    }

    public MaxHeightRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initialize(context, attrs);
    }

    private void initialize(Context context, AttributeSet attrs) {
        TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
        mMaxHeight = arr.getLayoutDimension(R.styleable.MaxHeightScrollView_maxHeight, mMaxHeight);
        arr.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mMaxHeight > 0) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.AT_MOST);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

在attrs.xml中
<declare-styleable name="MaxHeightScrollView">
        <attr name="maxHeight" format="dimension" />
    </declare-styleable>

然后在xml中设置maxHeight = 200dp,如果高度小于200dp,则采用wrap_content,超过200dp后将滚动。


0

将ListView或RecyclerView放在ConstraintLayout中,就不需要使用ScrollView视图了,也不必担心列表的高度问题...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接