public class

DividerDecoration

extends RecyclerView.ItemDecoration

 java.lang.Object

androidx.recyclerview.widget.RecyclerView.ItemDecoration

↳androidx.car.widget.itemdecorators.DividerDecoration

Gradle dependencies

compile group: 'androidx.car', name: 'car', version: '1.0.0-alpha7'

  • groupId: androidx.car
  • artifactId: car
  • version: 1.0.0-alpha7

Artifact androidx.car:car:1.0.0-alpha7 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.car:car com.android.support:car

Overview

A that will draw a dividing line between each item in the RecyclerView that it is added to.

Summary

Fields
public static final intINVALID_RESOURCE_ID

Constructors
publicDividerDecoration(Context context, int dividerStartMargin, int dividerEndMargin, int dividerStartId, int dividerEndId, int listDividerColor)

Methods
public voidgetItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)

Retrieve any offsets for the given item.

public voidonDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)

Draw any appropriate decorations into the Canvas supplied to the RecyclerView.

public voidsetDividerColor(int dividerColor)

Sets the color for the dividers.

public voidsetVisibilityManager(PagedListView.DividerVisibilityManager dvm)

Sets PagedListView.DividerVisibilityManager on the DividerDecoration.

public voidupdateDividerColor()

Updates the list divider color which may have changed due to a day night transition.

from RecyclerView.ItemDecorationgetItemOffsets, onDraw, onDraw, onDrawOver
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

public static final int INVALID_RESOURCE_ID

Constructors

public DividerDecoration(Context context, int dividerStartMargin, int dividerEndMargin, int dividerStartId, int dividerEndId, int listDividerColor)

Parameters:

dividerStartMargin: The start offset of the dividing line. This offset will be relative to dividerStartId if that value is given.
dividerEndMargin: The end offset of the dividing line. This offset will be relative to dividerEndId if that value is given.
dividerStartId: A child view id whose starting edge will be used as the starting edge of the dividing line. If this value is DividerDecoration.INVALID_RESOURCE_ID, the top container of each child view will be used.
dividerEndId: A child view id whose ending edge will be used as the starting edge of the dividing line. If this value is DividerDecoration.INVALID_RESOURCE_ID, then the top container view of each child will be used.

Methods

public void setDividerColor(int dividerColor)

Sets the color for the dividers.

public void updateDividerColor()

Updates the list divider color which may have changed due to a day night transition.

public void setVisibilityManager(PagedListView.DividerVisibilityManager dvm)

Sets PagedListView.DividerVisibilityManager on the DividerDecoration.

public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)

Draw any appropriate decorations into the Canvas supplied to the RecyclerView. Any content drawn by this method will be drawn after the item views are drawn and will thus appear over the views.

Parameters:

c: Canvas to draw into
parent: RecyclerView this ItemDecoration is drawing into
state: The current state of RecyclerView.

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)

Retrieve any offsets for the given item. Each field of outRect specifies the number of pixels that the item view should be inset by, similar to padding or margin. The default implementation sets the bounds of outRect to 0 and returns.

If this ItemDecoration does not affect the positioning of item views, it should set all four fields of outRect (left, top, right, bottom) to zero before returning.

If you need to access Adapter for additional data, you can call RecyclerView.getChildAdapterPosition(View) to get the adapter position of the View.

Parameters:

outRect: Rect to receive the output.
view: The child view to decorate
parent: RecyclerView this ItemDecoration is decorating
state: The current state of RecyclerView.

Source

/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.car.widget.itemdecorators;

import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;

import androidx.annotation.ColorRes;
import androidx.annotation.IdRes;
import androidx.annotation.RestrictTo;
import androidx.car.R;
import androidx.car.util.GridLayoutManagerUtils;
import androidx.car.widget.PagedListView.DividerVisibilityManager;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

/**
 * A {@link RecyclerView.ItemDecoration} that will draw a dividing line between each item in the
 * RecyclerView that it is added to.
 *
 * @hide
 */
@RestrictTo(LIBRARY_GROUP_PREFIX)
public class DividerDecoration extends RecyclerView.ItemDecoration {
    public static final int INVALID_RESOURCE_ID = -1;

    private final Context mContext;
    private final Paint mPaint;
    private final int mDividerHeight;
    private final int mDividerStartMargin;
    private final int mDividerEndMargin;
    @IdRes private final int mDividerStartId;
    @IdRes private final int mDividerEndId;
    @ColorRes private int mListDividerColor;
    private DividerVisibilityManager mVisibilityManager;

    /**
     * @param dividerStartMargin The start offset of the dividing line. This offset will be
     *     relative to {@code dividerStartId} if that value is given.
     * @param dividerEndMargin The end offset of the dividing line. This offset will be
     *     relative to {@code dividerEndId} if that value is given.
     * @param dividerStartId A child view id whose starting edge will be used as the starting
     *     edge of the dividing line. If this value is {@link #INVALID_RESOURCE_ID}, the top
     *     container of each child view will be used.
     * @param dividerEndId A child view id whose ending edge will be used as the starting edge
     *     of the dividing line. If this value is {@link #INVALID_RESOURCE_ID}, then the top
     *     container view of each child will be used.
     */
    public DividerDecoration(Context context, int dividerStartMargin,
            int dividerEndMargin, @IdRes int dividerStartId, @IdRes int dividerEndId,
            @ColorRes int listDividerColor) {
        mContext = context;
        mDividerStartMargin = dividerStartMargin;
        mDividerEndMargin = dividerEndMargin;
        mDividerStartId = dividerStartId;
        mDividerEndId = dividerEndId;
        mListDividerColor = listDividerColor;

        mPaint = new Paint();
        mPaint.setColor(mContext.getColor(listDividerColor));
        mDividerHeight = mContext.getResources().getDimensionPixelSize(
                R.dimen.car_list_divider_height);
    }

    /** Sets the color for the dividers. */
    public void setDividerColor(@ColorRes int dividerColor) {
        mListDividerColor = dividerColor;
        updateDividerColor();
    }

    /** Updates the list divider color which may have changed due to a day night transition. */
    public void updateDividerColor() {
        mPaint.setColor(mContext.getColor(mListDividerColor));
    }

    /** Sets {@link DividerVisibilityManager} on the DividerDecoration.*/
    public void setVisibilityManager(DividerVisibilityManager dvm) {
        mVisibilityManager = dvm;
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        boolean usesGridLayoutManager = parent.getLayoutManager() instanceof GridLayoutManager;
        for (int i = 0; i < parent.getChildCount(); i++) {
            View container = parent.getChildAt(i);
            int itemPosition = parent.getChildAdapterPosition(container);

            if (!showDividerForAdapterPosition(itemPosition)) {
                continue;
            }

            View nextVerticalContainer;
            if (usesGridLayoutManager) {
                // Find an item in next row to calculate vertical space.
                int lastItemPosition =
                        GridLayoutManagerUtils.getLastItemPositionOnSameRow(container, parent);
                nextVerticalContainer =
                        parent.getLayoutManager().findViewByPosition(lastItemPosition + 1);
            } else {
                nextVerticalContainer = parent.getChildAt(i + 1);
            }

            if (nextVerticalContainer == null) {
                // Skip drawing divider for the last row in GridLayoutManager, or the last
                // item (presumably in LinearLayoutManager).
                continue;
            }

            int spacing = nextVerticalContainer.getTop() - container.getBottom();

            // Sometimes during refresh, the nextVerticalContainer can still exist, but is
            // not positioned in its corresponding position in the list (i.e. it has been pushed
            // off-screen). This will result in a negative value for spacing. Do not draw a
            // divider in this case to avoid the divider appearing in the wrong position.
            if (spacing >= 0) {
                drawDivider(c, container, spacing);
            }
        }
    }

    /**
     * Draws a divider under {@code container}.
     *
     * @param spacing between {@code container} and next view.
     */
    private void drawDivider(Canvas c, View container, int spacing) {
        View startChild =
                mDividerStartId != INVALID_RESOURCE_ID
                        ? container.findViewById(mDividerStartId)
                        : container;

        View endChild =
                mDividerEndId != INVALID_RESOURCE_ID
                        ? container.findViewById(mDividerEndId)
                        : container;

        if (startChild == null || endChild == null) {
            return;
        }

        Rect containerRect = new Rect();
        container.getGlobalVisibleRect(containerRect);

        Rect startRect = new Rect();
        startChild.getGlobalVisibleRect(startRect);

        Rect endRect = new Rect();
        endChild.getGlobalVisibleRect(endRect);

        int left = container.getLeft() + mDividerStartMargin
                + (startRect.left - containerRect.left);
        int right = container.getRight() - mDividerEndMargin
                - (endRect.right - containerRect.right);
        // "(spacing + divider height) / 2" aligns the center of divider to that of spacing
        // between two items.
        // When spacing is an odd value (e.g. created by other decoration), space under divider
        // is greater by 1dp.
        int bottom = container.getBottom() + (spacing + mDividerHeight) / 2;
        int top = bottom - mDividerHeight;

        c.drawRect(left, top, right, bottom, mPaint);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
            RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int pos = parent.getChildAdapterPosition(view);
        if (!showDividerForAdapterPosition(pos)) {
            return;
        }
        // Add an bottom offset to all items that should have divider, even when divider is not
        // drawn for the bottom item(s).
        // With GridLayoutManager it's difficult to tell whether a view is in the last row.
        // This is to keep expected behavior consistent.
        outRect.bottom = mDividerHeight;
    }

    private boolean showDividerForAdapterPosition(int position) {
        // If visibility manager is not set, default to show dividers.
        return mVisibilityManager == null || mVisibilityManager.getShowDivider(position);
    }
}