将支持库从“23.1.1”升级到“23.2.1”后,回收站视图项目填满整个回收站视图高度

Recycler view item fill up entire recycler view height after upgrading support library from "23.1.1" to "23.2.1"

以前,我使用以下旧支持库“23.1.1”。

compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:support-v4:23.1.1'
compile 'com.android.support:preference-v7:23.1.1'
compile 'com.android.support:preference-v14:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'

效果很好。这是我的 RecyclerView 的样子

现在,由于修复了一些错误,我希望迁移到“23.2.1”。

compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:support-v4:23.2.1'
compile 'com.android.support:preference-v7:23.2.1'
compile 'com.android.support:preference-v14:23.2.1'
compile 'com.android.support:design:23.2.1'
compile 'com.android.support:recyclerview-v7:23.2.1'

然而,突然之间,我所有的 RecyclerView 项目,似乎填满了 RecyclerView 整个高度。

这是我的布局文件的代码片段:https://gist.github.com/yccheok/241a0d38d56305a1be24d09b54eb1600

真正让我困惑的是,尽管我在回收站视图项目布局中使用了 "wrap_content",但它并没有按预期工作。

我没有为我的 RecyclerView 使用任何自定义布局管理器。

http://developer.android.com/tools/support-library/index.html开始,我发现这次23.2.1对RecyclerView做了很多改动。

我最怀疑的是 https://code.google.com/p/android/issues/detail?id=201856 ,因为它涉及更改 各种测量规范方法

到目前为止,我尝试用一​​个简单的 RecyclerView 项目重现问题,使用 23.2.1 但失败了!它没有 "item fills up the RecyclerView entire height" 问题。我的猜测是,我的简单项目没有模拟我的生产项目的复杂布局结构。我的生产项目具有以下布局

<Activity>
    <Fragment>
        <View Pager>
            <Fragment>
                <RecyclerView />
            </Fragment>
        </View Pager>
    </Fragment>
</Activity>

调试了几个小时后,我仍然找不到这个问题的根本原因,有什么提示吗?

谢谢。

我试过的

我曾尝试改变 RecyclerView

来自

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

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

一开始看起来不错。但是,当您执行滚动时,事情不会按预期工作:https://www.youtube.com/watch?v=U2EChFn6WkI

更新:我终于找到了根本原因

是我这边的错误!由于我需要为最后一行项目设置不同的边距,因此这是我的适配器代码。

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    final List<TransactionSummary> transactionSummaries = buyArray.transactionSummaries;

    if (position == transactionSummaries.size() - 1) {
        holder.itemView.setLayoutParams(lastLayoutParams);
    } else {
        holder.itemView.setLayoutParams(normalLayoutParams);
    }

不幸的是,lastLayoutParamsnormalLayoutParams 被初始化为

    normalLayoutParams = new LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.MATCH_PARENT,
        LinearLayout.LayoutParams.MATCH_PARENT
    );

    lastLayoutParams = new LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.MATCH_PARENT,
        LinearLayout.LayoutParams.MATCH_PARENT
    );

使用LinearLayout.LayoutParams.WRAP_CONTENT解决问题。

我遇到了类似的问题。最终是回收商不是问题所在。检查您的 CardView 项目测量是否转换为如下所示:

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

如果您不使用 CardView,请确保您在适配器中用于视图的元素具有 android:layout_height="wrap_content" 而不是 match_parent

如果这不起作用,您可以为视图项添加另一个属性设置 minHeightmaxHeight

我认为这是有问题的行:

<View   android:layout_width="1px"
            android:layout_height="match_parent"    <!--change this to wrap_content-->
            android:background="?attr/buyPortfolioSeperatorBackground"
            android:layout_marginRight="5dp"
            android:layout_marginLeft="5dp" />

您的布局项中有 2 个位置 layout_height="match_parent"。您应该将它们都更改为 wrap_content.

更新

您似乎正在为 Adapter 中的 View 更新 LayoutParam

可以这么说,因为在您开始滚动之前,您的 UI 看起来绝对没问题。这意味着您的 XML 是正确的,因为它在您的 XML 布局文件中定义。

它在滚动开始后发生变化,这意味着您的 onBindViewHolder 实现中存在逻辑错误。这就是为什么向下滚动时出现错误,然后向上滚动时错误仍然存​​在的原因。

旧答案

你的问题是你的分流器出了问题:

<View
    android:layout_width="1px"
    android:layout_height="match_parent"
    android:background="?attr/buyPortfolioSeperatorBackground"
    android:layout_marginRight="5dp"
    android:layout_marginLeft="5dp" />

出于测试目的,将其设置为:

<View
    android:layout_width="1px"
    android:layout_height="30dp"
    android:background="?attr/buyPortfolioSeperatorBackground"
    android:layout_marginRight="5dp"
    android:layout_marginLeft="5dp" />

确保两个都改了!

好消息:

我可以向您指出更改 RecyclerView 行为的确切版本:这不是 23.2.1 中的更改,而是 23.2.0 (February 2016) 中的更改。更具体地说:

RecyclerView.LayoutManager no longer ignores some RecyclerView.LayoutParams settings, such as MATCH_PARENT in the scroll direction.

Note: These lifted restrictions may cause unexpected behavior in your layouts. Make sure you specify the correct layout parameters.

确实,如果您启动 23.2.0 库,您会看到相同的行为。在您的情况下,该行为可以简化为:

现在,当 RecyclerView 的子级 android:layout_x="match_parent" 时,这将影响 RecyclerView 的 android:layout_x,而在 23.1.1 和更早版本中并非如此。

坏消息:

即使我 99% 确定这就是你的问题背后的原因,我仍然看不出你的代码有问题。实际上,我已经使用您的 XML 结构(仅更改 color/background 参数)和 LinearLayoutManager 设置了一个 RecyclerView,它在 23.2.1 中按预期工作。如果您想执行完整性检查,我可以分享我的实现。

你应该仔细检查你的适配器 implementation/manipulation 即使它被拉得太长了。

回收视图的高度只能是"wrap_content"。如果单元格的大小增加,回收视图将处理高度。

buy_portfolio_fragment.xml

 <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/buyPortfolioListViewBackground"
        android:requiresFadingEdge="none"
        android:scrollbars="vertical"
        android:paddingTop="@dimen/default_tab_layout_height"
        android:clipToPadding="false" />

只需将 row_layout 高度设为 wrap_content 所以所有项目只需要行实际高度space。

要修复此错误 row_layout 应该 fixedwrap_content!我也有这个问题,刚刚意识到 row_layout 的高度是 match_parent.