【问题标题】:Force RecyclerView to bottom of page in layout在布局中强制 RecyclerView 到页面底部
【发布时间】:2015-05-01 07:45:27
【问题描述】:

我有一个由ImageViewRecyclerView 组成的页面。 RecyclerView 包含少量项目(目前为三个),仅占我测试设备屏幕的四分之一左右。然而,尽管尝试了许多布局选项,我仍无法让 RecyclerView 有效地包装其内容并占用包含这三行所需的足够空间,并将其余空间留给我的 ImageView

为了帮助说明我的意思,我画了两张图。第一个显示我想要发生的事情,第二个显示正在发生的事情:

到目前为止,我已经尝试了几种不同的 RelativeLayout 组合 - 例如,我将设置 RecyclerViewlayout:align_ParentBottom 和第二个 RelativeLayout 包含 ImageViewlayout:alignComponent 以便它的底部匹配 RecyclerView 顶部(这通常会拖动 ImageView 布局,以便它填充任何剩余空间,这是我想要发生的。)

RecyclerView 尽管它只包含几行,但它一直占据它所能占用的所有空间。我目前的“解决方案”是将所有内容放在LinearLayout 中,并将gravity 设置为RecyclerView,但这并不理想,因为在不同的模拟器上它不会与屏幕底部完全对齐,而在其他情况下,空间不足,RecyclerView 变为可滚动。

提前感谢任何人提供的任何帮助和建议。

【问题讨论】:

    标签: java android xml android-layout


    【解决方案1】:

    非常感谢所有做出贡献的人,但我在layout 文件之外找到了一个编程解决方案。如果其他人正在寻找解决此问题的方法,我找到了一个here

    似乎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);
            }
        }
    }
    

    再次感谢。

    【讨论】:

      【解决方案2】:

      将两者放在一个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 留下任何空间。
      • 抱歉,在使用 TextViews 进行测试时,它似乎对我有用。你试过了吗?
      • 是的,我在 Nexus 7 中对其进行了测试。它仅在我想将 RecyclerView 放在 ImageView 之上时才有效。如果我这样做,那么布局是正确的。但是,如果反过来,在页面底部使用RecyclerView(如我所愿),那么RecyclerView(不是ImageView,我很抱歉)占据了所有空间并且没有为@987654329留下任何空间@.
      【解决方案3】:

      我能想到的唯一解决方案是使用布局权重。为图像指定屏幕的 70%,为 Recyclerview 指定 30%,因为您说您只有 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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-17
        • 1970-01-01
        • 1970-01-01
        • 2021-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多