ChatGPT解决这个技术问题 Extra ChatGPT

滚动视图中的 Android 列表视图

我有一个 android 布局,其中有一个 scrollView,其中包含许多元素。在 scrollView 的底部,我有一个 listView,然后由适配器填充。

我遇到的问题是 android 将 listViewscrollView 中排除,因为 scrollView 已经具有可滚动功能。我希望 listView 与内容一样长,并且主滚动视图可以滚动。

我怎样才能实现这种行为?

这是我的主要布局:

<ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="2"
    android:fillViewport="true"
    android:gravity="top" >

    <LinearLayout
        android:id="@+id/foodItemActvity_linearLayout_fragments"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
    </LinearLayout>

</ScrollView>

然后,我以编程方式将我的组件添加到 id:foodItemActvity_linearLayout_fragments 的线性布局中。下面是加载到该线性布局中的视图之一。这是卷轴给我带来麻烦的一个。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
       android:id="@+id/fragment_dds_review_textView_label"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Reviews:"
       android:textAppearance="?android:attr/textAppearanceMedium" />

   <ListView
       android:id="@+id/fragment_dds_review_listView"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
   </ListView>
</LinearLayout>

然后我的适配器会填满这个列表视图。

这是我单击主滚动视图时来自 android 层次结构查看器的图像:

https://i.stack.imgur.com/3Gsoj.jpg

如您所见,它不包括评论列表视图。

我应该能够向下滚动页面并看到 8 条评论,但它只显示这 3 条评论,我可以滚动评论所在的小部分。我想要一个全局页面滚动

我得到了解决方案:androidhub4you.com/2012/12/…
这里是。您可以找到完整的描述信息:stackoverflow.com/questions/20116381/…
这个很容易用 RecycleView 代表 ListView
我希望它对你有用stackoverflow.com/a/62011087/11554604

a
arshu

让任何子视图在 ScrollView 内滚动。 ListView、RecyclerView 等任何东西。您只需在当前 xml 中将 ScrollView 替换为 androidx.core.widget.NestedScrollView然后魔法发生了。

下面是一个示例 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">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:paddingBottom="20dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Recycler View inside a Scroll View"
            android:textColor="@color/black"
            android:textSize="@dimen/_20sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="Below is a Recycler View as an example."
            android:textSize="16sp" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            app:layout_constraintTop_toBottomOf="@id/et_damaged_qty" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="This textview automatically goes below the Recycler View."
            android:textSize="16sp" />
    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>

现在,您可以摆脱为解决嵌套滚动所做的所有丑陋黑客行为。


谢谢!这对我有用,但我必须进行一些调整,因为列表项是复杂的视图,我使用的是 ExpandableListView:view = listAdapter.getView(0, view, listView); int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.MATCH_PARENT, View.MeasureSpec.EXACTLY); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.EXACTLY); view.measure(widthMeasureSpec, heightMeasureSpec);
我发现这个解决方案在我的情况下非常有效,即支持具有可变高度的列表项 - stackoverflow.com/a/17503823/1433187
请删除多余的 requestLayout() - setLayoutParams 方法已经这样做了。
FIX 测量 view.measure(MeasureSpec.makeMeasureSpec(desiredWidth, MeasureSpec.AT_MOST),MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
我需要对 gridview 做同样的事情。有什么建议吗?
R
Ryan M

答案很简单,我很惊讶这里还没有答案。

在列表本身上使用 Header View 或/和 Footer View。不要将 ScrollViewListView 或任何可以滚动的东西混用。它旨在与页眉和页脚一起使用:)

本质上,获取 ListView 上方的所有内容,将其作为布局放入另一个 .xml 文件中,然后在代码中对其进行膨胀并将其作为标题视图添加到列表中。

IE

View header = getLayoutInflater().inflate(R.layout.header, null);
View footer = getLayoutInflater().inflate(R.layout.footer, null);
listView.addHeaderView(header);
listView.addFooterView(footer);

如果添加标题视图,onListItemClick 中的位置 int 参数将为 +1。所以你必须处理它。 (列表中的第一项将具有位置 1,而不是 0)
我希望 ViewPager 有一个标题。
我希望 GridView 有一个标题
您是否尝试在页眉或页脚中添加另一个 ListViewScrollView
除非您需要在标题中编辑文本,否则这种方法很有效。出现在列表视图中时,Edittext 不保留焦点
a
acyn

我知道它已经很长时间了,但我也遇到了这个问题,尝试了这个解决方案并且它正在工作。所以我想它也可以帮助其他人。

我在滚动视图的布局 xml 上添加了 android:fillViewport="true"。所以总的来说我的 ScrollView 会是这样的。

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scrollView6" 
    android:fillViewport="true">

它对我来说就像魔术一样。位于我的 ScrollView 内的 ListView 再次扩大到它的大小。

这是 ScrollView 和 ListView 的完整示例代码。

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scrollView6" android:fillViewport="true">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        ....
        <ListView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/lv_transList" android:layout_gravity="top"
            android:layout_marginTop="5dp"/>
        ....
    </LinearLayout>
</ScrollView>

它禁用 ListView 滚动行为,因此如果项目大于屏幕大小,则无法滚动列表视图。
它禁用 ScrollView 的滚动功能
此解决方案不起作用,因为如果列表视图占据整个屏幕,则列表视图下方的元素无法访问
D
Dedaniya HirenKumar

您创建不可滚动的自定义 ListView

  public class NonScrollListView extends ListView {

            public NonScrollListView(Context context) {
                super(context);
            }
            public NonScrollListView(Context context, AttributeSet attrs) {
                super(context, attrs);
            }
            public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
            }
            @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 version="1.0" encoding="utf-8"?>
        <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fadingEdgeLength="0dp"
            android:fillViewport="true"
            android:overScrollMode="never"
            android:scrollbars="none" >

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >

                <!-- com.Example Changed with your Package name -->

                <com.Example.NonScrollListView
                    android:id="@+id/lv_nonscroll_list"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" >
                </com.Example.NonScrollListView>

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/lv_nonscroll_list" >

                    <!-- Your another layout in scroll view -->

                </RelativeLayout>
            </RelativeLayout>

        </ScrollView>

在 Java 文件中创建 customListview 的对象而不是 ListView,例如: NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);


这会强制滚动视图在列表视图的顶部滚动。意外行为
S
Su Zhenpeng
    public static void setListViewHeightBasedOnChildren(ListView listView) {
    // 获取ListView对应的Adapter
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        return;
    }

    int totalHeight = 0;
    for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(0, 0); // 计算子项View 的宽高
        totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
            + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    // listView.getDividerHeight()获取子项间分隔符占用的高度
    // params.height最后得到整个ListView完整显示需要的高度
    listView.setLayoutParams(params);
}

您可以将此代码用于滚动视图中的列表视图


这会禁用内置滚动的 Listviews 吗?
这也适用于 RecyclerView 内的 ListView 以显示超过第一个元素。
谢谢,这个答案很有帮助。我的问题是我在 ScrollView 中有一个 ListView,当我更新 ListView 中的元素时,ScrollView 仍然具有相同的高度。这意味着即使 ListView 的行数较少,用户也能够向下滚动。
对于花费大量时间弄清楚如何将 ListView 放入 ScrollView(不建议)的任何人,因为使用线性布局会杀死您的 UI,那么这工作正常,但建议您在 linearview 中动态添加项目
S
Sibin

不要在 Parent ScrollView 中做任何事情。仅对子 ListView 执行此操作。一切都会完美运行。

mListView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mScrollView.requestDisallowInterceptTouchEvent(true);
               int action = event.getActionMasked();
                switch (action) {
                    case MotionEvent.ACTION_UP:
                        mScrollView.requestDisallowInterceptTouchEvent(false);
                        break;
                }
                return false;
            }
        });

这应该是一个公认的答案。它简单而智能。只需在触摸列表视图时禁用滚动视图,并在您抬起手指时再次启用它
N
Nandan Kumar Singh

如果您在代码中仅实现了 ListView,则此代码将解决您的问题。

如果您使用 RelativeLayout 作为 ListView 子项,则此代码会在 listItem.measure(0, 0); 此处返回 NullPointerException,因为 RelativeLayout.And 解决方案是将您的 Relativelayout 放在 LinearLayout 中,它会正常工作。

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

    int totalHeight = 0;
    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(0, 0);
        totalHeight += listItem.getMeasuredHeight();
    }

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

如果您的列表视图中有填充,那么您也应该添加它:- int padding = listView.getPaddingTop() + listView.getPaddingBottom();
是的,相对布局在计算高度时会产生问题。感谢您解释相对布局问题
C
Community

您可以通过将 android:fillViewport="true" 添加到 ScrollView 来解决此问题。

<ScrollView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@color/white"
      android:fillViewport="true"
      android:scrollbars="vertical">

<ListView
      android:id="@+id/statusList"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:animationCache="false"
      android:divider="@null"
      android:scrollingCache="false"
      android:smoothScrollbar="true" />

</ScrollView>

在使用该属性之前,我的列表视图中只有一个子视图可见。使用后,列表的所有行或子项都是可见的。


v8 以上的新 Android 版本不再支持 Android:scrollingCache="false"。
A
Alexander Zhak

我会把它留在这里,以防有人遇到同样的问题。我必须在 ScrollView 中放置一个 ListView。由于多种原因,带有标题的 ListView 不是一个选项。也不是使用 LinearLayout 代替 ListView 的选项。所以我遵循了接受的解决方案,但它不起作用,因为列表中的项目具有多行的复杂布局,并且每个列表视图项目的高度可变。高度测量不正确。解决方案是测量 ListView Adapter 的 getView() 方法中的每个项目。

@Override
public View getView(int position, View view, ViewGroup parent) {
    ViewHolder holder;
    if (view == null) {
        . . .
        view.setTag(holder);
    } else holder = (ViewHolder)view.getTag();
    . . .

    // measure ListView item (to solve 'ListView inside ScrollView' problem)
    view.measure(View.MeasureSpec.makeMeasureSpec(
                    View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    return view;
}

T
Taras Okunev

您可以轻松地将 ListView 放入 ScrollView!只需要以编程方式更改 ListView 的高度,如下所示:

    ViewGroup.LayoutParams listViewParams = (ViewGroup.LayoutParams)listView.getLayoutParams();
    listViewParams.height = 400;
    listView.requestLayout();

这完美!


这就是 the accepted answer 所做的,但它不是神奇地确定它是 400,而是计算确切的高度。这样你就不用猜了。
H
Hiren Patel

经过大量研发后完成:

fragment_one.xml 应如下所示:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scrollViewParent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="400dip" >

            <ListView
                android:id="@+id/listView"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <View
                android:id="@+id/customView"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="@android:color/transparent" />
        </RelativeLayout>

        <!-- Your other elements are here -->

    </LinearLayout>

</ScrollView>

您的 FragmentOne.java Java 类如下所示:

private ListView listView;
private View customView

onCreateView

listView = (ListView) rootView.findViewById(R.id.listView);
scrollViewParent = (ScrollView)rootView.findViewById(R.id.scrollViewParent);
customView = (View)rootView.findViewById(R.id.customView);

customView.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        // Disallow ScrollView to intercept touch events.
                        scrollViewParent.requestDisallowInterceptTouchEvent(true);
                        // Disable touch on transparent view
                        return false;

                    case MotionEvent.ACTION_UP:
                        // Allow ScrollView to intercept touch events.
                        scrollViewParent.requestDisallowInterceptTouchEvent(false);
                        return true;

                    case MotionEvent.ACTION_MOVE:
                        scrollViewParent.requestDisallowInterceptTouchEvent(true);
                        return false;

                    default:
                        return true;
                }
            }
        });

M
Malcolm Bryant

我的要求是在 ScrollView 中包含一个大小相等的项目的 ListView。我尝试了此处列出的其他一些解决方案,但似乎都没有正确调整 ListView 的大小(空间太小或太多)。这对我有用:

    public static void expandListViewHeight(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null)
        return;

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    listView.measure(0, 0);
    params.height = listView.getMeasuredHeight() * listAdapter.getCount() + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
}

希望这可以帮助某人。


C
CHarris

我有一个与原始海报提出的问题类似的问题 - 如何使列表视图在滚动视图内滚动 - 这个答案解决了我的问题。 Disable scrolling of a ListView contained within a ScrollView

我没有像 OP 那样将新片段调用到现有布局或类似的东西中,所以我的代码看起来像这样:

<ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="2"
    android:fillViewport="true"
    android:gravity="top" >

 <LinearLayout
        android:id="@+id/foodItemActvity_linearLayout_fragments"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >


    <TextView
       android:id="@+id/fragment_dds_review_textView_label"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Reviews:"
       android:textAppearance="?android:attr/textAppearanceMedium" />

   <ListView
       android:id="@+id/my_listView"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
   </ListView>

</LinearLayout>

</ScrollView>

基本上我正在做的是在调用它之前检查列表视图的长度,当我调用它时,我将它变成那个长度。在你的 java 类中使用这个函数:

public static void justifyListViewHeightBasedOnChildren (ListView listView) {

    ListAdapter adapter = listView.getAdapter();

    if (adapter == null) {
        return;
    }
    ViewGroup vg = listView;
    int totalHeight = 0;
    for (int i = 0; i < adapter.getCount(); i++) {
        View listItem = adapter.getView(i, null, vg);
        listItem.measure(0, 0);
        totalHeight += listItem.getMeasuredHeight();
    }

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

并像这样调用函数:

justifyListViewHeightBasedOnChildren(listView);

结果是一个没有滚动条的列表视图,列表视图的整个长度被显示,随着滚动视图的滚动条滚动。


A
AAverin

正如其他人已经提到的,不要在 ScrollView 中使用 ListView。

要解决方法,您可以使用 LinearLayout,但仍要保持整洁 - 使用 Adapter 填充 LinearLayout,就像使用 ListView 一样

您可以将此类用作支持适配器的 LinearLayout 替代品

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;

public class AdaptableLinearLayout extends LinearLayout {

private BaseAdapter mAdapter;

private int mItemCount = 0;

private boolean mDisableChildrenWhenDisabled = false;

private int mWidthMeasureSpec;
private int mHeightMeasureSpec;


public AdaptableLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}

public BaseAdapter getAdapter() {
    return mAdapter;
}

public void setAdapter(BaseAdapter adapter) {
    mAdapter = adapter;
    adapter.registerDataSetObserver(new DataSetObserver() {
        @Override
        public void onChanged() {
            updateLayout();
            super.onChanged();
        }

        @Override
        public void onInvalidated() {
            updateLayout();
            super.onInvalidated();
        }
    });
    updateLayout();
}

private void updateLayout() {
    mItemCount = mAdapter.getCount();
    requestLayout();
    invalidate();
}

/**
 * set size for the current View
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    mWidthMeasureSpec = widthMeasureSpec;
    mHeightMeasureSpec = heightMeasureSpec;

    removeAllViewsInLayout();
    for (int i = 0; i < mItemCount; i++) {
        makeAndAddView(i);
    }
}

private View makeAndAddView(int position) {
    View child;

    // Nothing found in the recycler -- ask the adapter for a view
    child = mAdapter.getView(position, null, this);

    // Position the view
    setUpChild(child, position);

    return child;

}

private void setUpChild(View child, int position) {

    ViewGroup.LayoutParams lp = child.getLayoutParams();
    if (lp == null) {
        lp = generateDefaultLayoutParams();
    }
    addViewInLayout(child, position, lp);

    // Get measure specs
    int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, getPaddingTop() + getPaddingBottom(), lp.height);
    int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, getPaddingLeft() + getPaddingRight(), lp.width);

    // Measure child
    child.measure(childWidthSpec, childHeightSpec);

    int childLeft;
    int childRight;

    // Position vertically based on gravity setting
    int childTop = getPaddingTop() + ((getMeasuredHeight() - getPaddingBottom() - getPaddingTop() - child.getMeasuredHeight()) / 2);
    int childBottom = childTop + child.getMeasuredHeight();

    int width = child.getMeasuredWidth();
    childLeft = 0;
    childRight = childLeft + width;

    child.layout(childLeft, childTop, childRight, childBottom);

    if (mDisableChildrenWhenDisabled) {
        child.setEnabled(isEnabled());
    }
}
}

这是否管理回收?还是适配器负责回收视图?
我很久以前就实现了这个类,所以我认为出于 dev.speed 的目的,我没有添加回收支持。正如我现在在代码中看到的那样,类假定回收器是空的
J
Jeyhun Karimov

您可以将所有内容放入线性布局。也就是说,创建线性布局,它将有 2 个孩子,滚动视图和另一个线性布局。给他们布局权重,然后就可以了:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="0dip" android:layout_weight="0.8">

    <LinearLayout
        android:id="@+id/seTaskActivityRoot"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/taskName" />


        <Spinner
            android:id="@+id/seTaskPrioritiesSP"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/taskTargetInNumeric" />

        <Spinner
            android:id="@+id/seTaskUnitsSP"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/textView6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/newTaskCurrentStatus" />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:hint="@string/addTaskCurrentStatus"
            android:inputType="numberDecimal" />


    </LinearLayout>
</ScrollView>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="0dip"
    android:orientation="vertical" android:layout_weight="0.2">

    <TextView
        android:id="@+id/textView8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />

    <ListView
        android:id="@+id/logList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>


这意味着 ListView 不会随其余内容一起滚动。无论用户是向上还是向下滚动,它都会一直占据部分屏幕
M
Muhammad Asim

永远不要将 ScrollView 与 ListView 一起使用,因为 ListView 负责自己的垂直滚动。最重要的是,这样做会破坏 ListView 中处理大型列表的所有重要优化,因为它有效地强制 ListView 显示其整个项目列表以填充 ScrollView 提供的无限容器。

http://developer.android.com/reference/android/widget/ScrollView.html


S
SimonSays

切勿将 ListView 放在 ScrollView 内!您可以在 Google 上找到有关该主题的更多信息。在您的情况下,使用 LinearLayout 而不是 ListView 并以编程方式添加元素。


哦,好的,我明白了,我还可以使用类似的适配器概念来填充线性布局吗?
R
Rajnish Mishra

更新

<ScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:fillViewport="true"
android:gravity="top" >

<LinearLayout
    android:id="@+id/foodItemActvity_linearLayout_fragments"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
</LinearLayout>

<ScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:fillViewport="true"
android:gravity="top" >

<LinearLayout
    android:id="@+id/foodItemActvity_linearLayout_fragments"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
</LinearLayout>

这里的重点是您尝试将高度设置为 0dp(固定)


这样权重就会对其产生影响。
您希望上方的产品图像和左文本视图可滚动吗?如果是这样,您应该在滚动视图中删除这两项,因为我目前可以看到它们不是
它们当前位于滚动视图内,因为我以编程方式将它们添加到滚动视图内的线性布局中。如果我的逻辑是正确的,则线性布局子级也应该与滚动视图一起使用。
b
bedman

找到了scrollview -> viewpager -> FragmentPagerAdapter -> fragment -> 动态列表视图的解决方案,但我不是作者。有一些错误,但至少它有效

public class CustomPager extends ViewPager {

    private View mCurrentView;

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

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

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mCurrentView == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        int height = 0;
        mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = mCurrentView.getMeasuredHeight();
        if (h > height) height = h;
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void measureCurrentView(View currentView) {
        mCurrentView = currentView;
        this.post(new Runnable() {
            @Override
            public void run() {
                requestLayout();
            }
        });
    }

    public int measureFragment(View view) {
        if (view == null)
            return 0;

        view.measure(0, 0);
        return view.getMeasuredHeight();
    }
}


public class MyPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    private int mCurrentPosition = -1;


    public MyPagerAdapter(FragmentManager fm) {
        super(fm);//or u can set them separately, but dont forget to call notifyDataSetChanged()
        this.fragments = new ArrayList<Fragment>();
        fragments.add(new FirstFragment());
        fragments.add(new SecondFragment());
        fragments.add(new ThirdFragment());
        fragments.add(new FourthFragment());
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        if (position != mCurrentPosition) {
            Fragment fragment = (Fragment) object;
            CustomPager pager = (CustomPager) container;
            if (fragment != null && fragment.getView() != null) {
                mCurrentPosition = position;
                pager.measureCurrentView(fragment.getView());
            }
        }
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

片段布局可以是任何东西

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:orientation="vertical"
    android:layout_height="match_parent" tools:context="nevet.me.wcviewpagersample.FirstFragment">


    <ListView
        android:id="@+id/lv1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#991199"/>
</LinearLayout>

然后在某个地方

lv = (ListView) view.findViewById(R.id.lv1);
        lv.setAdapter(arrayAdapter);
        setListViewHeightBasedOnChildren(lv);
    }

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        int totalHeight = 0;
        View view = null;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            view = listAdapter.getView(i, view, listView);
            if (i == 0)
                view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth,
                        LinearLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }

M
Manohar

使用这个 ListView 为我工作

   package net.londatiga.android.widget;

      import android.util.AttributeSet;
      import android.view.ViewGroup;
      import android.widget.ListView;
      import android.content.Context;

   public class ExpandableHeightListView extends ListView
      {

    boolean expanded = false;

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

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

public ExpandableHeightListView(Context context, AttributeSet attrs,
        int defStyle)
{
    super(context, attrs, defStyle);
}

public boolean isExpanded()
{
    return expanded;
}

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    // HACK! TAKE THAT ANDROID!
    if (isExpanded())
    {
        // Calculate entire height by providing a very large height hint.
        // But do not use the highest 2 bits of this integer; those are
        // reserved for the MeasureSpec mode.
        int expandSpec = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);

        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
    else
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

public void setExpanded(boolean expanded)
{
    this.expanded = expanded;
}
}

并在 xml

            <com.pakagename.ExpandableHeightListView
                android:id="@+id/expandableHeightListView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </com.Example.ExpandableHeightListView>

并在 MainActivity

  ExpandableHeightListView listView = new ExpandableHeightListView(this);
    listview=(ExpandableHeightListView)findViewById(R.id.expandableHeightListView);
   listView.setAdapter(adapter); //set your adaper
   listView.setExpanded(true);

Refer This 文章了解更多信息并了解如何将 gridview 保持在滚动视图中


P
Powkachu

不能在 List-view 中使用 Scroll-view,因为 List-view 已经具有滚动属性。

要在 Scroll-view 中使用列表视图,您可以按照以下步骤对我有用: 1) 创建 NonScrollListView java 文件,禁用列表视图的默认滚动属性。并且代码在你的包结构下面;导入android.content.Context;导入android.util.AttributeSet;导入android.view.ViewGroup;导入 android.widget.ListView;公共类 NonScrollListView 扩展 ListView { public NonScrollListView(Context context) { super(context); } public NonScrollListView(上下文上下文,AttributeSet attrs){超级(上下文,attrs); } public NonScrollListView(上下文上下文,AttributeSet attrs,int defStyle){ super(context,attrs,defStyle); } @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 参数 = getLayoutParams(); params.height = getMeasuredHeight(); } } 2) 现在创建包含 NestedScrollView 的 xml 文件,并在其中使用 NonScrollListView 列出您的项目。这将使您的整个屏幕与所有视图一起滚动。 <查看android:layout_width= "match_parent" android:layout_height="1dp" android:layout_marginBottom="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:background="#ddd"/> < /LinearLayout> 3) 现在在java 类,即home.java 中定义NonScrollListView 而不是Listview。包 comabc.xyz.landscapeapp;导入android.content.Intent;导入android.support.annotation.NonNull;导入 android.support.annotation.Nullable;导入android.support.v4.app.Fragment;导入android.os.Bundle;导入 android.support.v4.app.FragmentTransaction;导入android.util.Log;导入 android.view.LayoutInflater;导入android.view.View;导入android.view.ViewGroup;导入 android.widget.AdapterView;导入android.widget.Button;导入android.widget.ImageView;导入 android.widget.ListView;导入 android.widget.Toast;导入android.widget.Toolbar;导入 android.widget.ViewFlipper;公共类主页扩展片段 { int pos = 0; ViewFlipper v_flipper; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_home, container, false);返回视图; } @Override public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) { NonScrollListView listView = (NonScrollListView) view.findViewById(R.id.listview); customAdapter customAdapter = new customAdapter(getActivity()); listView.setAdapter(customAdapter); listView.setFocusable(false); customAdapter.notifyDataSetChanged(); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Log.d("listview click", "onItemClick:"); /* FragmentTransaction fr = getFragmentManager().beginTransaction().replace(R.id.fragment_container, new productdisplay()); fr.putExtra("Position", position); fr.addToBackStack("tag"); fr.commit() ;*/ Intent intent = new Intent(getActivity(), productdisplay.class); intent.putExtra("Position", position); startActivity(intent); } }); //图像滑块 int images[] = {R.drawable.slide1, R.drawable.slide2, R.drawable.slide3}; v_flipper = view.findViewById(R.id.v_flipper); for (int image : images) { FlipperImages(image); } } 私人无效翻转器图像(int image){ ImageView imageView = new ImageView(getActivity()); imageView.setBackgroundResource(图像); v_flipper.addView(imageView); v_flipper.setFlipInterval(4000); v_flipper.setAutoStart(true); v_flipper.setInAnimation(getActivity(), android.R.anim.slide_in_left); v_flipper.setOutAnimation(getActivity(), android.R.anim.slide_out_right); } } 注意:我在这里使用了 Fragments。


N
Nguyen Quang Anh

好的,这是我的答案。固定 ListView 高度的方法已经足够封闭,但并不完美。如果大多数物品的高度相同,那效果很好。但如果不是这样,那就有大问题了。我试了很多次,当我把listItem.getMeasureHeight和listItem.getMeasuerWidth的值放到日志中时,我看到宽度值变化很大,这不是预期的,因为同一个ListView中的所有项目都应该具有相同的宽度。还有错误:

有些人使用了 measure(0 ,0),这实际上使视图在两个方向和宽度上都不受约束。有的尝试获取listView的宽度,然后返回0,没有意义。

当我进一步阅读 android 如何渲染视图时,我意识到所有这些尝试都无法达到我搜索的答案,除非这些函数在视图渲染后运行。

这次我在想要固定高度的ListView上使用getViewTreeObserver,然后addOnGlobalLayoutListener。在这个方法中,我声明了一个新的 OnGlobalLayoutListener,这一次,getWidth 返回 ListView 的实际宽度。

private void getLayoutWidth(final ListView lv, final int pad){
        //final ArrayList<Integer> width = new ArrayList<Integer>();

        ViewTreeObserver vto = lv.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                lv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                //width.add(layout.getMeasuredWidth());
                int width = lv.getMeasuredWidth();
                ListUtils.setDynamicHeight(lv, width, pad);
            }
        });
    }

public static class ListUtils {
        //private static final int UNBOUNDED = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        public static void setDynamicHeight(ListView mListView, int width, int pad) {
            ListAdapter mListAdapter = mListView.getAdapter();
            mListView.getParent();
            if (mListAdapter == null) {
                // when adapter is null
                return;
            }
            int height = 0;


            int desiredWidth = View.MeasureSpec.makeMeasureSpec(width - 2*pad, View.MeasureSpec.EXACTLY);
            for (int i = 0; i < mListAdapter.getCount(); i++) {
                View listItem = mListAdapter.getView(i, null, mListView);

                listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
                //listItem.measure(UNBOUNDED, UNBOUNDED);
                height += listItem.getMeasuredHeight() + 2*pad;
                Log.v("ViewHeight :", mListAdapter.getClass().toString() + " " + listItem.getMeasuredHeight() + "--" + listItem.getMeasuredWidth());
            }
            ViewGroup.LayoutParams params = mListView.getLayoutParams();
            params.height = height + (mListView.getDividerHeight() * (mListAdapter.getCount() - 1));
            mListView.setLayoutParams(params);
            mListView.requestLayout();
        }
    }

value pad 是我在 ListView 布局中设置的填充。


a
atablash

如果出于某种原因您不想使用 addHeaderViewaddFooterView,例如当您有多个列表时,最好重用 ListAdapter 来填充一个简单的 LinearLayout,这样就没有滚动功能。

如果您已经有一个从 ListFragment 派生的完整片段,并希望将其转换为具有简单 LinearLayout 的类似片段而不滚动(例如,将其放入 ScrollView),您可以实现这样的适配器片段:

// converts listFragment to linearLayout (no scrolling)
// please call init() after fragment is inflated to set listFragment to convert
public class ListAsArrayFragment extends Fragment {
    public ListAsArrayFragment() {}

    private ListFragment mListFragment;
    private LinearLayout mRootView;


    // please call me!
    public void init(Activity activity, ListFragment listFragment){
        mListFragment = listFragment;
        mListFragment.onAttach(activity);
        mListFragment.getListAdapter().registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                refreshView();
            }
        });
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // create an empty vertical LinearLayout as the root view of this fragment
        mRootView = new LinearLayout(getActivity());
        mRootView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        mRootView.setOrientation(LinearLayout.VERTICAL);
        return mRootView;
    }

    // reusing views for performance
    // todo: support for more than one view type
    ArrayList<View> mViewsToReuse = new ArrayList<>();
    ArrayList<View> mCurrentViews = new ArrayList<>();

    // re-add views to linearLayout
    void refreshView(){

        // remove old views from linearLayout and move them to mViewsToReuse
        mRootView.removeAllViews();
        mViewsToReuse.addAll(mCurrentViews);
        mCurrentViews.clear();

        // create new views
        for(int i=0; i<mListFragment.getListAdapter().getCount(); ++i){
            View viewToReuse = null;
            if(!mViewsToReuse.isEmpty()){
                viewToReuse = mViewsToReuse.get(mViewsToReuse.size()-1);
                mViewsToReuse.remove(mViewsToReuse.size()-1);
            }
            final View view = mListFragment.getListAdapter().getView(i, viewToReuse, mRootView);
            ViewGroup.LayoutParams oldParams = view.getLayoutParams();
            view.setLayoutParams(new LinearLayout.LayoutParams(oldParams.width, oldParams.height));
            final int finalI = i;

            // pass click events to listFragment
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListFragment.onListItemClick(null, view, finalI, finalI);
                }
            });
            mRootView.addView(view);
            mCurrentViews.add(view);
        }
    }

您可能还想根据需要将 onCreateonPauseonResume 等转发到原始片段或尝试继承而不是组合(但覆盖某些方法,因此原始片段实际上并未附加到布局层次结构) ;但我想尽可能地隔离原始片段,因为我们只需要提取它的ListAdapter。如果您在 onAttach 中调用原始片段的 setListAdapter,那可能就足够了。

以下是如何使用 ListAsArrayFragment 来包含 OriginalListFragment 而无需滚动。在父 Activity 的 onCreate 中:

ListAsArrayFragment fragment = (ListAsArrayFragment) getFragmentManager().findFragmentById(R.id.someFragmentId);
OriginalListFragment originalFragment = new OriginalListFragment();
fragment.init(this, originalFragment);

// now access originalFragment.getListAdapter() to modify list entries
// and remember to call notifyDatasetChanged()

q
qwerty

找到了scrollview -> viewpager -> FragmentPagerAdapter -> fragment -> 动态列表视图的解决方案,但我不是作者。

public class CustomPager extends ViewPager {

    private View mCurrentView;

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

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

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mCurrentView == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        int height = 0;
        mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = mCurrentView.getMeasuredHeight();
        if (h > height) height = h;
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void measureCurrentView(View currentView) {
        mCurrentView = currentView;
        this.post(new Runnable() {
            @Override
            public void run() {
                requestLayout();
            }
        });
    }

    public int measureFragment(View view) {
        if (view == null)
            return 0;

        view.measure(0, 0);
        return view.getMeasuredHeight();
    }
}


public class MyPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    private int mCurrentPosition = -1;


    public MyPagerAdapter(FragmentManager fm) {
        super(fm);//or u can set them separately, but dont forget to call notifyDataSetChanged()
        this.fragments = new ArrayList<Fragment>();
        fragments.add(new FirstFragment());
        fragments.add(new SecondFragment());
        fragments.add(new ThirdFragment());
        fragments.add(new FourthFragment());
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        if (position != mCurrentPosition) {
            Fragment fragment = (Fragment) object;
            CustomPager pager = (CustomPager) container;
            if (fragment != null && fragment.getView() != null) {
                mCurrentPosition = position;
                pager.measureCurrentView(fragment.getView());
            }
        }
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

片段布局可以是任何东西

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:orientation="vertical"
    android:layout_height="match_parent" tools:context="nevet.me.wcviewpagersample.FirstFragment">


    <ListView
        android:id="@+id/lv1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#991199"/>
</LinearLayout>

然后在某个地方

 lv = (ListView) view.findViewById(R.id.lv1);
        lv.setAdapter(arrayAdapter);
        setListViewHeightBasedOnChildren(lv);
    }

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        int totalHeight = 0;
        View view = null;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            view = listAdapter.getView(i, view, listView);
            if (i == 0)
                view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth,
                        LinearLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }

j
jww

在 xml 中:

<com.example.util.NestedListView
                    android:layout_marginTop="10dp"
                    android:id="@+id/listview"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:divider="@null"

                    android:layout_below="@+id/rl_delivery_type" >
                </com.example.util.NestedListView>

在 Java 中:

public class NestedListView extends ListView implements View.OnTouchListener, AbsListView.OnScrollListener {

    private int listViewTouchAction;
    private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;

    public NestedListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        listViewTouchAction = -1;
        setOnScrollListener(this);
        setOnTouchListener(this);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {
        if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
            if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
                scrollBy(0, -1);
            }
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int newHeight = 0;
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode != MeasureSpec.EXACTLY) {
            ListAdapter listAdapter = getAdapter();
            if (listAdapter != null && !listAdapter.isEmpty()) {
                int listPosition = 0;
                for (listPosition = 0; listPosition < listAdapter.getCount()
                        && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
                    View listItem = listAdapter.getView(listPosition, null, this);
                    //now it will not throw a NPE if listItem is a ViewGroup instance
                    if (listItem instanceof ViewGroup) {
                        listItem.setLayoutParams(new LayoutParams(
                                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                    }
                    listItem.measure(widthMeasureSpec, heightMeasureSpec);
                    newHeight += listItem.getMeasuredHeight();
                }
                newHeight += getDividerHeight() * listPosition;
            }
            if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
                if (newHeight > heightSize) {
                    newHeight = heightSize;
                }
            }
        } else {
            newHeight = getMeasuredHeight();
        }
        setMeasuredDimension(getMeasuredWidth(), newHeight);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
            if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
                scrollBy(0, 1);
            }
        }
        return false;
    }
}

f
farshid bohlooli

将适配器分配给列表视图后只需调用此函数

public static void setListViewHeightBasedOnChildren
            (ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        int totalHeight = 0;
        View view = null;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            view = listAdapter.getView(i, view, listView);
            if (i == 0) view.setLayoutParams(new
                    ViewGroup.LayoutParams(desiredWidth,
                    ViewGroup.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();

        params.height = totalHeight + (listView.getDividerHeight() *
                (listAdapter.getCount() - 1));

        listView.setLayoutParams(params);
        listView.requestLayout();
    } 

S
S Kumar

最好的解决方案是在子滚动中添加此 android:nestedScrollingEnabled="true" 属性,例如我已将此属性插入到我的 ListView 中,它是 ScrollView 的子级。我希望这个方法对你有用:-

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    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">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:gravity="center_horizontal">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="TextView"/>
        <ListView
            android:nestedScrollingEnabled="true" //add this only
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="300dp"/>
    </LinearLayout>
</ScrollView>

带有滚动视图的列表视图的最佳解决方案你应该是最好的答案......谢谢
M
Mohammad No3ratii

如果您在 ScrollView 内的 listView 中显示所有项目,请使用此代码

val params: ViewGroup.LayoutParams = listView!!.layoutParams
params.height = useitemsList.size * 200 //add static height 
listView!!.layoutParams = params
listView!!.requestLayout()

S
Shibu Tamang

只需在父滚动视图内的列表视图高度属性中设置所需高度的值。它将与其他父子项一起滚动。


M
Manuel Schmitzberger

这对我有用(link1link2):

您创建不可滚动的自定义 ListView public class NonScrollListView extends ListView { public NonScrollListView(Context context) { super(context); } public NonScrollListView(上下文上下文,AttributeSet attrs){超级(上下文,attrs); } public NonScrollListView(上下文上下文,AttributeSet attrs,int defStyle){ super(context,attrs,defStyle); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightMeasureSpec_custom = View.MeasureSpec.makeMeasureSpec( Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom); ViewGroup.LayoutParams 参数 = getLayoutParams(); params.height = getMeasuredHeight(); } }

在你的布局文件中 < RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" >

创建 customListview 的对象,而不是 ListView,例如: NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);