【问题标题】:CardView layout_width="match_parent" does not match parent RecyclerView widthCardView layout_width="match_parent" 与父 RecyclerView 宽度不匹配
【发布时间】:2014-08-21 15:06:24
【问题描述】:

我有一个片段,其中包含一个 RecyclerView,layout_width="match_parent":

<android.support.v7.widget.RecyclerView 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"
    android:layout_gravity="center"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity$PlaceholderFragment" />

RecyclerView 中的项目也是 CardView,layout_width="match_parent":

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    card_view:cardCornerRadius="4dp">

    <TextView
        android:layout_gravity="center"
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="match_parent"
        android:textAppearance="?android:textAppearanceLarge"/>
</android.support.v7.widget.CardView>

我将项目视图放大如下:

public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        CardView v = (CardView) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_listitem, null, true);

        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

但是当我运行应用程序时,CardView 呈现为 wrap_content 如下所示:

请注意,这是在模拟器上运行的,而不是真实设备。

是我做错了什么,还是一个错误?

【问题讨论】:

  • 膨胀 CardView 时,是否为父视图提供了 true 参数?
  • 嗨@NiekHaarman,请查看编辑。我添加了膨胀代码。是的,我已经传递了真正的参数。

标签: android android-layout android-5.0-lollipop android-recyclerview android-cardview


【解决方案1】:

inflate 的文档:

从指定的 xml 资源扩充新的视图层次结构。投掷 InflateException 如果有错误。

Parameters
resource 要加载的 XML 布局资源的 ID(例如, R.layout.main_page) 根
view 成为 生成的层次结构(如果 attachToRoot 为真),或者只是一个 提供一组 LayoutParams 值的对象 返回的层次结构(如果 attachToRoot 为 false。)
attachToRoot 是否 膨胀的层次结构应该附加到根参数吗?如果 false,root 仅用于创建正确的子类 XML 中根视图的 LayoutParams。返回根视图 膨胀的等级制度。如果提供了 root 并且 attachToRoot 为真, 这是根;否则它是膨胀的 XML 文件的根。

这里重要的是提供true,但提供父:

LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_listitem, parent, false);

提供parent 视图可以让inflater 知道要使用什么布局参数。提供false 参数告诉它 将它附加到父级。这就是RecyclerView 将为您做的事情。

【讨论】:

  • 该解决方案对我不起作用,因为 ListView 的 layout_widthwrap_content。这很奇怪,因为这不应该影响列表视图!所以我的理解是,当您向 layoutinflater 提供 false 作为参数时,ListView 会将列表项添加到 ListView 中,其布局参数与 ListView 本身匹配! :0
  • 你能不能多贴一点代码,因为我想我也在做同样的事情,但实际上它不起作用
  • 我夸大了你的建议,而 match_parent 对我不起作用。
  • 我认为正确的理解是当你将attachToRoot设置为false时,你需要提供一个定义了LayoutParams值的对象。该对象不一定是父对象。 “......只是一个对象,它为返回的层次结构的根提供一组 LayoutParams 值(如果 attachToRoot 为假。)......”但我不明白为什么 inflater 无法读取 CardView 中定义但需要的 LayoutParams另一个对象参数通知它?
  • 如果我使用自定义视图,如何处理?我的意思是ViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }
【解决方案2】:

使用 RelativeLayout 作为 CardView 的直接父级。

<RelativeLayout 
    android:layout_width="match_parent" ... >
    <CardView 
        android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>

【讨论】:

  • 是的,这似乎也对我有用。我正在使用 LinearLayout 并且上面的建议不起作用,因为我已经在这样做了(即不附加到根,但提供父级)。您必须同时执行 RelativeLayout + 不附加父级,但提供一个。
  • 它对我有用,但我不知道为什么这样做可以解决问题。谁能解释一下原因?
  • 好久不见,android x 正在生产中,bug 还没有修复!
  • 最简单的方法。
  • 我遇到了类似的问题,这对我来说可以纠正我的卡片视图的宽度,但我在高度方面遇到了类似的问题?你能不能也给我一些建议?
【解决方案3】:

这对我有用,

 View viewHolder= LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item, null, false);
 viewHolder.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
 return new ViewOffersHolder(viewHolder);

【讨论】:

    【解决方案4】:

    我的做法是:

    View view = mInflater.inflate(R.layout.row_cardview, null, true);
                WindowManager windowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
                int width = windowManager.getDefaultDisplay().getWidth();
                view.setLayoutParams(new RecyclerView.LayoutParams(width, RecyclerView.LayoutParams.MATCH_PARENT));
    

    解释: 获得卡片视图后,在 onCreateViewHolde 中获取屏幕宽度,然后为卡片视图设置相应的布局参数。

    【讨论】:

    • 请稍微改进一下。它基本上说“试试这个”
    • 添加说明。请检查,如果需要任何进一步的帮助,请在此处发表评论。
    【解决方案5】:

    这似乎已在'com.android.support:recyclerview-v7:23.2.1' 中修复

    更多讨论请参见:RecyclerView wrap_content

    【讨论】:

      【解决方案6】:

      只需设置新的布局参数

      view.setLayoutParams(new RecyclerView.LayoutParams(
          RecyclerView.LayoutParams.MATCH_PARENT,
          RecyclerView.LayoutParams.WRAP_CONTENT
      ));
      

      【讨论】:

      • 我发现在使用继承自 ConstraintLayout 的自定义视图类时,在 onBindViewHolder() 中执行此操作很有用。
      • 这不是一个好的答案,因为布局设置的边距会受到影响。
      【解决方案7】:

      默认实现强制在默认布局管理器中使用 wrap_content

        @Override
      public LayoutParams generateDefaultLayoutParams() {
          return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                  ViewGroup.LayoutParams.WRAP_CONTENT);
      }
      

      您所要做的就是在您的 LayoutManager 中重写此方法,如下所示:

        @Override
      public LayoutParams generateDefaultLayoutParams() {
          return new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                  ViewGroup.LayoutParams.WRAP_CONTENT);
      }
      

      【讨论】:

        【解决方案8】:

        这对我有用

        View view = inflator.inflate(R.layout.layout_item, ***null***, false);
        

        【讨论】:

          【解决方案9】:

          使用负值的card_view:contentPadding

          <android.support.v7.widget.CardView
              xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:card_view="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              card_view:contentPadding="-4dp"
              card_view:cardElevation="0dp"
              android:layout_height="wrap_content">
          

          它对我有用

          【讨论】:

            【解决方案10】:

            CardView 包裹在一个具有宽度的布局中:match_parent

            【讨论】: