RecyclerView不遵守height=wrap_content的高度设置?

5

我有一个聊天屏幕,其中包含两个视图:用于显示之前聊天记录的可循环视图以及一个自定义视图,该自定义视图封装了一个编辑文本、一个发送按钮和另一个可循环视图,让用户选择其他要发送的内容,例如照片等。这个自定义视图被称为“面板”。

因此,我的聊天活动具有以下布局:

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

    <chat.example.app.widget.Panel
        style="@style/PanelStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:id="@+id/panel" />

    <android.support.v7.widget.RecyclerView
        android:background="@android:color/holo_red_dark"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:scrollbars="vertical"
        android:id="@+id/previous_chat"
        android:layout_above="@id/panel"
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

我的“面板”视图具有以下布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white">
    <RelativeLayout
        android:id="@+id/staging_area_root"
        android:layout_gravity="center"
        android:gravity="center"
        android:paddingLeft="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <!-- Chat box and send -->
    </RelativeLayout>
    <!-- THIS GUY IS PROBLEMATIC -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/card_set"
        android:layout_margin="15dp"
        android:layout_below="@id/staging_area_root"
        android:background="@android:color/holo_blue_bright"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>  

问题在于来自Panel的回收视图占据了整个屏幕空间。因此我只看到了有问题的来自Panel类的回收视图。
这两个回收视图都分配了LinearLayoutManager。目前还没有适配器。
我在build.gradle中使用了最新的支持库。
compile 'com.android.support:recyclerview-v7:23.2.0'  

查看最新的 Android 开发者博客文章:

此版本为 LayoutManager API 带来了一项令人兴奋的新功能:自动测量!这使得 RecyclerView 可以根据其内容的大小来调整自身大小。这意味着以前无法使用 WRAP_CONTENT 作为 RecyclerView 尺寸的情况现在可以实现了。您会发现所有内置的 LayoutManagers 现在都支持自动测量。

我有所遗漏吗?

更新1:

我给问题严重的可滚动视图添加了一个没有任何项目的适配器,但仍然没有解决方案。

更新2:
截图:

enter image description here


不要在您的“Panel”上使用android:layout_gravity,而是使用android:layout_alignParentBottomandroid:layout_centerHorizontal。我复制粘贴了您的布局,删除了“Panel”xml,并用其布局xml替换它,在Android Studio的预览中一切看起来都很好。 - Alex Townsend
@AlexTownsend 没有运气。更新一下,我正在使用 alignParentBottom。还没有在这里更新代码。也许这与我的自定义视图创建方式有关? - An SO User
@AlexTownsend,您想要哪个屏幕截图?带有您要求我更改的属性吗? :) - An SO User
@AlexTownsend 完成。蓝色的recyclerview来自Panel - An SO User
@AlexTownsend 这是一个有趣的边缘情况。如果我的回收站中填充了来自服务器的项目,而服务器没有返回任何项目,那该怎么办呢?看起来现在必须添加一个“空”视图 :-/ - An SO User
显示剩余5条评论
1个回答

8

代码片段取自23.2版本的RecyclerView中的onMeasure()调用:

if (mLayout.mAutoMeasure) {
        final int widthMode = MeasureSpec.getMode(widthSpec);
        final int heightMode = MeasureSpec.getMode(heightSpec);
        final boolean skipMeasure = widthMode == MeasureSpec.EXACTLY
                && heightMode == MeasureSpec.EXACTLY;
        mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
        if (skipMeasure || mAdapter == null) {
            return;
        }
        if (mState.mLayoutStep == State.STEP_START) {
            dispatchLayoutStep1();
        }
        // set dimensions in 2nd step. Pre-layout should happen with old dimensions for
        // consistency
        mLayout.setMeasureSpecs(widthSpec, heightSpec);
        mState.mIsMeasuring = true;
        dispatchLayoutStep2();

        // now we can get the width and height from the children.
        mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);

        // if RecyclerView has non-exact width and height and if there is at least one child
        // which also has non-exact width & height, we have to re-measure.
        if (mLayout.shouldMeasureTwice()) {
            mLayout.setMeasureSpecs(
                    MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
            mState.mIsMeasuring = true;
            dispatchLayoutStep2();
            // now we can get the width and height from the children.
            mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
        }
    }

mLayout.setMeasuredDimensionFromChildren() 调用将基于 RecyclerView 的子项大小进行自动测量。这意味着,需要有效的具有一个或多个子项的 RecyclerView.Adapter 才能触发自动测量。


不能刷+1按钮。非常感谢。 :) - An SO User

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接