【问题标题】:Android: wrap_content is not working with ListViewAndroid:wrap_content 不适用于 ListView
【发布时间】:2026-01-31 20:20:02
【问题描述】:

我正在开发安卓系统。我希望我的列表视图水平包装其内容而不是填充所有宽度。 wrap_content 属性不起作用。怎么办?

【问题讨论】:

    标签: android listview


    【解决方案1】:

    为了在ListView中实现wrap_content的高度,我们需要使用CustomListView,即extends我们的原生ListView

    MyListView.java

    public class MyListView extends ListView {
    
        public MyListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyListView(Context context) {
            super(context);
        }
    
        public MyListView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                    MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
        }
    
    }
    

    在您的layout 中使用这样的自定义视图,

    layout.xml

    <com.yourpackagename.MyListView
            ...       
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ... />
    

    【讨论】:

    • 太棒了!当我想在 RecyclerView 中使用 ListView 时为我工作。
    • 这个答案很有用,但是当 ListView 在 RecyclerView 内时,向上滚动似乎有问题。所以真正的解决方案是覆盖 onMeasure 方法。看到这个答案:*.com/a/24186596/1901561
    • 例如,如果第二行大于第一行,则不起作用。
    • 高度很好,宽度怎么样,宽度取全长,如果我把 wrapcontnet 作为宽度不起作用
    • 工作就像一个魅力
    【解决方案2】:

    正如Romain Guy(谷歌工程师致力于UI工具包)在他的帖子中所说的

    通过将宽度设置为wrap_content,您是在告诉 ListView 与其最宽的子视图一样宽。因此,ListView 必须测量其项目并获取它必须在适配器上调用 getView() 的项目。这可能会发生多次,具体取决于布局传递的数量、父布局的行为等。

    因此,如果您将 ListView 的布局宽度或布局高度设置为 wrap_content,ListView 将尝试测量附加到它的每个视图 - 这绝对不是您想要的。

    牢记:始终避免为 ListViews 或 GridViews 设置 wrap_content,有关更多详细信息,请参阅 Google I/O video 谈论 listview 的世界

    【讨论】:

    • 这个建议似乎并不普遍。 ListView/Adapater 组合比人们最初可能意识到的更通用和可扩展,这意味着人们也可能没有意识到将 wrap_content 用于任意数据集的后果。但这并不是说数据集大小固定或有限的情况并不多。在这些情况下,使用 wrap_content 更像是一种判断。
    • 这似乎是 lint 应该警告的 - 但目前没有。
    • 我不知道为什么这个答案被接受:它根本没有回答这个问题。它还模仿了 Romain's Guy 的帖子——这是关于一个完全不同的问题:布局被测量的次数——并指向一个视频,该视频实际上解释了为什么 wrap_content 应该工作,至少对于 3 个列表项,并且“有点为更复杂的列表工作”(以相当大的性能成本)。
    • 直到现在,lint 还没有这样做。本可以让我免于数小时的尝试!
    【解决方案3】:

    可以使用LinearLayout来实现。

    像这个例子一样创建:

    public class LinearLayoutAdapter   {
        LinearLayout linearLayout;
        ArrayList<String>  arrayList 
        private View rootView;
        private static LayoutInflater inflater;
    
        public ChoicesAdapter_(ArrayList<String>  arrayList ,LinearLayout linearLayout)
        {
            this.index =index;
            this.arrayList=arrayList;
            this.linearLayout=linearLayout;
            notifyDataSetChanged();
        }
        private void notifyDataSetChanged() {
            linearLayout.removeAllViews();
            for (int i =0;i<getCount();i++){
                linearLayout.addView(getView(i,null,null));
            }
        }
        public int getCount() {
            return  arrayList.size();
        }
        public Object getItem(int position) {
            return null;
        }
        public long getItemId(int position) {
            return 0;
        }
        public View getView(final int position, View convertView, ViewGroup parent) {
           rootView = inflater.inflate(R.layout.row_list, null);
           TextView  textView = (TextView)rootView.findViewById(R.id.text);    
           textView.setText(arrayList.get(position));
            return rootView;
        }
    }
    

    MainActivity 示例:

    public class MainActivity extends Activity    {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ArrayList<String>  arrayList = new  ArrayList<String>();
            arrayList.add("Accent");
            arrayList.add("Acclaim");
            arrayList.add("Accord");
            arrayList.add("Achieva");
            arrayList.add("Aerio");
            arrayList.add("Aerostar");
            LinearLayout linearLayout = (LinearLayout)findViewById(R.id.linearLayout);
            linearLayoutAdapter= LinearLayoutAdapter(arrayList,linearLayout);
        }
    }
    

    XML 示例:

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:textColor="@color/dark_gray"
        android:background="@color/white"
        android:textSize="20dp"
        android:text=""  />
    

    【讨论】:

    • 是的,你可以这样做,但是你会松散(或有很多事情要实现)listitem 视图的回收系统。它适用于少数项目,但对于少数项目,您可能会考虑不使用列表视图或适配器。
    【解决方案4】:
    I want my list view to wrap its content horizontally and not to fill all the width. 
    

    在列表视图的情况下,您不能提供 wrap_content ,因为如果您只为列表视图提供 wrap_content 前三个项目(行) 将显示其余将是忽略.. 所以不要使用 wrap_content.. 总是使用 fill_parent 或 match_parent 作为列表视图

    对于列表视图的高效设计,您可以查看World of ListView

    【讨论】:

    【解决方案5】:

    我知道我回答这个问题有点太晚了。但在我看来,如果您希望您的 ListView 具有某种 wrap_content 行为,您可以将其开始和结束边距设置为某个静态值。这在我的情况下有效。 如果您担心为各种屏幕尺寸做这件事,那么有一个非常有用的库来处理这种情况。 可扩展的 DP。请在 github 中检查一次。

    【讨论】:

      最近更新 更多