package com.marverenic.music.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.support.annotation.IdRes; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.view.View; import com.marverenic.music.R; /** * An {@link android.support.v7.widget.RecyclerView.ItemDecoration} that draws a solid color behind * a {@link RecyclerView} and its children */ public class BackgroundDecoration extends RecyclerView.ItemDecoration { private Drawable mBackground; private NinePatchDrawable mShadow; private int[] excludedIDs; /** * Create an ItemDecorator for use with a RecyclerView * @param excludedLayoutIDs A list of layoutIDs to exclude adding a background color to * empty to add a background to the entire RecyclerView */ public BackgroundDecoration(@IdRes int... excludedLayoutIDs) { excludedIDs = excludedLayoutIDs; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); if (mShadow == null || mBackground == null) { Context ctx = parent.getContext(); int color = ContextCompat.getColor(ctx, R.color.background_elevated); mBackground = new ColorDrawable(color); mShadow = (NinePatchDrawable) ContextCompat.getDrawable(ctx, R.drawable.list_shadow); } Rect shadowPadding = new Rect(); mShadow.getPadding(shadowPadding); if (excludedIDs == null || excludedIDs.length == 0) { int top = 0; int bottom = c.getHeight(); mBackground.setBounds(left, top, right, bottom); mBackground.draw(c); mShadow.setBounds(left - shadowPadding.left, top - shadowPadding.top, right + shadowPadding.right, bottom + shadowPadding.bottom); mShadow.draw(c); } else { int layoutCount = parent.getChildCount(); for (int i = 0; i < layoutCount; i++) { View topView = parent.getChildAt(i); if (includeView(topView.getId())) { //noinspection StatementWithEmptyBody while (++i < layoutCount && includeView(parent.getChildAt(i).getId())) { // Find the last view in this section that will receive a background // This loop is intentionally left empty } View bottomView = parent.getChildAt(--i); Rect topInset = new Rect(); Rect endInset = new Rect(); parent.getLayoutManager().calculateItemDecorationsForChild(topView, topInset); parent.getLayoutManager().calculateItemDecorationsForChild(bottomView, endInset); RecyclerView.LayoutParams topParams = (RecyclerView.LayoutParams) topView.getLayoutParams(); RecyclerView.LayoutParams bottomParams = (RecyclerView.LayoutParams) bottomView.getLayoutParams(); int top = topView.getTop() - topParams.topMargin - topInset.top; int bottom; if (i == layoutCount - 1 || parent.getChildAdapterPosition(bottomView) == parent.getAdapter().getItemCount() - 1) { // If this is the last item in the adapter or last visible view, // fill the parent bottom = parent.getBottom(); } else { // Otherwise, fill to the bottom of the last item in the section bottom = bottomView.getBottom() + endInset.bottom + bottomParams.bottomMargin; } mBackground.setBounds(left, top, right, bottom); mBackground.draw(c); mShadow.setBounds(left - shadowPadding.left, top - shadowPadding.top, right + shadowPadding.right, bottom + shadowPadding.bottom); mShadow.draw(c); } } } } private boolean includeView(int viewId) { for (int i : excludedIDs) { if (viewId == i) { return false; } } return true; } }