【问题标题】:RecyclerView item width layout_width=“match_parent” does not match parentRecyclerView 项目宽度 layout_width="match_parent" 与父不匹配
【发布时间】:2015-08-25 07:21:31
【问题描述】:

我正在使用 RecyclerView 并且我正在尝试使 RecyclerView 的宽度项 match_parent 因为我正在使用

LinearLayoutManager.HORIZONTAL

 <android.support.v7.widget.RecyclerView
            android:id="@+id/listOffersHits"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

custom_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<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_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:layout_weight="1"
    android:layout_margin="2dp"
    card_view:cardCornerRadius="2dp">
    <ImageView
        android:id="@+id/offerImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        android:background="@drawable/item_selector"
        android:scaleType="fitXY"
        android:src="@drawable/offer"
        />

</android.support.v7.widget.CardView>

布局管理器

   LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL, false);
    listOffersHits.setLayoutManager(linearLayoutManager);

ViewHolder

View view= LayoutInflater.from(parent.getContext())
                .inflate(R.layout.custom_layout, parent, false);
        ViewOffersHolder viewHolder=new ViewOffersHolder(view);
        return viewHolder;

【问题讨论】:

  • @Rami 感谢您的评论,我已经尝试了两种建议的解决方案,但仍然相同。而且我不认为 CardView 的问题,因为我将其更改为 FrameLayout 并且仍然相同。
  • 我找到的最佳解决方案在这里:stackoverflow.com/a/62139337/13588475

标签: android xml android-recyclerview


【解决方案1】:

我解决了这个问题:

1- 获取屏幕尺寸(宽度)。

2- 使 ViewHolder 宽度与屏幕尺寸相同。

如果有人需要,请在我的代码下方。

WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        int width = windowManager.getDefaultDisplay().getWidth();
        int height = windowManager.getDefaultDisplay().getHeight();
        view.setLayoutParams(new RecyclerView.LayoutParams(width, RecyclerView.LayoutParams.MATCH_PARENT));

【讨论】:

  • 或在 kotlin 中,您可以在适配器 onCreateViewHolder 函数中使用 val outMetrics = DisplayMetrics() val display = parent.display display?.getRealMetrics(outMetrics) itemView.layoutParams = RecyclerView.LayoutParams(outMetrics.widthPixels, RecyclerView.LayoutParams.MATCH_PARENT),就在 return 之前
【解决方案2】:

注意:请参阅本文最后的更新。


旧答案:

以下对我有用:

view.getLayoutParams ().width = parentViewGroup.getWidth (); 

,在膨胀视图 'view' 之后。

它基本上采用父级的宽度并将新视图的 layout_width 替换为父级的宽度。

您还可以为 MATCH_PARENT 添加检查,以确保它正确显示,以防您将来将 XML 修改为不同的宽度。就像这样:

    public ViewHolder onCreateViewHolder (ViewGroup parent, int type) {
        View vItem = LayoutInflater.from (parent.getContext ()) 
                             .inflate (R.layout.bookmark_card, parent, false); 
        if (vItem.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT) 
            vItem.getLayoutParams ().width = parent.getWidth (); 
        return new ViewHolder (vItem); 
    } 

只有在此之前宽度为 MATCH_PARENT 时,它才会使其成为父宽度。

编辑:

请注意过度使用此修复程序,因为它的变体导致我出现布局错误。我这样做了:

    public ViewHolder onCreateViewHolder (ViewGroup parent, int type) { 
        View vItem = LayoutInflater.from (parent.getContext ()) 
                             .inflate (R.layout.page_tile, parent, false); 
        if (vItem.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT) 
            vItem.getLayoutParams ().width = parent.getWidth (); 
        if (vItem.getLayoutParams ().height == RecyclerView.LayoutParams.MATCH_PARENT) 
            vItem.getLayoutParams ().height = parent.getHeight (); 
        return new ViewHolder (vItem); 
    } 

这行得通,但是当 RecyclerView 调整大小时,它没有更新宽度和高度。因此,可以应用此修复的两个修复之一:

  1. 检查 RecyclerView 适配器的方向,只对允许滚动的维度执行此 parent.getHeight() 等。
  2. 或者,在ViewHolder的某处,保存原来的'width'和'height',然后在onBindViewHolder()方法中每次都重做这一步。

以下修复似乎有效:

    public ViewHolder onCreateViewHolder (ViewGroup parent, int type) { 
        View vItem = LayoutInflater.from (parent.getContext ()) 
                             .inflate (R.layout.page_tile, parent, false); 
        ViewHolder holder = new ViewHolder (vItem); // Create view holder. 
        holder.vItem = vItem; // Save top-level View. 
        holder.vParent = parent; // Save its parent. 
        ViewGroup.LayoutParams lp = vItem.getLayoutParams (); 
        if (lp != null) { // Save the original width and height from lp: 
            holder.originalWidth = lp.width; 
            holder.originalHeight = lp.height; 
            refreshLayoutParams (holder); // Check for MATCH_PARENT. 
        } else holder.originalHeight = holder.originalWidth = 0; 
        return holder; 
    } 
    public void onBindViewHolder (ViewHolder holder, int position) { 
        ... do work here ... 
        refreshLayoutParams (holder); // Check AGAIN for MATCH_PARENT. 
    } 
    private void refreshLayoutParams (ViewHolder holder) {
        ViewGroup.LayoutParams lp = holder.vItem.getLayoutParams (); 
        View parent = holder.vParent; 
        if (parent == null) return; // Is there a parent to check against? 
        if (lp == null) 
            holder.vItem.setLayoutParams (lp = 
                            new RecyclerView.LayoutParams (holder.originalWidth, holder.originalHeight)); 
        if (holder.originalWidth == RecyclerView.LayoutParams.MATCH_PARENT) 
            lp.width = parent.getWidth (); // Check width. 
        if (holder.originalHeight == RecyclerView.LayoutParams.MATCH_PARENT) 
            lp.height = parent.getHeight (); // Check height. 
    } 

另请注意:如果你在onBindViewHolder()方法中使用这种调整大小的方法,你还需要getAdapter().notifyDataSetChanged()里面的Activity.onSizeChanged()

简而言之,主要思想是:在每个 bind 上检查 MATCH_PARENT,而不仅仅是在创建视图持有者上。这样调整 RecyclerView 的大小也可以。


更新:至少从 RecyclerView v7:23.2.1 开始,他们似乎已经修复了它,因此现在不再需要这些自定义修复。 RecyclerView 本身现在应该可以识别 WRAP_CONTENT 和 MATCH_PARENT 设置。

【讨论】:

  • 这个对我来说效果很好。但是:我没有使用 view.getLayoutParams().width = ...,而是使用 view.setLayoutParams(new LinearLayout.LayoutParams(viewGroup.getWidth(), ViewGroup.LayoutParams.WRAP_CONTENT));反而。原因是 view.getLayoutParams 可能为空(在我的情况下是出于某种奇怪的原因)。
  • @Igor 谢谢。我在上面进行编辑时考虑到了这一点。
【解决方案3】:

在布局中删除它。

android:layout_weight="1"

并再次为适配器中的项目设置布局参数。

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

【讨论】:

  • 我做到了,但没有改变。
【解决方案4】:

调用GridLayoutManager而不是LinearLayoutManager并放一列最简单

来自您的 xml:

<androidx.recyclerview.widget.RecyclerView
        app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
        app:spanCount="1"
...

或者来自 Kotlin:

recyclerView.layoutManager = GridLayoutManager(this,1)

或来自 Java:

recyclerView.setLayoutManager(new GridLayoutManager (this, 1);

【讨论】:

    猜你喜欢
    • 2014-08-21
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    相关资源
    最近更新 更多