在布局中强制将RecyclerView放置在页面底部

3
我有一个页面,由一个 ImageView 和一个 RecyclerView 组成。RecyclerView 中只有少量项目(目前只有三个),并且仅占测试设备屏幕的约四分之一。然而,尽管我尝试了许多布局选项,我仍无法使 RecyclerView 有效地包装其内容,并占用足够的空间来容纳这三行,同时留出其余空间给我的 ImageView。
为了帮助说明我的意思,我画了两张图。第一个显示了我想要发生的事情,第二个则是正在发生的情况:
(插入图片)
到目前为止,我已经尝试了几种不同的 RelativeLayout 组合 - 例如,我将 RecyclerView 设置为 layout:align_ParentBottom,将包含 ImageView 的第二个 RelativeLayout 设置为 layout:alignComponent,以便它的底部与 RecyclerView 顶部相匹配(这通常会拖动 ImageView 布局,以便它填充任何剩余空间,这就是我想要发生的事情)。
但 RecyclerView 只是继续占用所有可用的空间,即使它只包含少量行。我目前的“解决方案”是将所有内容放在 LinearLayout 中,并将 RecyclerView 的 gravity 设定为较小值,但这并不理想,因为在不同的模拟器中,它无法完全与屏幕底部对齐,在其他模拟器中没有足够的空间,RecyclerView 就会变得可滚动。
感谢任何人能提供的帮助和建议。
3个回答

3
感谢所有贡献者,但我已经在`layout`文件之外找到了一个程序化的解决方案。如果有人正在寻找此问题的解决方案,可以在这里找到答案。
目前似乎存在`RecyclerView`无法包裹内容的问题。解决方案是构建一个扩展`LinearLayoutManager`的自定义类。我在下面发布了适用于我的解决方案 - 其中大部分内容复制粘贴自我引用链接中给出的答案。唯一的小问题是它没有考虑装饰添加的额外空间,这就是为什么我必须对代码末尾附近的以下行进行微调的原因:
//I added the =2 at the end.    
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin + 2;

以下是完整的代码:

public class HomeLinearLayoutManager extends LinearLayoutManager{

    HomeLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    private int[] mMeasuredDimension = new int[2];

    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                          int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);
        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);
        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            measureScrapChild(recycler, i,
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);

            if (getOrientation() == HORIZONTAL) {
                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }
        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        setMeasuredDimension(width, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        if (view != null) {
            RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
            int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                    getPaddingLeft() + getPaddingRight(), p.width);
            int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                    getPaddingTop() + getPaddingBottom(), p.height);
            view.measure(childWidthSpec, childHeightSpec);
            measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
            measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin + 2;
            recycler.recycleView(view);
        }
    }
}

再次感谢您。
Thank again.

0
将两个元素放入RelativeLayout中,并使ImageView填充父容器:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">
<RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"/>
<ImageView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@id/recyclerView"
    />
</RelativeLayout>

编辑:不小心写成了TextView,已修正。


谢谢您的建议,但在这种情况下,ImageView 只是占据了所有空间,没有留给 RecyclerView - PPartisan
抱歉,当我使用TextView进行测试时,它似乎对我有效。你试过了吗? - dulleh
是的,我在Nexus 7上进行了测试。只有当我想把“RecyclerView”放在“ImageView”的顶部时它才有效。如果我这样做,那么布局就是正确的。然而,如果是另一种情况,即“RecyclerView”在页面底部(正如我所希望的那样),那么“RecyclerView”(而不是“ImageView”,我很抱歉)将占据所有空间,不留给“ImageView”。 - PPartisan

0
我能想到的唯一解决方案是使用布局权重。将屏幕的70%指定为图像,30%指定为Recyclerview,因为您说您只有3行。使用adjustViewByBounds确保图像的纵横比得以保持。
我的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
    <ImageView
        android:src="@drawable/ic_round_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:layout_weight=".9"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight=".1"/>
</LinearLayout>

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