4860e4ee48
Test: make setup-wizard-lib Bug: 76692459 Change-Id: I40171e973d442b1a1815e9e7d7c2cc984cb38bac
244 lines
9.3 KiB
Java
244 lines
9.3 KiB
Java
/*
|
|
* Copyright (C) 2015 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 com.android.setupwizardlib;
|
|
|
|
import android.content.Context;
|
|
import android.content.res.TypedArray;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.view.View;
|
|
|
|
import androidx.annotation.IntDef;
|
|
import androidx.core.view.ViewCompat;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
|
|
/**
|
|
* An {@link androidx.recyclerview.widget.RecyclerView.ItemDecoration} for RecyclerView to draw
|
|
* dividers between items. This ItemDecoration will draw the drawable specified by
|
|
* {@link #setDivider(android.graphics.drawable.Drawable)} as the divider in between each item by
|
|
* default, and the behavior of whether the divider is shown can be customized by subclassing
|
|
* {@link com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}.
|
|
*
|
|
* <p>Modified from v14 PreferenceFragment.DividerDecoration.
|
|
*/
|
|
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
|
|
|
/* static section */
|
|
|
|
/**
|
|
* An interface to be implemented by a {@link RecyclerView.ViewHolder} which controls whether
|
|
* dividers should be shown above and below that item.
|
|
*/
|
|
public interface DividedViewHolder {
|
|
|
|
/**
|
|
* Returns whether divider is allowed above this item. A divider will be shown only if both
|
|
* items immediately above and below it allows this divider.
|
|
*/
|
|
boolean isDividerAllowedAbove();
|
|
|
|
/**
|
|
* Returns whether divider is allowed below this item. A divider will be shown only if both
|
|
* items immediately above and below it allows this divider.
|
|
*/
|
|
boolean isDividerAllowedBelow();
|
|
}
|
|
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@IntDef({
|
|
DIVIDER_CONDITION_EITHER,
|
|
DIVIDER_CONDITION_BOTH})
|
|
public @interface DividerCondition {}
|
|
|
|
public static final int DIVIDER_CONDITION_EITHER = 0;
|
|
public static final int DIVIDER_CONDITION_BOTH = 1;
|
|
|
|
/**
|
|
* @deprecated Use {@link #DividerItemDecoration(android.content.Context)}
|
|
*/
|
|
@Deprecated
|
|
public static DividerItemDecoration getDefault(Context context) {
|
|
return new DividerItemDecoration(context);
|
|
}
|
|
|
|
/* non-static section */
|
|
|
|
private Drawable mDivider;
|
|
private int mDividerHeight;
|
|
private int mDividerIntrinsicHeight;
|
|
@DividerCondition
|
|
private int mDividerCondition;
|
|
|
|
public DividerItemDecoration() {
|
|
}
|
|
|
|
public DividerItemDecoration(Context context) {
|
|
final TypedArray a = context.obtainStyledAttributes(R.styleable.SuwDividerItemDecoration);
|
|
final Drawable divider = a.getDrawable(
|
|
R.styleable.SuwDividerItemDecoration_android_listDivider);
|
|
final int dividerHeight = a.getDimensionPixelSize(
|
|
R.styleable.SuwDividerItemDecoration_android_dividerHeight, 0);
|
|
@DividerCondition final int dividerCondition = a.getInt(
|
|
R.styleable.SuwDividerItemDecoration_suwDividerCondition,
|
|
DIVIDER_CONDITION_EITHER);
|
|
a.recycle();
|
|
|
|
setDivider(divider);
|
|
setDividerHeight(dividerHeight);
|
|
setDividerCondition(dividerCondition);
|
|
}
|
|
|
|
@Override
|
|
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
|
if (mDivider == null) {
|
|
return;
|
|
}
|
|
final int childCount = parent.getChildCount();
|
|
final int width = parent.getWidth();
|
|
final int dividerHeight = mDividerHeight != 0 ? mDividerHeight : mDividerIntrinsicHeight;
|
|
for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) {
|
|
final View view = parent.getChildAt(childViewIndex);
|
|
if (shouldDrawDividerBelow(view, parent)) {
|
|
final int top = (int) ViewCompat.getY(view) + view.getHeight();
|
|
mDivider.setBounds(0, top, width, top + dividerHeight);
|
|
mDivider.draw(c);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
|
|
RecyclerView.State state) {
|
|
if (shouldDrawDividerBelow(view, parent)) {
|
|
outRect.bottom = mDividerHeight != 0 ? mDividerHeight : mDividerIntrinsicHeight;
|
|
}
|
|
}
|
|
|
|
private boolean shouldDrawDividerBelow(View view, RecyclerView parent) {
|
|
final RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
|
|
final int index = holder.getLayoutPosition();
|
|
final int lastItemIndex = parent.getAdapter().getItemCount() - 1;
|
|
if (isDividerAllowedBelow(holder)) {
|
|
if (mDividerCondition == DIVIDER_CONDITION_EITHER) {
|
|
// Draw the divider without consulting the next item if we only
|
|
// need permission for either above or below.
|
|
return true;
|
|
}
|
|
} else if (mDividerCondition == DIVIDER_CONDITION_BOTH || index == lastItemIndex) {
|
|
// Don't draw if the current view holder doesn't allow drawing below
|
|
// and the current theme requires permission for both the item below and above.
|
|
// Also, if this is the last item, there is no item below to ask permission
|
|
// for whether to draw a divider above, so don't draw it.
|
|
return false;
|
|
}
|
|
// Require permission from index below to draw the divider.
|
|
if (index < lastItemIndex) {
|
|
final RecyclerView.ViewHolder nextHolder =
|
|
parent.findViewHolderForLayoutPosition(index + 1);
|
|
if (!isDividerAllowedAbove(nextHolder)) {
|
|
// Don't draw if the next view holder doesn't allow drawing above
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Whether a divider is allowed above the view holder. The allowed values will be combined
|
|
* according to {@link #getDividerCondition()}. The default implementation delegates to
|
|
* {@link com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}, or simply allows
|
|
* the divider if the view holder doesn't implement {@code DividedViewHolder}. Subclasses can
|
|
* override this to give more information to decide whether a divider should be drawn.
|
|
*
|
|
* @return True if divider is allowed above this view holder.
|
|
*/
|
|
protected boolean isDividerAllowedAbove(RecyclerView.ViewHolder viewHolder) {
|
|
return !(viewHolder instanceof DividedViewHolder)
|
|
|| ((DividedViewHolder) viewHolder).isDividerAllowedAbove();
|
|
}
|
|
|
|
/**
|
|
* Whether a divider is allowed below the view holder. The allowed values will be combined
|
|
* according to {@link #getDividerCondition()}. The default implementation delegates to
|
|
* {@link com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}, or simply allows
|
|
* the divider if the view holder doesn't implement {@code DividedViewHolder}. Subclasses can
|
|
* override this to give more information to decide whether a divider should be drawn.
|
|
*
|
|
* @return True if divider is allowed below this view holder.
|
|
*/
|
|
protected boolean isDividerAllowedBelow(RecyclerView.ViewHolder viewHolder) {
|
|
return !(viewHolder instanceof DividedViewHolder)
|
|
|| ((DividedViewHolder) viewHolder).isDividerAllowedBelow();
|
|
}
|
|
|
|
/**
|
|
* Sets the drawable to be used as the divider.
|
|
*/
|
|
public void setDivider(Drawable divider) {
|
|
if (divider != null) {
|
|
mDividerIntrinsicHeight = divider.getIntrinsicHeight();
|
|
} else {
|
|
mDividerIntrinsicHeight = 0;
|
|
}
|
|
mDivider = divider;
|
|
}
|
|
|
|
/**
|
|
* Gets the drawable currently used as the divider.
|
|
*/
|
|
public Drawable getDivider() {
|
|
return mDivider;
|
|
}
|
|
|
|
/**
|
|
* Sets the divider height, in pixels.
|
|
*/
|
|
public void setDividerHeight(int dividerHeight) {
|
|
mDividerHeight = dividerHeight;
|
|
}
|
|
|
|
/**
|
|
* Gets the divider height, in pixels.
|
|
*/
|
|
public int getDividerHeight() {
|
|
return mDividerHeight;
|
|
}
|
|
|
|
/**
|
|
* Sets whether the divider needs permission from both the item view holder below
|
|
* and above from where the divider would draw itself or just needs permission from
|
|
* one or the other before drawing itself.
|
|
*/
|
|
public void setDividerCondition(@DividerCondition int dividerCondition) {
|
|
mDividerCondition = dividerCondition;
|
|
}
|
|
|
|
/**
|
|
* Gets whether the divider needs permission from both the item view holder below
|
|
* and above from where the divider would draw itself or just needs permission from
|
|
* one or the other before drawing itself.
|
|
*/
|
|
@DividerCondition
|
|
public int getDividerCondition() {
|
|
return mDividerCondition;
|
|
}
|
|
}
|