以编程方式设置RecyclerView的顶部填充不起作用?

时间:2017-07-20 07:23:09

标签: android android-layout padding

我有RecyclerView,它在屏幕上显示一些项目列表。布局如下:

 <RelativeLayout
        android:id="@+id/parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/top_layout">

        <RelativeLayout
            android:id="@+id/top_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true">

            <TextView
                android:id="@+id/tv1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textMultiLine"
                android:layout_alignParentTop="true"
                android:background="@android:color/holo_blue_light" />

            <TextView
                android:id="@+id/tv2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv1"
                android:inputType="textMultiLine"
                android:background="@android:color/holo_blue_light" />
        </RelativeLayout>


        <android.support.v7.widget.RecyclerView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentTop="true"
            android:clipToPadding="false"
            android:scrollbars="vertical" />

    </RelativeLayout>

在上面的布局tv1&amp; tv2有一些信息需要显示,它可能是单行或多行,因此不能给它们一个固定高度因此与它们的父项一起 - &gt; top_view tv1tv2都有高度作为换行内容。

我想要top_view高度的顶部填充。我正在以编程方式执行以下操作:

top_view = (RelativeLayout) findViewById(R.id.top_view );
list = (RecyclerView) findViewById(R.id.list);
list.setPadding(list.getPaddingLeft(),
                top_view.getHeight(),
                list.getPaddingRight(),
                list.getPaddingBottom());

但是上面的代码没有任何效果,如果我给了RecyclerView硬编码的top-padding android:paddingTop="100dp"它可以工作,但是我不能给出硬编码值,因为它依赖于{{1 }}。

top_view置于list之下的另一件事对我来说不起作用,因为我对此填充有一些其他要求。

那么为什么这个以编程方式设置topPadding不起作用?

4 个答案:

答案 0 :(得分:1)

您在RecyclerView(除适配器之外)操纵视图的方式是ItemDecoration

由于您要在列表中添加topPadding,因此只会影响第一项,因此请按照以下步骤创建自定义RecyclerView.ItemDecoration

public class PaddingTopItemDecoration extends RecyclerView.ItemDecoration {
    private final int size;

    public PaddingTopItemDecoration(int size) {
        this.size = size;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.top += size;
        }
    }
}

然后将其添加到您的RecylerView

// Insert your own top padding value
list.addItemDecoration(new PaddingTopItemDecoration(value));

答案 1 :(得分:0)

top_view.getHeight()将导致0.视图尚未绘制。

你可以试试这段代码。此时将设置高度。

@Override
public void onWindowFocusChanged (boolean hasFocus) {
        // the height will be set at this point

        list.setPadding(list.getPaddingLeft(),
            top_view.getHeight(),
            list.getPaddingRight(),
            list.getPaddingBottom());
}

答案 2 :(得分:0)

通常,使用

top_view.getMeasuredHeight() 

而不是

top_view.getHeight().

在这种情况下,请使用ViewTreeObserver。它会等待您绘制布局,以便您的高度不会返回0(就像绘制布局之前一样)。

parent = (RelativeLayout) findViewById(R.id.parent);

ViewTreeObserver vto = parent.getViewTreeObserver();
        if (vto.isAlive()) {
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    //Perform your actions here
                    list.setPadding(list.getPaddingLeft(),
                    top_view.getMeasuredHeight(),
                    list.getPaddingRight(),
                    list.getPaddingBottom());

                    //Remove observer after use
                    parent.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                }
            });
        }

答案 3 :(得分:0)

对于我的项目,我使用了这里存在的类

https://realm.io/docs/swift/latest/#object-notifications

这是一个非常简单的类,可以让你定义:

-top padding

-bottom padding

- 元素之间的填充

可以像这样使用

//if you want padding between elements 
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.addItemDecoration(new SpaceItemDecoration(5));

//if you want padding between elements + top and bottom padding 
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.addItemDecoration(new SpaceItemDecoration(5,true,true));

请记住,示例中的5是像素,如果您想要DP,则可以使用此方法将其从DP更改为像素(这是我在util类中使用的众多方法之一)

private static float cachedDpToPixelRatio = -1;

    public static float dpToPixels(Context context, int valueInDp) {
        if (cachedDpToPixelRatio == -1) {
            cachedDpToPixelRatio = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, context.getResources().getDisplayMetrics());

        }

        return cachedDpToPixelRatio * valueInDp;

    }