从RecyclerView

时间:2017-05-05 07:03:41

标签: android android-recyclerview

我有一个类可以将HeaderView添加到 RecyclerView 。它正在工作,但在视图的顶部添加了额外的不必要的空间。以下是代码段。我该如何删除这个空间?

enter image description here

public class HeaderDecoration extends RecyclerView.ItemDecoration {

private final View mView;
private final boolean mHorizontal;
private final float mParallax;
private final float mShadowSize;
private final int mColumns;
private final Paint mShadowPaint;

public HeaderDecoration(View view, boolean scrollsHorizontally, float parallax, float shadowSize, int columns) {
    mView = view;
    mHorizontal = scrollsHorizontally;
    mParallax = parallax;
    mShadowSize = shadowSize;
    mColumns = columns;

    if (mShadowSize > 0) {
        mShadowPaint = new Paint();
        mShadowPaint.setShader(mHorizontal ?
                new LinearGradient(mShadowSize, 0, 0, 0,
                        new int[]{Color.argb(55, 0, 0, 0), Color.argb(55, 0, 0, 0), Color.argb(3, 0, 0, 0)},
                        new float[]{0f, .5f, 1f},
                        Shader.TileMode.CLAMP) :
                new LinearGradient(0, mShadowSize, 0, 0,
                        new int[]{Color.argb(55, 0, 0, 0), Color.argb(55, 0, 0, 0), Color.argb(3, 0, 0, 0)},
                        new float[]{0f, .5f, 1f},
                        Shader.TileMode.CLAMP));
    } else {
        mShadowPaint = null;
    }
}

public static Builder with(Context context) {
    return new Builder(context);
}

public static Builder with(RecyclerView recyclerView) {
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    if (layoutManager instanceof GridLayoutManager) {
        GridLayoutManager manager = (GridLayoutManager) layoutManager;
        return new Builder(recyclerView.getContext(), manager.getSpanCount());
    } else if (layoutManager instanceof LinearLayoutManager) {
        LinearLayoutManager manager = (LinearLayoutManager) layoutManager;
        return new Builder(recyclerView.getContext(), manager.getOrientation() == LinearLayoutManager.HORIZONTAL);
    } else if (layoutManager instanceof StaggeredGridLayoutManager) {
        StaggeredGridLayoutManager manager = (StaggeredGridLayoutManager) layoutManager;
        return new Builder(recyclerView.getContext(), manager.getSpanCount());
    } else {
        return new Builder(recyclerView.getContext());
    }
}

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    super.onDraw(c, parent, state);
    // layout basically just gets drawn on the reserved space on top of the first view
    mView.layout(parent.getLeft(), 0, parent.getRight(), mView.getMeasuredHeight());

    for (int i = 0; i < parent.getChildCount(); i++) {
        View view = parent.getChildAt(i);
        if (parent.getChildAdapterPosition(view) == 0) {
            c.save();
            if (mHorizontal) {
                c.clipRect(parent.getLeft(), parent.getTop(), view.getLeft(), parent.getBottom());
                final int width = mView.getMeasuredWidth();
                final float left = (view.getLeft() - width) * mParallax;
                c.translate(left, 0);
                mView.draw(c);
                if (mShadowSize > 0) {
                    c.translate(view.getLeft() - left - mShadowSize, 0);
                    c.drawRect(parent.getLeft(), parent.getTop(), mShadowSize, parent.getBottom(), mShadowPaint);
                }
            } else {
                c.clipRect(parent.getLeft(), parent.getTop(), parent.getRight(), view.getTop());
                final int height = mView.getMeasuredHeight();
                final float top = (view.getTop() - height) * mParallax;
                c.translate(0, top);
                mView.draw(c);
                if (mShadowSize > 0) {
                    c.translate(0, view.getTop() - top - mShadowSize);
                    c.drawRect(parent.getLeft(), parent.getTop(), parent.getRight(), mShadowSize, mShadowPaint);
                }
            }
            c.restore();
            break;
        }
    }
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    if (parent.getChildAdapterPosition(view) < mColumns) {
        if (mHorizontal) {
            if (mView.getMeasuredWidth() <= 0) {
                mView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST),
                        View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST));
            }
            outRect.set(mView.getMeasuredWidth(), 0, 0, 0);
        } else {
            if (mView.getMeasuredHeight() <= 0) {
                mView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST),
                        View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST));
            }
            outRect.set(0, mView.getMeasuredHeight(), 0, 0);
        }
    } else {
        outRect.setEmpty();
    }
}

public static class Builder {
    private Context mContext;

    private View mView;
    private boolean mHorizontal;
    private float mParallax = 1f;
    private float mShadowSize;
    private int mColumns = 1;

    public Builder(@NonNull Context context) {
        mContext = context;
    }

    public Builder(@NonNull Context context, @IntRange(from = 1) int columns) {
        mContext = context;
        mColumns = columns;
    }

    public Builder(@NonNull Context context, boolean horizontal) {
        mContext = context;
        mHorizontal = horizontal;
    }


    public Builder setView(@NonNull View view) {
        mView = view;
        return this;
    }

    public Builder inflate(@LayoutRes int layoutRes) {
        mView = LayoutInflater.from(mContext).inflate(layoutRes, null, false);
        return this;
    }

    /**
     * Adds a parallax effect.
     *
     * @param parallax the multiplier to use, 0f would be the view standing still, 1f moves along with the first item.
     * @return this builder
     */
    public Builder parallax(@FloatRange(from = 0f, to = 1f) float parallax) {
        mParallax = parallax;
        return this;
    }

    public Builder scrollsHorizontally(boolean isHorizontal) {
        mHorizontal = isHorizontal;
        return this;
    }

    public Builder dropShadowDp(@IntRange(from = 0, to = 80) int dp) {
        mShadowSize = mContext.getResources().getDisplayMetrics().density * dp;
        return this;
    }

    public Builder dropShadow(@DimenRes int dimenResource) {
        mShadowSize = mContext.getResources().getDimensionPixelSize(dimenResource);
        return this;
    }

    public HeaderDecoration build() {
        if (mView == null) {
            throw new IllegalStateException("View must be set with either setView or inflate");
        }
        return new HeaderDecoration(mView, mHorizontal, mParallax, mShadowSize * 1.5f, mColumns);
    }

    public Builder columns(@IntRange(from = 1) int columns) {
        mColumns = columns;
        return this;
    }
}
}

并使用此课程如下

recyclerView.addItemDecoration(HeaderDecoration.with(recyclerView)
                .setView(getActivity().getLayoutInflater().inflate(R.layout.inflate_header_view_chat, null, false))
                .dropShadowDp(0)
                .build());

        chatAdapter = new ChatAdapter(getActivity(), postGroupData, this, mTotalRecords, this);
        recyclerView.setAdapter(chatAdapter);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
        linearLayoutManager.setStackFromEnd(true);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setOnTouchListener(this);
        chatAdapter.setOnItemClickListener(this);

recyclerView.xml

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

<include
    android:id="@+id/toolbar"
    layout="@layout/tool_bar_view_white" />

<View
    android:id="@+id/viewTop"
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:layout_below="@+id/toolbar"
    android:background="#BFBFBF" />

<com.sis.rockeit.widgets.TypefaceTextView
    android:id="@+id/load_more"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/toolbar"
    android:background="@color/md_blue_grey_300"
    android:gravity="center"
    android:padding="10dp"
    android:text="@string/loading_more_items"
    android:textColor="@color/colorAccent2"
    android:visibility="gone" />


<com.sis.rockeit.widgets.TypefaceTextView
    android:id="@+id/updating"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/toolbar"
    android:background="@color/md_blue_grey_300"
    android:gravity="center"
    android:padding="10dp"
    android:text="@string/updating"
    android:textColor="@color/colorAccent2"
    android:visibility="gone" />

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/relativeLayout"
    android:layout_below="@+id/viewTop">

    <include
        android:id="@+id/headerView"
        layout="@layout/inflate_header_view_chat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" />


    <android.support.v7.widget.RecyclerView xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/list"
        android:name="com.sis.rockeit.views.fragments.ChatFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/attachmentPreview"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/headerView"
        android:layout_marginEnd="@dimen/global_padding"
        android:layout_marginLeft="@dimen/global_padding"
        android:layout_marginRight="@dimen/global_padding"

        android:layout_marginStart="@dimen/global_padding"
        app:layoutManager="LinearLayoutManager"
        tools:context=".fragments.ChatFragment" />

    <RelativeLayout
        android:id="@+id/attachmentPreview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/headerView"
        android:background="@drawable/attachement_background">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerViewChatPreview"
            android:layout_width="match_parent"
            android:layout_height="@dimen/attachmentViewHeightChat" />
    </RelativeLayout>

    <include
        layout="@layout/inflate_attachment_menu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:visibility="visible" />

</RelativeLayout>

<RelativeLayout
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="@color/mdtp_white">

    <View
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#CFCFCD" />

    <ImageView
        android:id="@+id/imgAttachFilesChat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:padding="5dp"
        android:src="@drawable/add_attach" />

    <com.sis.rockeit.widgets.TypefaceTextView
        android:id="@+id/txtSendReply"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/view"
        android:layout_centerVertical="true"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:padding="10dp"
        android:text="Send"
        android:textColor="@color/rockeit_orange_color"
        app:fontName="@string/lato_medium" />

    <com.sis.rockeit.widgets.TypefaceEditText
        android:id="@+id/editChatText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/view"
        android:layout_margin="10dp"
        android:layout_toEndOf="@+id/imgAttachFilesChat"
        android:layout_toLeftOf="@+id/txtSendReply"
        android:layout_toRightOf="@+id/imgAttachFilesChat"
        android:layout_toStartOf="@+id/txtSendReply"
        android:background="@drawable/text_box"
        android:maxLines="3"
        android:padding="5dp"
        android:text=""
        android:textColor="@color/colorAccent2"
        android:textSize="@dimen/text_size_chat_bottom"
        app:fontName="@string/lato_medium" />


</RelativeLayout>
</RelativeLayout>

header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/global_padding">

<ImageView
    android:id="@+id/imgUser"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:src="@drawable/ic_profile" />

<com.sis.rockeit.widgets.TypefaceTextView
    android:id="@+id/textUserName"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/welcome_text_margin_top"
    android:text="Hi, David here!"
    android:textColor="@color/colorAccent2"
    android:textSize="24sp"
    app:fontName="@string/lato_black" />

<com.sis.rockeit.widgets.TypefaceTextView
    android:id="@+id/textView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="I would be happy to answer your questions."
    android:textColor="@color/colorAccent2"

    android:textSize="@dimen/welcome_msg_secondary_text_size"
    app:fontName="@string/lato_regular" />

1 个答案:

答案 0 :(得分:1)

使用下面的代码添加装饰器类。

private class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;

public SpacesItemDecoration(int space) {
    this.space = space;
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    if(parent.getChildAdapterPosition(view) == state.getItemCount()-1){
        outRect.bottom = space;
        outRect.top = 0; //don't forget about recycling...
    }
    if(parent.getChildAdapterPosition(view) == 0){
        outRect.top = space;
        outRect.bottom = 0;
    }
}
 }

将上面的类附加到装饰器视图。

int space = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
        getResources().getDisplayMetrics());
recyclerView.addItemDecoration(new SpacesItemDecoration(space));