summaryrefslogtreecommitdiff
path: root/library/recyclerview
diff options
context:
space:
mode:
Diffstat (limited to 'library/recyclerview')
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/DividerItemDecoration.java356
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/GlifPreferenceLayout.java103
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/GlifRecyclerLayout.java294
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/SetupWizardPreferenceLayout.java98
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/SetupWizardRecyclerLayout.java298
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/items/ItemViewHolder.java70
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/items/RecyclerItemAdapter.java401
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/template/RecyclerMixin.java393
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegate.java84
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/view/HeaderRecyclerView.java408
-rw-r--r--library/recyclerview/src/com/android/setupwizardlib/view/StickyHeaderRecyclerView.java174
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/items/RecyclerItemAdapterTest.java218
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/template/RecyclerMixinTest.java176
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/DividerItemDecorationTest.java334
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifPreferenceLayoutTest.java116
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifRecyclerLayoutTest.java250
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/HeaderRecyclerViewTest.java259
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardPreferenceLayoutTest.java118
-rw-r--r--library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardRecyclerLayoutTest.java257
-rw-r--r--library/recyclerview/test/robotest/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegateTest.java95
20 files changed, 2183 insertions, 2319 deletions
diff --git a/library/recyclerview/src/com/android/setupwizardlib/DividerItemDecoration.java b/library/recyclerview/src/com/android/setupwizardlib/DividerItemDecoration.java
index 2db17f8..128ed6b 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/DividerItemDecoration.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/DividerItemDecoration.java
@@ -21,223 +21,207 @@ 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 android.view.View;
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}.
+ * 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 */
+ /* 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 {
/**
- * An interface to be implemented by a {@link RecyclerView.ViewHolder} which controls whether
- * dividers should be shown above and below that item.
+ * 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.
*/
- 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;
+ boolean isDividerAllowedAbove();
/**
- * @deprecated Use {@link #DividerItemDecoration(android.content.Context)}
+ * 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.
*/
- @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;
+ boolean isDividerAllowedBelow();
+ }
- public DividerItemDecoration() {
- }
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({DIVIDER_CONDITION_EITHER, DIVIDER_CONDITION_BOTH})
+ public @interface DividerCondition {}
- 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);
- }
+ public static final int DIVIDER_CONDITION_EITHER = 0;
+ public static final int DIVIDER_CONDITION_BOTH = 1;
- @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);
- }
- }
- }
+ /** @deprecated Use {@link #DividerItemDecoration(android.content.Context)} */
+ @Deprecated
+ public static DividerItemDecoration getDefault(Context context) {
+ return new DividerItemDecoration(context);
+ }
- @Override
- public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
- RecyclerView.State state) {
- if (shouldDrawDividerBelow(view, parent)) {
- outRect.bottom = mDividerHeight != 0 ? mDividerHeight : mDividerIntrinsicHeight;
- }
- }
+ /* non-static section */
- 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();
- }
+ private Drawable divider;
+ private int dividerHeight;
+ private int dividerIntrinsicHeight;
+ @DividerCondition private int dividerCondition;
- /**
- * 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();
- }
+ public DividerItemDecoration() {}
- /**
- * 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;
+ 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 (divider == null) {
+ return;
}
-
- /**
- * Gets the drawable currently used as the divider.
- */
- public Drawable getDivider() {
- return mDivider;
+ final int childCount = parent.getChildCount();
+ final int width = parent.getWidth();
+ final int dividerHeight = this.dividerHeight != 0 ? this.dividerHeight : dividerIntrinsicHeight;
+ 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();
+ divider.setBounds(0, top, width, top + dividerHeight);
+ divider.draw(c);
+ }
}
+ }
- /**
- * Sets the divider height, in pixels.
- */
- public void setDividerHeight(int dividerHeight) {
- mDividerHeight = dividerHeight;
+ @Override
+ public void getItemOffsets(
+ Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ if (shouldDrawDividerBelow(view, parent)) {
+ outRect.bottom = dividerHeight != 0 ? dividerHeight : dividerIntrinsicHeight;
}
-
- /**
- * Gets the divider height, in pixels.
- */
- public int getDividerHeight() {
- return mDividerHeight;
+ }
+
+ 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 (dividerCondition == 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 (dividerCondition == 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;
}
-
- /**
- * 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;
+ // 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;
+ }
}
-
- /**
- * 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;
+ 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) {
+ dividerIntrinsicHeight = divider.getIntrinsicHeight();
+ } else {
+ dividerIntrinsicHeight = 0;
}
+ this.divider = divider;
+ }
+
+ /** Gets the drawable currently used as the divider. */
+ public Drawable getDivider() {
+ return divider;
+ }
+
+ /** Sets the divider height, in pixels. */
+ public void setDividerHeight(int dividerHeight) {
+ this.dividerHeight = dividerHeight;
+ }
+
+ /** Gets the divider height, in pixels. */
+ public int getDividerHeight() {
+ return dividerHeight;
+ }
+
+ /**
+ * 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) {
+ this.dividerCondition = 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 dividerCondition;
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/GlifPreferenceLayout.java b/library/recyclerview/src/com/android/setupwizardlib/GlifPreferenceLayout.java
index af1a739..795fdad 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/GlifPreferenceLayout.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/GlifPreferenceLayout.java
@@ -18,21 +18,20 @@ package com.android.setupwizardlib;
import android.content.Context;
import android.os.Bundle;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.setupwizardlib.template.RecyclerMixin;
/**
* A layout to be used with {@code PreferenceFragment} in v14 support library. This can be specified
- * as the {@code android:layout} in the {@code app:preferenceFragmentStyle} in
- * {@code app:preferenceTheme}.
+ * as the {@code android:layout} in the {@code app:preferenceFragmentStyle} in {@code
+ * app:preferenceTheme}.
+ *
+ * <p>Example:
*
- * <p />Example:
* <pre>{@code
* &lt;style android:name="MyActivityTheme">
* &lt;item android:name="preferenceTheme">@style/MyPreferenceTheme&lt;/item>
@@ -47,10 +46,11 @@ import com.android.setupwizardlib.template.RecyclerMixin;
* &lt;/style>
* }</pre>
*
- * where {@code my_preference_layout} is a layout that contains
- * {@link com.android.setupwizardlib.GlifPreferenceLayout}.
+ * where {@code my_preference_layout} is a layout that contains {@link
+ * com.android.setupwizardlib.GlifPreferenceLayout}.
+ *
+ * <p>Example:
*
- * <p />Example:
* <pre>{@code
* &lt;com.android.setupwizardlib.GlifPreferenceLayout
* xmlns:android="http://schemas.android.com/apk/res/android"
@@ -59,60 +59,57 @@ import com.android.setupwizardlib.template.RecyclerMixin;
* android:layout_height="match_parent" />
* }</pre>
*
- * <p />Fragments using this layout <em>must</em> delegate {@code onCreateRecyclerView} to the
- * implementation in this class:
- * {@link #onCreateRecyclerView(android.view.LayoutInflater, android.view.ViewGroup,
- * android.os.Bundle)}
+ * <p>Fragments using this layout <em>must</em> delegate {@code onCreateRecyclerView} to the
+ * implementation in this class: {@link #onCreateRecyclerView(android.view.LayoutInflater,
+ * android.view.ViewGroup, android.os.Bundle)}
*/
public class GlifPreferenceLayout extends GlifRecyclerLayout {
- public GlifPreferenceLayout(Context context) {
- super(context);
- }
+ public GlifPreferenceLayout(Context context) {
+ super(context);
+ }
- public GlifPreferenceLayout(Context context, int template, int containerId) {
- super(context, template, containerId);
- }
+ public GlifPreferenceLayout(Context context, int template, int containerId) {
+ super(context, template, containerId);
+ }
- public GlifPreferenceLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
+ public GlifPreferenceLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
- public GlifPreferenceLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
+ public GlifPreferenceLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
- @Override
- protected ViewGroup findContainer(int containerId) {
- if (containerId == 0) {
- containerId = R.id.suw_layout_content;
- }
- return super.findContainer(containerId);
+ @Override
+ protected ViewGroup findContainer(int containerId) {
+ if (containerId == 0) {
+ containerId = R.id.suw_layout_content;
}
+ return super.findContainer(containerId);
+ }
- /**
- * This method must be called in {@code PreferenceFragment#onCreateRecyclerView}.
- */
- public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
- Bundle savedInstanceState) {
- return mRecyclerMixin.getRecyclerView();
- }
+ /** This method must be called in {@code PreferenceFragment#onCreateRecyclerView}. */
+ public RecyclerView onCreateRecyclerView(
+ LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+ return mRecyclerMixin.getRecyclerView();
+ }
- @Override
- protected View onInflateTemplate(LayoutInflater inflater, int template) {
- if (template == 0) {
- template = R.layout.suw_glif_preference_template;
- }
- return super.onInflateTemplate(inflater, template);
+ @Override
+ protected View onInflateTemplate(LayoutInflater inflater, int template) {
+ if (template == 0) {
+ template = R.layout.suw_glif_preference_template;
}
+ return super.onInflateTemplate(inflater, template);
+ }
- @Override
- protected void onTemplateInflated() {
- // Inflate the recycler view here, so attributes on the decoration views can be applied
- // immediately.
- final LayoutInflater inflater = LayoutInflater.from(getContext());
- RecyclerView recyclerView = (RecyclerView) inflater.inflate(
- R.layout.suw_glif_preference_recycler_view, this, false);
- mRecyclerMixin = new RecyclerMixin(this, recyclerView);
- }
+ @Override
+ protected void onTemplateInflated() {
+ // Inflate the recycler view here, so attributes on the decoration views can be applied
+ // immediately.
+ final LayoutInflater inflater = LayoutInflater.from(getContext());
+ RecyclerView recyclerView =
+ (RecyclerView) inflater.inflate(R.layout.suw_glif_preference_recycler_view, this, false);
+ mRecyclerMixin = new RecyclerMixin(this, recyclerView);
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/GlifRecyclerLayout.java b/library/recyclerview/src/com/android/setupwizardlib/GlifRecyclerLayout.java
index 7e0b1b7..2595b79 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/GlifRecyclerLayout.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/GlifRecyclerLayout.java
@@ -20,15 +20,13 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION_CODES;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-
import com.android.setupwizardlib.template.RecyclerMixin;
import com.android.setupwizardlib.template.RecyclerViewScrollHandlingDelegate;
import com.android.setupwizardlib.template.RequireScrollMixin;
@@ -39,157 +37,137 @@ import com.android.setupwizardlib.template.RequireScrollMixin;
*/
public class GlifRecyclerLayout extends GlifLayout {
- protected RecyclerMixin mRecyclerMixin;
-
- public GlifRecyclerLayout(Context context) {
- this(context, 0, 0);
- }
-
- public GlifRecyclerLayout(Context context, int template) {
- this(context, template, 0);
- }
-
- public GlifRecyclerLayout(Context context, int template, int containerId) {
- super(context, template, containerId);
- init(context, null, 0);
- }
-
- public GlifRecyclerLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context, attrs, 0);
- }
-
- @TargetApi(VERSION_CODES.HONEYCOMB)
- public GlifRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context, attrs, defStyleAttr);
- }
-
- private void init(Context context, AttributeSet attrs, int defStyleAttr) {
- mRecyclerMixin.parseAttributes(attrs, defStyleAttr);
- registerMixin(RecyclerMixin.class, mRecyclerMixin);
-
- final RequireScrollMixin requireScrollMixin = getMixin(RequireScrollMixin.class);
- requireScrollMixin.setScrollHandlingDelegate(
- new RecyclerViewScrollHandlingDelegate(requireScrollMixin, getRecyclerView()));
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- mRecyclerMixin.onLayout();
- }
-
- @Override
- protected View onInflateTemplate(LayoutInflater inflater, int template) {
- if (template == 0) {
- template = R.layout.suw_glif_recycler_template;
- }
- return super.onInflateTemplate(inflater, template);
- }
-
- @Override
- protected void onTemplateInflated() {
- final View recyclerView = findViewById(R.id.suw_recycler_view);
- if (recyclerView instanceof RecyclerView) {
- mRecyclerMixin = new RecyclerMixin(this, (RecyclerView) recyclerView);
- } else {
- throw new IllegalStateException(
- "GlifRecyclerLayout should use a template with recycler view");
- }
- }
-
- @Override
- protected ViewGroup findContainer(int containerId) {
- if (containerId == 0) {
- containerId = R.id.suw_recycler_view;
- }
- return super.findContainer(containerId);
- }
-
- @Override
- // Returning generic type is the common pattern used for findViewBy* methods
- @SuppressWarnings("TypeParameterUnusedInFormals")
- public <T extends View> T findManagedViewById(int id) {
- final View header = mRecyclerMixin.getHeader();
- if (header != null) {
- final T view = header.findViewById(id);
- if (view != null) {
- return view;
- }
- }
- return super.findViewById(id);
- }
-
- /**
- * @see RecyclerMixin#setDividerItemDecoration(DividerItemDecoration)
- */
- public void setDividerItemDecoration(DividerItemDecoration decoration) {
- mRecyclerMixin.setDividerItemDecoration(decoration);
- }
-
- /**
- * @see RecyclerMixin#getRecyclerView()
- */
- public RecyclerView getRecyclerView() {
- return mRecyclerMixin.getRecyclerView();
- }
-
- /**
- * @see RecyclerMixin#setAdapter(Adapter)
- */
- public void setAdapter(Adapter<? extends ViewHolder> adapter) {
- mRecyclerMixin.setAdapter(adapter);
- }
-
- /**
- * @see RecyclerMixin#getAdapter()
- */
- public Adapter<? extends ViewHolder> getAdapter() {
- return mRecyclerMixin.getAdapter();
- }
-
- /**
- * @deprecated Use {@link #setDividerInsets(int, int)} instead.
- */
- @Deprecated
- public void setDividerInset(int inset) {
- mRecyclerMixin.setDividerInset(inset);
- }
-
- /**
- * @see RecyclerMixin#setDividerInset(int)
- */
- public void setDividerInsets(int start, int end) {
- mRecyclerMixin.setDividerInsets(start, end);
- }
-
- /**
- * @deprecated Use {@link #getDividerInsetStart()} instead.
- */
- @Deprecated
- public int getDividerInset() {
- return mRecyclerMixin.getDividerInset();
- }
-
- /**
- * @see RecyclerMixin#getDividerInsetStart()
- */
- public int getDividerInsetStart() {
- return mRecyclerMixin.getDividerInsetStart();
- }
-
- /**
- * @see RecyclerMixin#getDividerInsetEnd()
- */
- public int getDividerInsetEnd() {
- return mRecyclerMixin.getDividerInsetEnd();
- }
-
- /**
- * @see RecyclerMixin#getDivider()
- */
- public Drawable getDivider() {
- return mRecyclerMixin.getDivider();
- }
+ protected RecyclerMixin mRecyclerMixin;
+
+ public GlifRecyclerLayout(Context context) {
+ this(context, 0, 0);
+ }
+
+ public GlifRecyclerLayout(Context context, int template) {
+ this(context, template, 0);
+ }
+
+ public GlifRecyclerLayout(Context context, int template, int containerId) {
+ super(context, template, containerId);
+ init(null, 0);
+ }
+
+ public GlifRecyclerLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs, 0);
+ }
+
+ @TargetApi(VERSION_CODES.HONEYCOMB)
+ public GlifRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs, defStyleAttr);
+ }
+
+ private void init(AttributeSet attrs, int defStyleAttr) {
+ mRecyclerMixin.parseAttributes(attrs, defStyleAttr);
+ registerMixin(RecyclerMixin.class, mRecyclerMixin);
+
+ final RequireScrollMixin requireScrollMixin = getMixin(RequireScrollMixin.class);
+ requireScrollMixin.setScrollHandlingDelegate(
+ new RecyclerViewScrollHandlingDelegate(requireScrollMixin, getRecyclerView()));
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ mRecyclerMixin.onLayout();
+ }
+
+ @Override
+ protected View onInflateTemplate(LayoutInflater inflater, int template) {
+ if (template == 0) {
+ template = R.layout.suw_glif_recycler_template;
+ }
+ return super.onInflateTemplate(inflater, template);
+ }
+
+ @Override
+ protected void onTemplateInflated() {
+ final View recyclerView = findViewById(R.id.suw_recycler_view);
+ if (recyclerView instanceof RecyclerView) {
+ mRecyclerMixin = new RecyclerMixin(this, (RecyclerView) recyclerView);
+ } else {
+ throw new IllegalStateException(
+ "GlifRecyclerLayout should use a template with recycler view");
+ }
+ }
+
+ @Override
+ protected ViewGroup findContainer(int containerId) {
+ if (containerId == 0) {
+ containerId = R.id.suw_recycler_view;
+ }
+ return super.findContainer(containerId);
+ }
+
+ @Override
+ // Returning generic type is the common pattern used for findViewBy* methods
+ @SuppressWarnings("TypeParameterUnusedInFormals")
+ public <T extends View> T findManagedViewById(int id) {
+ final View header = mRecyclerMixin.getHeader();
+ if (header != null) {
+ final T view = header.findViewById(id);
+ if (view != null) {
+ return view;
+ }
+ }
+ return super.findViewById(id);
+ }
+
+ /** @see RecyclerMixin#setDividerItemDecoration(DividerItemDecoration) */
+ public void setDividerItemDecoration(DividerItemDecoration decoration) {
+ mRecyclerMixin.setDividerItemDecoration(decoration);
+ }
+
+ /** @see RecyclerMixin#getRecyclerView() */
+ public RecyclerView getRecyclerView() {
+ return mRecyclerMixin.getRecyclerView();
+ }
+
+ /** @see RecyclerMixin#setAdapter(Adapter) */
+ public void setAdapter(Adapter<? extends ViewHolder> adapter) {
+ mRecyclerMixin.setAdapter(adapter);
+ }
+
+ /** @see RecyclerMixin#getAdapter() */
+ public Adapter<? extends ViewHolder> getAdapter() {
+ return mRecyclerMixin.getAdapter();
+ }
+
+ /** @deprecated Use {@link #setDividerInsets(int, int)} instead. */
+ @Deprecated
+ public void setDividerInset(int inset) {
+ mRecyclerMixin.setDividerInset(inset);
+ }
+
+ /** @see RecyclerMixin#setDividerInset(int) */
+ public void setDividerInsets(int start, int end) {
+ mRecyclerMixin.setDividerInsets(start, end);
+ }
+
+ /** @deprecated Use {@link #getDividerInsetStart()} instead. */
+ @Deprecated
+ public int getDividerInset() {
+ return mRecyclerMixin.getDividerInset();
+ }
+
+ /** @see RecyclerMixin#getDividerInsetStart() */
+ public int getDividerInsetStart() {
+ return mRecyclerMixin.getDividerInsetStart();
+ }
+
+ /** @see RecyclerMixin#getDividerInsetEnd() */
+ public int getDividerInsetEnd() {
+ return mRecyclerMixin.getDividerInsetEnd();
+ }
+
+ /** @see RecyclerMixin#getDivider() */
+ public Drawable getDivider() {
+ return mRecyclerMixin.getDivider();
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/SetupWizardPreferenceLayout.java b/library/recyclerview/src/com/android/setupwizardlib/SetupWizardPreferenceLayout.java
index 670c309..e9aa329 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/SetupWizardPreferenceLayout.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/SetupWizardPreferenceLayout.java
@@ -18,21 +18,20 @@ package com.android.setupwizardlib;
import android.content.Context;
import android.os.Bundle;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.setupwizardlib.template.RecyclerMixin;
/**
* A layout to be used with {@code PreferenceFragment} in v14 support library. This can be specified
- * as the {@code android:layout} in the {@code app:preferenceFragmentStyle} in
- * {@code app:preferenceTheme}.
+ * as the {@code android:layout} in the {@code app:preferenceFragmentStyle} in {@code
+ * app:preferenceTheme}.
+ *
+ * <p>Example:
*
- * <p />Example:
* <pre>{@code
* &lt;style android:name="MyActivityTheme">
* &lt;item android:name="preferenceTheme">@style/MyPreferenceTheme&lt;/item>
@@ -47,10 +46,11 @@ import com.android.setupwizardlib.template.RecyclerMixin;
* &lt;/style>
* }</pre>
*
- * where {@code my_preference_layout} is a layout that contains
- * {@link com.android.setupwizardlib.SetupWizardPreferenceLayout}.
+ * where {@code my_preference_layout} is a layout that contains {@link
+ * com.android.setupwizardlib.SetupWizardPreferenceLayout}.
+ *
+ * <p>Example:
*
- * <p />Example:
* <pre>{@code
* &lt;com.android.setupwizardlib.SetupWizardPreferenceLayout
* xmlns:android="http://schemas.android.com/apk/res/android"
@@ -59,58 +59,56 @@ import com.android.setupwizardlib.template.RecyclerMixin;
* android:layout_height="match_parent" />
* }</pre>
*
- * <p />Fragments using this layout <em>must</em> delegate {@code onCreateRecyclerView} to the
+ * <p>Fragments using this layout <em>must</em> delegate {@code onCreateRecyclerView} to the
* implementation in this class: {@link #onCreateRecyclerView}
*/
public class SetupWizardPreferenceLayout extends SetupWizardRecyclerLayout {
- public SetupWizardPreferenceLayout(Context context) {
- super(context);
- }
+ public SetupWizardPreferenceLayout(Context context) {
+ super(context);
+ }
- public SetupWizardPreferenceLayout(Context context, int template, int containerId) {
- super(context, template, containerId);
- }
+ public SetupWizardPreferenceLayout(Context context, int template, int containerId) {
+ super(context, template, containerId);
+ }
- public SetupWizardPreferenceLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
+ public SetupWizardPreferenceLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
- public SetupWizardPreferenceLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
+ public SetupWizardPreferenceLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
- @Override
- protected ViewGroup findContainer(int containerId) {
- if (containerId == 0) {
- containerId = R.id.suw_layout_content;
- }
- return super.findContainer(containerId);
+ @Override
+ protected ViewGroup findContainer(int containerId) {
+ if (containerId == 0) {
+ containerId = R.id.suw_layout_content;
}
+ return super.findContainer(containerId);
+ }
- /**
- * This method must be called in {@code PreferenceFragment#onCreateRecyclerView}.
- */
- public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
- Bundle savedInstanceState) {
- return mRecyclerMixin.getRecyclerView();
- }
+ /** This method must be called in {@code PreferenceFragment#onCreateRecyclerView}. */
+ public RecyclerView onCreateRecyclerView(
+ LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+ return mRecyclerMixin.getRecyclerView();
+ }
- @Override
- protected View onInflateTemplate(LayoutInflater inflater, int template) {
- if (template == 0) {
- template = R.layout.suw_preference_template;
- }
- return super.onInflateTemplate(inflater, template);
+ @Override
+ protected View onInflateTemplate(LayoutInflater inflater, int template) {
+ if (template == 0) {
+ template = R.layout.suw_preference_template;
}
+ return super.onInflateTemplate(inflater, template);
+ }
- @Override
- protected void onTemplateInflated() {
- // Inflate the recycler view here, so attributes on the decoration views can be applied
- // immediately.
- final LayoutInflater inflater = LayoutInflater.from(getContext());
- RecyclerView recyclerView = (RecyclerView) inflater.inflate(
- R.layout.suw_preference_recycler_view, this, false);
- mRecyclerMixin = new RecyclerMixin(this, recyclerView);
- }
+ @Override
+ protected void onTemplateInflated() {
+ // Inflate the recycler view here, so attributes on the decoration views can be applied
+ // immediately.
+ final LayoutInflater inflater = LayoutInflater.from(getContext());
+ RecyclerView recyclerView =
+ (RecyclerView) inflater.inflate(R.layout.suw_preference_recycler_view, this, false);
+ mRecyclerMixin = new RecyclerMixin(this, recyclerView);
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/SetupWizardRecyclerLayout.java b/library/recyclerview/src/com/android/setupwizardlib/SetupWizardRecyclerLayout.java
index 5d3f1a5..ba0b598 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/SetupWizardRecyclerLayout.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/SetupWizardRecyclerLayout.java
@@ -18,178 +18,156 @@ package com.android.setupwizardlib;
import android.content.Context;
import android.graphics.drawable.Drawable;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-
import com.android.setupwizardlib.template.RecyclerMixin;
import com.android.setupwizardlib.template.RecyclerViewScrollHandlingDelegate;
import com.android.setupwizardlib.template.RequireScrollMixin;
/**
- * A setup wizard layout for use with {@link androidx.recyclerview.widget.RecyclerView}.
- * {@code android:entries} can also be used to specify an
- * {@link com.android.setupwizardlib.items.ItemHierarchy} to be used with this layout in XML.
+ * A setup wizard layout for use with {@link androidx.recyclerview.widget.RecyclerView}. {@code
+ * android:entries} can also be used to specify an {@link
+ * com.android.setupwizardlib.items.ItemHierarchy} to be used with this layout in XML.
*
* @see SetupWizardListLayout
*/
public class SetupWizardRecyclerLayout extends SetupWizardLayout {
- private static final String TAG = "RecyclerLayout";
-
- protected RecyclerMixin mRecyclerMixin;
-
- public SetupWizardRecyclerLayout(Context context) {
- this(context, 0, 0);
- }
-
- public SetupWizardRecyclerLayout(Context context, int template, int containerId) {
- super(context, template, containerId);
- init(context, null, 0);
- }
-
- public SetupWizardRecyclerLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context, attrs, 0);
- }
-
- public SetupWizardRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context, attrs, defStyleAttr);
- }
-
- private void init(Context context, AttributeSet attrs, int defStyleAttr) {
- mRecyclerMixin.parseAttributes(attrs, defStyleAttr);
- registerMixin(RecyclerMixin.class, mRecyclerMixin);
-
-
- final RequireScrollMixin requireScrollMixin = getMixin(RequireScrollMixin.class);
- requireScrollMixin.setScrollHandlingDelegate(
- new RecyclerViewScrollHandlingDelegate(requireScrollMixin, getRecyclerView()));
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- mRecyclerMixin.onLayout();
- }
-
- /**
- * @see RecyclerMixin#getAdapter()
- */
- public Adapter<? extends ViewHolder> getAdapter() {
- return mRecyclerMixin.getAdapter();
- }
-
- /**
- * @see RecyclerMixin#setAdapter(Adapter)
- */
- public void setAdapter(Adapter<? extends ViewHolder> adapter) {
- mRecyclerMixin.setAdapter(adapter);
- }
-
- /**
- * @see RecyclerMixin#getRecyclerView()
- */
- public RecyclerView getRecyclerView() {
- return mRecyclerMixin.getRecyclerView();
- }
-
- @Override
- protected ViewGroup findContainer(int containerId) {
- if (containerId == 0) {
- containerId = R.id.suw_recycler_view;
- }
- return super.findContainer(containerId);
- }
-
- @Override
- protected View onInflateTemplate(LayoutInflater inflater, int template) {
- if (template == 0) {
- template = R.layout.suw_recycler_template;
- }
- return super.onInflateTemplate(inflater, template);
- }
-
- @Override
- protected void onTemplateInflated() {
- final View recyclerView = findViewById(R.id.suw_recycler_view);
- if (recyclerView instanceof RecyclerView) {
- mRecyclerMixin = new RecyclerMixin(this, (RecyclerView) recyclerView);
- } else {
- throw new IllegalStateException(
- "SetupWizardRecyclerLayout should use a template with recycler view");
- }
- }
-
- @Override
- // Returning generic type is the common pattern used for findViewBy* methods
- @SuppressWarnings("TypeParameterUnusedInFormals")
- public <T extends View> T findManagedViewById(int id) {
- final View header = mRecyclerMixin.getHeader();
- if (header != null) {
- final T view = header.findViewById(id);
- if (view != null) {
- return view;
- }
- }
- return super.findViewById(id);
- }
-
- /**
- * @deprecated Use {@link #setDividerInsets(int, int)} instead.
- */
- @Deprecated
- public void setDividerInset(int inset) {
- mRecyclerMixin.setDividerInset(inset);
- }
-
- /**
- * Sets the start inset of the divider. This will use the default divider drawable set in the
- * theme and apply insets to it.
- *
- * @param start The number of pixels to inset on the "start" side of the list divider. Typically
- * this will be either {@code @dimen/suw_items_icon_divider_inset} or
- * {@code @dimen/suw_items_text_divider_inset}.
- * @param end The number of pixels to inset on the "end" side of the list divider.
- *
- * @see RecyclerMixin#setDividerInsets(int, int)
- */
- public void setDividerInsets(int start, int end) {
- mRecyclerMixin.setDividerInsets(start, end);
- }
-
- /**
- * @deprecated Use {@link #getDividerInsetStart()} instead.
- */
- @Deprecated
- public int getDividerInset() {
- return mRecyclerMixin.getDividerInset();
- }
-
- /**
- * @see RecyclerMixin#getDividerInsetStart()
- */
- public int getDividerInsetStart() {
- return mRecyclerMixin.getDividerInsetStart();
- }
-
- /**
- * @see RecyclerMixin#getDividerInsetEnd()
- */
- public int getDividerInsetEnd() {
- return mRecyclerMixin.getDividerInsetEnd();
- }
-
- /**
- * @see RecyclerMixin#getDivider()
- */
- public Drawable getDivider() {
- return mRecyclerMixin.getDivider();
- }
+ protected RecyclerMixin mRecyclerMixin;
+
+ public SetupWizardRecyclerLayout(Context context) {
+ this(context, 0, 0);
+ }
+
+ public SetupWizardRecyclerLayout(Context context, int template, int containerId) {
+ super(context, template, containerId);
+ init(null, 0);
+ }
+
+ public SetupWizardRecyclerLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs, 0);
+ }
+
+ public SetupWizardRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs, defStyleAttr);
+ }
+
+ private void init(AttributeSet attrs, int defStyleAttr) {
+ mRecyclerMixin.parseAttributes(attrs, defStyleAttr);
+ registerMixin(RecyclerMixin.class, mRecyclerMixin);
+
+ final RequireScrollMixin requireScrollMixin = getMixin(RequireScrollMixin.class);
+ requireScrollMixin.setScrollHandlingDelegate(
+ new RecyclerViewScrollHandlingDelegate(requireScrollMixin, getRecyclerView()));
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ mRecyclerMixin.onLayout();
+ }
+
+ /** @see RecyclerMixin#getAdapter() */
+ public Adapter<? extends ViewHolder> getAdapter() {
+ return mRecyclerMixin.getAdapter();
+ }
+
+ /** @see RecyclerMixin#setAdapter(Adapter) */
+ public void setAdapter(Adapter<? extends ViewHolder> adapter) {
+ mRecyclerMixin.setAdapter(adapter);
+ }
+
+ /** @see RecyclerMixin#getRecyclerView() */
+ public RecyclerView getRecyclerView() {
+ return mRecyclerMixin.getRecyclerView();
+ }
+
+ @Override
+ protected ViewGroup findContainer(int containerId) {
+ if (containerId == 0) {
+ containerId = R.id.suw_recycler_view;
+ }
+ return super.findContainer(containerId);
+ }
+
+ @Override
+ protected View onInflateTemplate(LayoutInflater inflater, int template) {
+ if (template == 0) {
+ template = R.layout.suw_recycler_template;
+ }
+ return super.onInflateTemplate(inflater, template);
+ }
+
+ @Override
+ protected void onTemplateInflated() {
+ final View recyclerView = findViewById(R.id.suw_recycler_view);
+ if (recyclerView instanceof RecyclerView) {
+ mRecyclerMixin = new RecyclerMixin(this, (RecyclerView) recyclerView);
+ } else {
+ throw new IllegalStateException(
+ "SetupWizardRecyclerLayout should use a template with recycler view");
+ }
+ }
+
+ @Override
+ // Returning generic type is the common pattern used for findViewBy* methods
+ @SuppressWarnings("TypeParameterUnusedInFormals")
+ public <T extends View> T findManagedViewById(int id) {
+ final View header = mRecyclerMixin.getHeader();
+ if (header != null) {
+ final T view = header.findViewById(id);
+ if (view != null) {
+ return view;
+ }
+ }
+ return super.findViewById(id);
+ }
+
+ /** @deprecated Use {@link #setDividerInsets(int, int)} instead. */
+ @Deprecated
+ public void setDividerInset(int inset) {
+ mRecyclerMixin.setDividerInset(inset);
+ }
+
+ /**
+ * Sets the start inset of the divider. This will use the default divider drawable set in the
+ * theme and apply insets to it.
+ *
+ * @param start The number of pixels to inset on the "start" side of the list divider. Typically
+ * this will be either {@code @dimen/suw_items_icon_divider_inset} or
+ * {@code @dimen/suw_items_text_divider_inset}.
+ * @param end The number of pixels to inset on the "end" side of the list divider.
+ * @see RecyclerMixin#setDividerInsets(int, int)
+ */
+ public void setDividerInsets(int start, int end) {
+ mRecyclerMixin.setDividerInsets(start, end);
+ }
+
+ /** @deprecated Use {@link #getDividerInsetStart()} instead. */
+ @Deprecated
+ public int getDividerInset() {
+ return mRecyclerMixin.getDividerInset();
+ }
+
+ /** @see RecyclerMixin#getDividerInsetStart() */
+ public int getDividerInsetStart() {
+ return mRecyclerMixin.getDividerInsetStart();
+ }
+
+ /** @see RecyclerMixin#getDividerInsetEnd() */
+ public int getDividerInsetEnd() {
+ return mRecyclerMixin.getDividerInsetEnd();
+ }
+
+ /** @see RecyclerMixin#getDivider() */
+ public Drawable getDivider() {
+ return mRecyclerMixin.getDivider();
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/items/ItemViewHolder.java b/library/recyclerview/src/com/android/setupwizardlib/items/ItemViewHolder.java
index aeaba68..419e2aa 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/items/ItemViewHolder.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/items/ItemViewHolder.java
@@ -16,44 +16,42 @@
package com.android.setupwizardlib.items;
-import android.view.View;
-
import androidx.recyclerview.widget.RecyclerView;
-
+import android.view.View;
import com.android.setupwizardlib.DividerItemDecoration;
class ItemViewHolder extends RecyclerView.ViewHolder
- implements DividerItemDecoration.DividedViewHolder {
-
- private boolean mIsEnabled;
- private IItem mItem;
-
- ItemViewHolder(View itemView) {
- super(itemView);
- }
-
- @Override
- public boolean isDividerAllowedAbove() {
- return mIsEnabled;
- }
-
- @Override
- public boolean isDividerAllowedBelow() {
- return mIsEnabled;
- }
-
- public void setEnabled(boolean isEnabled) {
- mIsEnabled = isEnabled;
- itemView.setClickable(isEnabled);
- itemView.setEnabled(isEnabled);
- itemView.setFocusable(isEnabled);
- }
-
- public void setItem(IItem item) {
- mItem = item;
- }
-
- public IItem getItem() {
- return mItem;
- }
+ implements DividerItemDecoration.DividedViewHolder {
+
+ private boolean isEnabled;
+ private IItem item;
+
+ ItemViewHolder(View itemView) {
+ super(itemView);
+ }
+
+ @Override
+ public boolean isDividerAllowedAbove() {
+ return isEnabled;
+ }
+
+ @Override
+ public boolean isDividerAllowedBelow() {
+ return isEnabled;
+ }
+
+ public void setEnabled(boolean isEnabled) {
+ this.isEnabled = isEnabled;
+ itemView.setClickable(isEnabled);
+ itemView.setEnabled(isEnabled);
+ itemView.setFocusable(isEnabled);
+ }
+
+ public void setItem(IItem item) {
+ this.item = item;
+ }
+
+ public IItem getItem() {
+ return item;
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/items/RecyclerItemAdapter.java b/library/recyclerview/src/com/android/setupwizardlib/items/RecyclerItemAdapter.java
index 56c60e7..ee753b8 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/items/RecyclerItemAdapter.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/items/RecyclerItemAdapter.java
@@ -20,14 +20,12 @@ import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.setupwizardlib.R;
/**
@@ -36,217 +34,214 @@ import com.android.setupwizardlib.R;
* XML.
*/
public class RecyclerItemAdapter extends RecyclerView.Adapter<ItemViewHolder>
- implements ItemHierarchy.Observer {
+ implements ItemHierarchy.Observer {
- private static final String TAG = "RecyclerItemAdapter";
+ private static final String TAG = "RecyclerItemAdapter";
- /**
- * A view tag set by {@link View#setTag(Object)}. If set on the root view of a layout, it will
- * not create the default background for the list item. This means the item will not have ripple
- * touch feedback by default.
- */
- public static final String TAG_NO_BACKGROUND = "noBackground";
+ /**
+ * A view tag set by {@link View#setTag(Object)}. If set on the root view of a layout, it will not
+ * create the default background for the list item. This means the item will not have ripple touch
+ * feedback by default.
+ */
+ public static final String TAG_NO_BACKGROUND = "noBackground";
- /**
- * Listener for item selection in this adapter.
- */
- public interface OnItemSelectedListener {
-
- /**
- * Called when an item in this adapter is clicked.
- *
- * @param item The Item corresponding to the position being clicked.
- */
- void onItemSelected(IItem item);
- }
-
- private final ItemHierarchy mItemHierarchy;
- private OnItemSelectedListener mListener;
-
- public RecyclerItemAdapter(ItemHierarchy hierarchy) {
- mItemHierarchy = hierarchy;
- mItemHierarchy.registerObserver(this);
- }
+ /** Listener for item selection in this adapter. */
+ public interface OnItemSelectedListener {
/**
- * Gets the item at the given position.
+ * Called when an item in this adapter is clicked.
*
- * @see ItemHierarchy#getItemAt(int)
+ * @param item The Item corresponding to the position being clicked.
*/
- public IItem getItem(int position) {
- return mItemHierarchy.getItemAt(position);
- }
-
- @Override
- public long getItemId(int position) {
- IItem mItem = getItem(position);
- if (mItem instanceof AbstractItem) {
- final int id = ((AbstractItem) mItem).getId();
- return id > 0 ? id : RecyclerView.NO_ID;
- } else {
- return RecyclerView.NO_ID;
- }
- }
-
- @Override
- public int getItemCount() {
- return mItemHierarchy.getCount();
- }
-
- @Override
- public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
- final View view = inflater.inflate(viewType, parent, false);
- final ItemViewHolder viewHolder = new ItemViewHolder(view);
-
- final Object viewTag = view.getTag();
- if (!TAG_NO_BACKGROUND.equals(viewTag)) {
- final TypedArray typedArray = parent.getContext()
- .obtainStyledAttributes(R.styleable.SuwRecyclerItemAdapter);
- Drawable selectableItemBackground = typedArray.getDrawable(
- R.styleable.SuwRecyclerItemAdapter_android_selectableItemBackground);
- if (selectableItemBackground == null) {
- selectableItemBackground = typedArray.getDrawable(
- R.styleable.SuwRecyclerItemAdapter_selectableItemBackground);
- }
-
- Drawable background = view.getBackground();
- if (background == null) {
- background = typedArray.getDrawable(
- R.styleable.SuwRecyclerItemAdapter_android_colorBackground);
- }
-
- if (selectableItemBackground == null || background == null) {
- Log.e(TAG, "Cannot resolve required attributes."
- + " selectableItemBackground=" + selectableItemBackground
- + " background=" + background);
- } else {
- final Drawable[] layers = {background, selectableItemBackground};
- view.setBackgroundDrawable(new PatchedLayerDrawable(layers));
- }
-
- typedArray.recycle();
- }
-
- view.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- final IItem item = viewHolder.getItem();
- if (mListener != null && item != null && item.isEnabled()) {
- mListener.onItemSelected(item);
- }
+ void onItemSelected(IItem item);
+ }
+
+ private final ItemHierarchy itemHierarchy;
+ private OnItemSelectedListener listener;
+
+ public RecyclerItemAdapter(ItemHierarchy hierarchy) {
+ itemHierarchy = hierarchy;
+ itemHierarchy.registerObserver(this);
+ }
+
+ /**
+ * Gets the item at the given position.
+ *
+ * @see ItemHierarchy#getItemAt(int)
+ */
+ public IItem getItem(int position) {
+ return itemHierarchy.getItemAt(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ IItem mItem = getItem(position);
+ if (mItem instanceof AbstractItem) {
+ final int id = ((AbstractItem) mItem).getId();
+ return id > 0 ? id : RecyclerView.NO_ID;
+ } else {
+ return RecyclerView.NO_ID;
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return itemHierarchy.getCount();
+ }
+
+ @Override
+ public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+ final View view = inflater.inflate(viewType, parent, false);
+ final ItemViewHolder viewHolder = new ItemViewHolder(view);
+
+ final Object viewTag = view.getTag();
+ if (!TAG_NO_BACKGROUND.equals(viewTag)) {
+ final TypedArray typedArray =
+ parent.getContext().obtainStyledAttributes(R.styleable.SuwRecyclerItemAdapter);
+ Drawable selectableItemBackground =
+ typedArray.getDrawable(
+ R.styleable.SuwRecyclerItemAdapter_android_selectableItemBackground);
+ if (selectableItemBackground == null) {
+ selectableItemBackground =
+ typedArray.getDrawable(R.styleable.SuwRecyclerItemAdapter_selectableItemBackground);
+ }
+
+ Drawable background = view.getBackground();
+ if (background == null) {
+ background =
+ typedArray.getDrawable(R.styleable.SuwRecyclerItemAdapter_android_colorBackground);
+ }
+
+ if (selectableItemBackground == null || background == null) {
+ Log.e(
+ TAG,
+ "Cannot resolve required attributes."
+ + " selectableItemBackground="
+ + selectableItemBackground
+ + " background="
+ + background);
+ } else {
+ final Drawable[] layers = {background, selectableItemBackground};
+ view.setBackgroundDrawable(new PatchedLayerDrawable(layers));
+ }
+
+ typedArray.recycle();
+ }
+
+ view.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ final IItem item = viewHolder.getItem();
+ if (listener != null && item != null && item.isEnabled()) {
+ listener.onItemSelected(item);
}
+ }
});
- return viewHolder;
+ return viewHolder;
+ }
+
+ @Override
+ public void onBindViewHolder(ItemViewHolder holder, int position) {
+ final IItem item = getItem(position);
+ holder.setEnabled(item.isEnabled());
+ holder.setItem(item);
+ item.onBindView(holder.itemView);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ // Use layout resource as item view type. RecyclerView item type does not have to be
+ // contiguous.
+ IItem item = getItem(position);
+ return item.getLayoutResource();
+ }
+
+ @Override
+ public void onChanged(ItemHierarchy hierarchy) {
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onItemRangeChanged(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
+ notifyItemRangeChanged(positionStart, itemCount);
+ }
+
+ @Override
+ public void onItemRangeInserted(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
+ notifyItemRangeInserted(positionStart, itemCount);
+ }
+
+ @Override
+ public void onItemRangeMoved(
+ ItemHierarchy itemHierarchy, int fromPosition, int toPosition, int itemCount) {
+ // There is no notifyItemRangeMoved
+ // https://code.google.com/p/android/issues/detail?id=125984
+ if (itemCount == 1) {
+ notifyItemMoved(fromPosition, toPosition);
+ } else {
+ // If more than one, degenerate into the catch-all data set changed callback, since I'm
+ // not sure how recycler view handles multiple calls to notifyItemMoved (if the result
+ // is committed after every notification then naively calling
+ // notifyItemMoved(from + i, to + i) is wrong).
+ // Logging this in case this is a more common occurrence than expected.
+ Log.i(TAG, "onItemRangeMoved with more than one item");
+ notifyDataSetChanged();
+ }
+ }
+
+ @Override
+ public void onItemRangeRemoved(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
+ notifyItemRangeRemoved(positionStart, itemCount);
+ }
+
+ /**
+ * Find an item hierarchy within the root hierarchy.
+ *
+ * @see ItemHierarchy#findItemById(int)
+ */
+ public ItemHierarchy findItemById(int id) {
+ return itemHierarchy.findItemById(id);
+ }
+
+ /** Gets the root item hierarchy in this adapter. */
+ public ItemHierarchy getRootItemHierarchy() {
+ return itemHierarchy;
+ }
+
+ /**
+ * Sets the listener to listen for when user clicks on a item.
+ *
+ * @see OnItemSelectedListener
+ */
+ public void setOnItemSelectedListener(OnItemSelectedListener listener) {
+ this.listener = listener;
+ }
+
+ /**
+ * Before Lollipop, LayerDrawable always return true in getPadding, even if the children layers do
+ * not have any padding. Patch the implementation so that getPadding returns false if the padding
+ * is empty.
+ *
+ * <p>When getPadding is true, the padding of the view will be replaced by the padding of the
+ * drawable when {@link View#setBackgroundDrawable(Drawable)} is called. This patched class makes
+ * sure layer drawables without padding does not clear out original padding on the view.
+ */
+ @VisibleForTesting
+ static class PatchedLayerDrawable extends LayerDrawable {
+
+ /** {@inheritDoc} */
+ PatchedLayerDrawable(Drawable[] layers) {
+ super(layers);
}
@Override
- public void onBindViewHolder(ItemViewHolder holder, int position) {
- final IItem item = getItem(position);
- holder.setEnabled(item.isEnabled());
- holder.setItem(item);
- item.onBindView(holder.itemView);
- }
-
- @Override
- public int getItemViewType(int position) {
- // Use layout resource as item view type. RecyclerView item type does not have to be
- // contiguous.
- IItem item = getItem(position);
- return item.getLayoutResource();
- }
-
- @Override
- public void onChanged(ItemHierarchy hierarchy) {
- notifyDataSetChanged();
- }
-
- @Override
- public void onItemRangeChanged(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
- notifyItemRangeChanged(positionStart, itemCount);
- }
-
- @Override
- public void onItemRangeInserted(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
- notifyItemRangeInserted(positionStart, itemCount);
- }
-
- @Override
- public void onItemRangeMoved(ItemHierarchy itemHierarchy, int fromPosition, int toPosition,
- int itemCount) {
- // There is no notifyItemRangeMoved
- // https://code.google.com/p/android/issues/detail?id=125984
- if (itemCount == 1) {
- notifyItemMoved(fromPosition, toPosition);
- } else {
- // If more than one, degenerate into the catch-all data set changed callback, since I'm
- // not sure how recycler view handles multiple calls to notifyItemMoved (if the result
- // is committed after every notification then naively calling
- // notifyItemMoved(from + i, to + i) is wrong).
- // Logging this in case this is a more common occurrence than expected.
- Log.i(TAG, "onItemRangeMoved with more than one item");
- notifyDataSetChanged();
- }
- }
-
- @Override
- public void onItemRangeRemoved(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
- notifyItemRangeRemoved(positionStart, itemCount);
- }
-
- /**
- * Find an item hierarchy within the root hierarchy.
- *
- * @see ItemHierarchy#findItemById(int)
- */
- public ItemHierarchy findItemById(int id) {
- return mItemHierarchy.findItemById(id);
- }
-
- /**
- * Gets the root item hierarchy in this adapter.
- */
- public ItemHierarchy getRootItemHierarchy() {
- return mItemHierarchy;
- }
-
- /**
- * Sets the listener to listen for when user clicks on a item.
- *
- * @see OnItemSelectedListener
- */
- public void setOnItemSelectedListener(OnItemSelectedListener listener) {
- mListener = listener;
- }
-
- /**
- * Before Lollipop, LayerDrawable always return true in getPadding, even if the children layers
- * do not have any padding. Patch the implementation so that getPadding returns false if the
- * padding is empty.
- *
- * When getPadding is true, the padding of the view will be replaced by the padding of the
- * drawable when {@link View#setBackgroundDrawable(Drawable)} is called. This patched class
- * makes sure layer drawables without padding does not clear out original padding on the view.
- */
- @VisibleForTesting
- static class PatchedLayerDrawable extends LayerDrawable {
-
- /**
- * {@inheritDoc}
- */
- PatchedLayerDrawable(Drawable[] layers) {
- super(layers);
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- final boolean superHasPadding = super.getPadding(padding);
- return superHasPadding
- && !(padding.left == 0
- && padding.top == 0
- && padding.right == 0
- && padding.bottom == 0);
- }
+ public boolean getPadding(Rect padding) {
+ final boolean superHasPadding = super.getPadding(padding);
+ return superHasPadding
+ && !(padding.left == 0 && padding.top == 0 && padding.right == 0 && padding.bottom == 0);
}
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerMixin.java b/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerMixin.java
index 32e7bd8..a6c6526 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerMixin.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerMixin.java
@@ -21,16 +21,14 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
-import android.util.AttributeSet;
-import android.view.View;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-
+import android.util.AttributeSet;
+import android.view.View;
import com.android.setupwizardlib.DividerItemDecoration;
import com.android.setupwizardlib.R;
import com.android.setupwizardlib.TemplateLayout;
@@ -51,223 +49,208 @@ import com.android.setupwizardlib.view.HeaderRecyclerView.HeaderAdapter;
*/
public class RecyclerMixin implements Mixin {
- private TemplateLayout mTemplateLayout;
+ private final TemplateLayout templateLayout;
- @NonNull
- private final RecyclerView mRecyclerView;
+ @NonNull private final RecyclerView recyclerView;
- @Nullable
- private View mHeader;
+ @Nullable private View header;
- @NonNull
- private DividerItemDecoration mDividerDecoration;
+ @NonNull private DividerItemDecoration dividerDecoration;
- private Drawable mDefaultDivider;
- private Drawable mDivider;
+ private Drawable defaultDivider;
+ private Drawable divider;
- private int mDividerInsetStart;
- private int mDividerInsetEnd;
+ private int dividerInsetStart;
+ private int dividerInsetEnd;
- /**
- * Creates the RecyclerMixin. Unlike typical mixins which are created in the constructor, this
- * mixin should be called in {@link TemplateLayout#onTemplateInflated()}, which is called by
- * the super constructor, because the recycler view and the header needs to be made available
- * before other mixins from the super class.
- *
- * @param layout The layout this mixin belongs to.
- */
- public RecyclerMixin(@NonNull TemplateLayout layout, @NonNull RecyclerView recyclerView) {
- mTemplateLayout = layout;
+ /**
+ * Creates the RecyclerMixin. Unlike typical mixins which are created in the constructor, this
+ * mixin should be called in {@link TemplateLayout#onTemplateInflated()}, which is called by the
+ * super constructor, because the recycler view and the header needs to be made available before
+ * other mixins from the super class.
+ *
+ * @param layout The layout this mixin belongs to.
+ */
+ public RecyclerMixin(@NonNull TemplateLayout layout, @NonNull RecyclerView recyclerView) {
+ templateLayout = layout;
- mDividerDecoration = new DividerItemDecoration(mTemplateLayout.getContext());
+ dividerDecoration = new DividerItemDecoration(templateLayout.getContext());
- // The recycler view needs to be available
- mRecyclerView = recyclerView;
- mRecyclerView.setLayoutManager(new LinearLayoutManager(mTemplateLayout.getContext()));
+ // The recycler view needs to be available
+ this.recyclerView = recyclerView;
+ this.recyclerView.setLayoutManager(new LinearLayoutManager(templateLayout.getContext()));
- if (recyclerView instanceof HeaderRecyclerView) {
- mHeader = ((HeaderRecyclerView) recyclerView).getHeader();
- }
-
- mRecyclerView.addItemDecoration(mDividerDecoration);
+ if (recyclerView instanceof HeaderRecyclerView) {
+ header = ((HeaderRecyclerView) recyclerView).getHeader();
}
- /**
- * Parse XML attributes and configures this mixin and the recycler view accordingly. This should
- * be called from the constructor of the layout.
- *
- * @param attrs The {@link AttributeSet} as passed into the constructor. Can be null if the
- * layout was not created from XML.
- * @param defStyleAttr The default style attribute as passed into the layout constructor. Can be
- * 0 if it is not needed.
- */
- public void parseAttributes(@Nullable AttributeSet attrs, int defStyleAttr) {
- final Context context = mTemplateLayout.getContext();
- final TypedArray a = context.obtainStyledAttributes(
- attrs, R.styleable.SuwRecyclerMixin, defStyleAttr, 0);
-
- final int entries = a.getResourceId(R.styleable.SuwRecyclerMixin_android_entries, 0);
- if (entries != 0) {
- final ItemHierarchy inflated = new ItemInflater(context).inflate(entries);
- final RecyclerItemAdapter adapter = new RecyclerItemAdapter(inflated);
- adapter.setHasStableIds(a.getBoolean(
- R.styleable.SuwRecyclerMixin_suwHasStableIds, false));
- setAdapter(adapter);
- }
- int dividerInset =
- a.getDimensionPixelSize(R.styleable.SuwRecyclerMixin_suwDividerInset, -1);
- if (dividerInset != -1) {
- setDividerInset(dividerInset);
- } else {
- int dividerInsetStart =
- a.getDimensionPixelSize(R.styleable.SuwRecyclerMixin_suwDividerInsetStart, 0);
- int dividerInsetEnd =
- a.getDimensionPixelSize(R.styleable.SuwRecyclerMixin_suwDividerInsetEnd, 0);
- setDividerInsets(dividerInsetStart, dividerInsetEnd);
- }
-
- a.recycle();
+ this.recyclerView.addItemDecoration(dividerDecoration);
+ }
+
+ /**
+ * Parse XML attributes and configures this mixin and the recycler view accordingly. This should
+ * be called from the constructor of the layout.
+ *
+ * @param attrs The {@link AttributeSet} as passed into the constructor. Can be null if the layout
+ * was not created from XML.
+ * @param defStyleAttr The default style attribute as passed into the layout constructor. Can be 0
+ * if it is not needed.
+ */
+ public void parseAttributes(@Nullable AttributeSet attrs, int defStyleAttr) {
+ final Context context = templateLayout.getContext();
+ final TypedArray a =
+ context.obtainStyledAttributes(attrs, R.styleable.SuwRecyclerMixin, defStyleAttr, 0);
+
+ final int entries = a.getResourceId(R.styleable.SuwRecyclerMixin_android_entries, 0);
+ if (entries != 0) {
+ final ItemHierarchy inflated = new ItemInflater(context).inflate(entries);
+ final RecyclerItemAdapter adapter = new RecyclerItemAdapter(inflated);
+ adapter.setHasStableIds(a.getBoolean(R.styleable.SuwRecyclerMixin_suwHasStableIds, false));
+ setAdapter(adapter);
}
-
- /**
- * @return The recycler view contained in the layout, as marked by
- * {@code @id/suw_recycler_view}. This will return {@code null} if the recycler view
- * doesn't exist in the layout.
- */
- @SuppressWarnings("NullableProblems") // If clients guarantee that the template has a recycler
- // view, and call this after the template is inflated,
- // this will not return null.
- public RecyclerView getRecyclerView() {
- return mRecyclerView;
+ int dividerInset = a.getDimensionPixelSize(R.styleable.SuwRecyclerMixin_suwDividerInset, -1);
+ if (dividerInset != -1) {
+ setDividerInset(dividerInset);
+ } else {
+ int dividerInsetStart =
+ a.getDimensionPixelSize(R.styleable.SuwRecyclerMixin_suwDividerInsetStart, 0);
+ int dividerInsetEnd =
+ a.getDimensionPixelSize(R.styleable.SuwRecyclerMixin_suwDividerInsetEnd, 0);
+ setDividerInsets(dividerInsetStart, dividerInsetEnd);
}
- /**
- * Gets the header view of the recycler layout. This is useful for other mixins if they need to
- * access views within the header, usually via {@link TemplateLayout#findManagedViewById(int)}.
- */
- @SuppressWarnings("NullableProblems") // If clients guarantee that the template has a header,
- // this call will not return null.
- public View getHeader() {
- return mHeader;
+ a.recycle();
+ }
+
+ /**
+ * @return The recycler view contained in the layout, as marked by {@code @id/suw_recycler_view}.
+ * This will return {@code null} if the recycler view doesn't exist in the layout.
+ */
+ @SuppressWarnings("NullableProblems") // If clients guarantee that the template has a recycler
+ // view, and call this after the template is inflated,
+ // this will not return null.
+ public RecyclerView getRecyclerView() {
+ return recyclerView;
+ }
+
+ /**
+ * Gets the header view of the recycler layout. This is useful for other mixins if they need to
+ * access views within the header, usually via {@link TemplateLayout#findManagedViewById(int)}.
+ */
+ @SuppressWarnings("NullableProblems") // If clients guarantee that the template has a header,
+ // this call will not return null.
+ public View getHeader() {
+ return header;
+ }
+
+ /**
+ * Recycler mixin needs to update the dividers if the layout direction has changed. This method
+ * should be called when {@link View#onLayout(boolean, int, int, int, int)} of the template is
+ * called.
+ */
+ public void onLayout() {
+ if (divider == null) {
+ // Update divider in case layout direction has just been resolved
+ updateDivider();
}
-
- /**
- * Recycler mixin needs to update the dividers if the layout direction has changed. This method
- * should be called when {@link View#onLayout(boolean, int, int, int, int)} of the template
- * is called.
- */
- public void onLayout() {
- if (mDivider == null) {
- // Update divider in case layout direction has just been resolved
- updateDivider();
- }
+ }
+
+ /**
+ * Gets the adapter of the recycler view in this layout. If the adapter includes a header, this
+ * method will unwrap it and return the underlying adapter.
+ *
+ * @return The adapter, or {@code null} if the recycler view has no adapter.
+ */
+ public Adapter<? extends ViewHolder> getAdapter() {
+ @SuppressWarnings("unchecked") // RecyclerView.getAdapter returns raw type :(
+ final RecyclerView.Adapter<? extends ViewHolder> adapter = recyclerView.getAdapter();
+ if (adapter instanceof HeaderAdapter) {
+ return ((HeaderAdapter<? extends ViewHolder>) adapter).getWrappedAdapter();
}
-
- /**
- * Gets the adapter of the recycler view in this layout. If the adapter includes a header,
- * this method will unwrap it and return the underlying adapter.
- *
- * @return The adapter, or {@code null} if the recycler view has no adapter.
- */
- public Adapter<? extends ViewHolder> getAdapter() {
- @SuppressWarnings("unchecked") // RecyclerView.getAdapter returns raw type :(
- final RecyclerView.Adapter<? extends ViewHolder> adapter = mRecyclerView.getAdapter();
- if (adapter instanceof HeaderAdapter) {
- return ((HeaderAdapter<? extends ViewHolder>) adapter).getWrappedAdapter();
- }
- return adapter;
+ return adapter;
+ }
+
+ /** Sets the adapter on the recycler view in this layout. */
+ public void setAdapter(Adapter<? extends ViewHolder> adapter) {
+ recyclerView.setAdapter(adapter);
+ }
+
+ /** @deprecated Use {@link #setDividerInsets(int, int)} instead. */
+ @Deprecated
+ public void setDividerInset(int inset) {
+ setDividerInsets(inset, 0);
+ }
+
+ /**
+ * Sets the start inset of the divider. This will use the default divider drawable set in the
+ * theme and apply insets to it.
+ *
+ * @param start The number of pixels to inset on the "start" side of the list divider. Typically
+ * this will be either {@code @dimen/suw_items_glif_icon_divider_inset} or
+ * {@code @dimen/suw_items_glif_text_divider_inset}.
+ * @param end The number of pixels to inset on the "end" side of the list divider.
+ */
+ public void setDividerInsets(int start, int end) {
+ dividerInsetStart = start;
+ dividerInsetEnd = end;
+ updateDivider();
+ }
+
+ /**
+ * @return The number of pixels inset on the start side of the divider.
+ * @deprecated This is the same as {@link #getDividerInsetStart()}. Use that instead.
+ */
+ @Deprecated
+ public int getDividerInset() {
+ return getDividerInsetStart();
+ }
+
+ /** @return The number of pixels inset on the start side of the divider. */
+ public int getDividerInsetStart() {
+ return dividerInsetStart;
+ }
+
+ /** @return The number of pixels inset on the end side of the divider. */
+ public int getDividerInsetEnd() {
+ return dividerInsetEnd;
+ }
+
+ private void updateDivider() {
+ boolean shouldUpdate = true;
+ if (Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
+ shouldUpdate = templateLayout.isLayoutDirectionResolved();
}
-
- /**
- * Sets the adapter on the recycler view in this layout.
- */
- public void setAdapter(Adapter<? extends ViewHolder> adapter) {
- mRecyclerView.setAdapter(adapter);
- }
-
- /**
- * @deprecated Use {@link #setDividerInsets(int, int)} instead.
- */
- @Deprecated
- public void setDividerInset(int inset) {
- setDividerInsets(inset, 0);
- }
-
- /**
- * Sets the start inset of the divider. This will use the default divider drawable set in the
- * theme and apply insets to it.
- *
- * @param start The number of pixels to inset on the "start" side of the list divider. Typically
- * this will be either {@code @dimen/suw_items_glif_icon_divider_inset} or
- * {@code @dimen/suw_items_glif_text_divider_inset}.
- * @param end The number of pixels to inset on the "end" side of the list divider.
- */
- public void setDividerInsets(int start, int end) {
- mDividerInsetStart = start;
- mDividerInsetEnd = end;
- updateDivider();
- }
-
- /**
- * @return The number of pixels inset on the start side of the divider.
- * @deprecated This is the same as {@link #getDividerInsetStart()}. Use that instead.
- */
- @Deprecated
- public int getDividerInset() {
- return getDividerInsetStart();
- }
-
- /**
- * @return The number of pixels inset on the start side of the divider.
- */
- public int getDividerInsetStart() {
- return mDividerInsetStart;
- }
-
- /**
- * @return The number of pixels inset on the end side of the divider.
- */
- public int getDividerInsetEnd() {
- return mDividerInsetEnd;
- }
-
- private void updateDivider() {
- boolean shouldUpdate = true;
- if (Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
- shouldUpdate = mTemplateLayout.isLayoutDirectionResolved();
- }
- if (shouldUpdate) {
- if (mDefaultDivider == null) {
- mDefaultDivider = mDividerDecoration.getDivider();
- }
- mDivider = DrawableLayoutDirectionHelper.createRelativeInsetDrawable(
- mDefaultDivider,
- mDividerInsetStart /* start */,
- 0 /* top */,
- mDividerInsetEnd /* end */,
- 0 /* bottom */,
- mTemplateLayout);
- mDividerDecoration.setDivider(mDivider);
- }
- }
-
- /**
- * @return The drawable used as the divider.
- */
- public Drawable getDivider() {
- return mDivider;
- }
-
- /**
- * Sets the divider item decoration directly. This is a low level method which should be used
- * only if custom divider behavior is needed, for example if the divider should be shown /
- * hidden in some specific cases for view holders that cannot implement
- * {@link com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}.
- */
- public void setDividerItemDecoration(@NonNull DividerItemDecoration decoration) {
- mRecyclerView.removeItemDecoration(mDividerDecoration);
- mDividerDecoration = decoration;
- mRecyclerView.addItemDecoration(mDividerDecoration);
- updateDivider();
+ if (shouldUpdate) {
+ if (defaultDivider == null) {
+ defaultDivider = dividerDecoration.getDivider();
+ }
+ divider =
+ DrawableLayoutDirectionHelper.createRelativeInsetDrawable(
+ defaultDivider,
+ dividerInsetStart /* start */,
+ 0 /* top */,
+ dividerInsetEnd /* end */,
+ 0 /* bottom */,
+ templateLayout);
+ dividerDecoration.setDivider(divider);
}
+ }
+
+ /** @return The drawable used as the divider. */
+ public Drawable getDivider() {
+ return divider;
+ }
+
+ /**
+ * Sets the divider item decoration directly. This is a low level method which should be used only
+ * if custom divider behavior is needed, for example if the divider should be shown / hidden in
+ * some specific cases for view holders that cannot implement {@link
+ * com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}.
+ */
+ public void setDividerItemDecoration(@NonNull DividerItemDecoration decoration) {
+ recyclerView.removeItemDecoration(dividerDecoration);
+ dividerDecoration = decoration;
+ recyclerView.addItemDecoration(dividerDecoration);
+ updateDivider();
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegate.java b/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegate.java
index bfe8df2..8838c44 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegate.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegate.java
@@ -16,12 +16,10 @@
package com.android.setupwizardlib.template;
-import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
-
+import android.util.Log;
import com.android.setupwizardlib.template.RequireScrollMixin.ScrollHandlingDelegate;
/**
@@ -30,55 +28,53 @@ import com.android.setupwizardlib.template.RequireScrollMixin.ScrollHandlingDele
*/
public class RecyclerViewScrollHandlingDelegate implements ScrollHandlingDelegate {
- private static final String TAG = "RVRequireScrollMixin";
+ private static final String TAG = "RVRequireScrollMixin";
- @Nullable
- private final RecyclerView mRecyclerView;
+ @Nullable private final RecyclerView recyclerView;
- @NonNull
- private final RequireScrollMixin mRequireScrollMixin;
+ @NonNull private final RequireScrollMixin requireScrollMixin;
- public RecyclerViewScrollHandlingDelegate(
- @NonNull RequireScrollMixin requireScrollMixin,
- @Nullable RecyclerView recyclerView) {
- mRequireScrollMixin = requireScrollMixin;
- mRecyclerView = recyclerView;
- }
+ public RecyclerViewScrollHandlingDelegate(
+ @NonNull RequireScrollMixin requireScrollMixin, @Nullable RecyclerView recyclerView) {
+ this.requireScrollMixin = requireScrollMixin;
+ this.recyclerView = recyclerView;
+ }
- private boolean canScrollDown() {
- if (mRecyclerView != null) {
- // Compatibility implementation of View#canScrollVertically
- final int offset = mRecyclerView.computeVerticalScrollOffset();
- final int range = mRecyclerView.computeVerticalScrollRange()
- - mRecyclerView.computeVerticalScrollExtent();
- return range != 0 && offset < range - 1;
- }
- return false;
+ private boolean canScrollDown() {
+ if (recyclerView != null) {
+ // Compatibility implementation of View#canScrollVertically
+ final int offset = recyclerView.computeVerticalScrollOffset();
+ final int range =
+ recyclerView.computeVerticalScrollRange() - recyclerView.computeVerticalScrollExtent();
+ return range != 0 && offset < range - 1;
}
+ return false;
+ }
- @Override
- public void startListening() {
- if (mRecyclerView != null) {
- mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
- @Override
- public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
- mRequireScrollMixin.notifyScrollabilityChange(canScrollDown());
- }
- });
-
- if (canScrollDown()) {
- mRequireScrollMixin.notifyScrollabilityChange(true);
+ @Override
+ public void startListening() {
+ if (this.recyclerView != null) {
+ this.recyclerView.addOnScrollListener(
+ new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ requireScrollMixin.notifyScrollabilityChange(canScrollDown());
}
- } else {
- Log.w(TAG, "Cannot require scroll. Recycler view is null.");
- }
+ });
+
+ if (canScrollDown()) {
+ requireScrollMixin.notifyScrollabilityChange(true);
+ }
+ } else {
+ Log.w(TAG, "Cannot require scroll. Recycler view is null.");
}
+ }
- @Override
- public void pageScrollDown() {
- if (mRecyclerView != null) {
- final int height = mRecyclerView.getHeight();
- mRecyclerView.smoothScrollBy(0, height);
- }
+ @Override
+ public void pageScrollDown() {
+ if (recyclerView != null) {
+ final int height = recyclerView.getHeight();
+ recyclerView.smoothScrollBy(0, height);
}
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/view/HeaderRecyclerView.java b/library/recyclerview/src/com/android/setupwizardlib/view/HeaderRecyclerView.java
index 0304b65..3808e11 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/view/HeaderRecyclerView.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/view/HeaderRecyclerView.java
@@ -19,259 +19,257 @@ package com.android.setupwizardlib.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
-
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.setupwizardlib.DividerItemDecoration;
import com.android.setupwizardlib.R;
/**
* A RecyclerView that can display a header item at the start of the list. The header can be set by
- * {@code app:suwHeader} in XML. Note that the header will not be inflated until a layout manager
- * is set.
+ * {@code app:suwHeader} in XML. Note that the header will not be inflated until a layout manager is
+ * set.
*/
public class HeaderRecyclerView extends RecyclerView {
- private static class HeaderViewHolder extends ViewHolder
- implements DividerItemDecoration.DividedViewHolder {
-
- HeaderViewHolder(View itemView) {
- super(itemView);
- }
-
- @Override
- public boolean isDividerAllowedAbove() {
- return false;
- }
+ private static class HeaderViewHolder extends ViewHolder
+ implements DividerItemDecoration.DividedViewHolder {
- @Override
- public boolean isDividerAllowedBelow() {
- return false;
- }
+ HeaderViewHolder(View itemView) {
+ super(itemView);
}
- /**
- * An adapter that can optionally add one header item to the RecyclerView.
- *
- * @param <CVH> Type of the content view holder. i.e. view holder type of the wrapped adapter.
- */
- public static class HeaderAdapter<CVH extends ViewHolder>
- extends RecyclerView.Adapter<ViewHolder> {
-
- private static final int HEADER_VIEW_TYPE = Integer.MAX_VALUE;
+ @Override
+ public boolean isDividerAllowedAbove() {
+ return false;
+ }
- private RecyclerView.Adapter<CVH> mAdapter;
- private View mHeader;
+ @Override
+ public boolean isDividerAllowedBelow() {
+ return false;
+ }
+ }
- private final AdapterDataObserver mObserver = new AdapterDataObserver() {
+ /**
+ * An adapter that can optionally add one header item to the RecyclerView.
+ *
+ * @param <CVH> Type of the content view holder. i.e. view holder type of the wrapped adapter.
+ */
+ public static class HeaderAdapter<CVH extends ViewHolder>
+ extends RecyclerView.Adapter<ViewHolder> {
- @Override
- public void onChanged() {
- notifyDataSetChanged();
- }
+ private static final int HEADER_VIEW_TYPE = Integer.MAX_VALUE;
- @Override
- public void onItemRangeChanged(int positionStart, int itemCount) {
- if (mHeader != null) {
- positionStart++;
- }
- notifyItemRangeChanged(positionStart, itemCount);
- }
+ private final RecyclerView.Adapter<CVH> adapter;
+ private View header;
- @Override
- public void onItemRangeInserted(int positionStart, int itemCount) {
- if (mHeader != null) {
- positionStart++;
- }
- notifyItemRangeInserted(positionStart, itemCount);
- }
+ private final AdapterDataObserver observer =
+ new AdapterDataObserver() {
- @Override
- public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
- if (mHeader != null) {
- fromPosition++;
- toPosition++;
- }
- // Why is there no notifyItemRangeMoved?
- for (int i = 0; i < itemCount; i++) {
- notifyItemMoved(fromPosition + i, toPosition + i);
- }
- }
+ @Override
+ public void onChanged() {
+ notifyDataSetChanged();
+ }
- @Override
- public void onItemRangeRemoved(int positionStart, int itemCount) {
- if (mHeader != null) {
- positionStart++;
- }
- notifyItemRangeRemoved(positionStart, itemCount);
+ @Override
+ public void onItemRangeChanged(int positionStart, int itemCount) {
+ if (header != null) {
+ positionStart++;
}
- };
-
- public HeaderAdapter(RecyclerView.Adapter<CVH> adapter) {
- mAdapter = adapter;
- mAdapter.registerAdapterDataObserver(mObserver);
- setHasStableIds(mAdapter.hasStableIds());
- }
+ notifyItemRangeChanged(positionStart, itemCount);
+ }
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- // Returning the same view (mHeader) results in crash ".. but view is not a real child."
- // The framework creates more than one instance of header because of "disappear"
- // animations applied on the header and this necessitates creation of another header
- // view to use after the animation. We work around this restriction by returning an
- // empty FrameLayout to which the header is attached using #onBindViewHolder method.
- if (viewType == HEADER_VIEW_TYPE) {
- FrameLayout frameLayout = new FrameLayout(parent.getContext());
- FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.WRAP_CONTENT);
- frameLayout.setLayoutParams(params);
- return new HeaderViewHolder(frameLayout);
- } else {
- return mAdapter.onCreateViewHolder(parent, viewType);
+ @Override
+ public void onItemRangeInserted(int positionStart, int itemCount) {
+ if (header != null) {
+ positionStart++;
}
- }
-
- @Override
- @SuppressWarnings("unchecked") // Non-header position always return type CVH
- public void onBindViewHolder(ViewHolder holder, int position) {
- if (mHeader != null) {
- position--;
+ notifyItemRangeInserted(positionStart, itemCount);
+ }
+
+ @Override
+ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
+ if (header != null) {
+ fromPosition++;
+ toPosition++;
}
-
- if (holder instanceof HeaderViewHolder) {
- if (mHeader == null) {
- throw new IllegalStateException("HeaderViewHolder cannot find mHeader");
- }
- if (mHeader.getParent() != null) {
- ((ViewGroup) mHeader.getParent()).removeView(mHeader);
- }
- FrameLayout mHeaderParent = (FrameLayout) holder.itemView;
- mHeaderParent.addView(mHeader);
- } else {
- mAdapter.onBindViewHolder((CVH) holder, position);
+ // Why is there no notifyItemRangeMoved?
+ for (int i = 0; i < itemCount; i++) {
+ notifyItemMoved(fromPosition + i, toPosition + i);
}
- }
+ }
- @Override
- public int getItemViewType(int position) {
- if (mHeader != null) {
- position--;
+ @Override
+ public void onItemRangeRemoved(int positionStart, int itemCount) {
+ if (header != null) {
+ positionStart++;
}
- if (position < 0) {
- return HEADER_VIEW_TYPE;
- }
- return mAdapter.getItemViewType(position);
- }
-
- @Override
- public int getItemCount() {
- int count = mAdapter.getItemCount();
- if (mHeader != null) {
- count++;
- }
- return count;
- }
-
- @Override
- public long getItemId(int position) {
- if (mHeader != null) {
- position--;
- }
- if (position < 0) {
- return Long.MAX_VALUE;
- }
- return mAdapter.getItemId(position);
- }
-
- public void setHeader(View header) {
- mHeader = header;
- }
-
- public RecyclerView.Adapter<CVH> getWrappedAdapter() {
- return mAdapter;
- }
- }
-
- private View mHeader;
- private int mHeaderRes;
+ notifyItemRangeRemoved(positionStart, itemCount);
+ }
+ };
- public HeaderRecyclerView(Context context) {
- super(context);
- init(null, 0);
+ public HeaderAdapter(RecyclerView.Adapter<CVH> adapter) {
+ this.adapter = adapter;
+ this.adapter.registerAdapterDataObserver(observer);
+ setHasStableIds(this.adapter.hasStableIds());
}
- public HeaderRecyclerView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(attrs, 0);
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ // Returning the same view (header) results in crash ".. but view is not a real child."
+ // The framework creates more than one instance of header because of "disappear"
+ // animations applied on the header and this necessitates creation of another header
+ // view to use after the animation. We work around this restriction by returning an
+ // empty FrameLayout to which the header is attached using #onBindViewHolder method.
+ if (viewType == HEADER_VIEW_TYPE) {
+ FrameLayout frameLayout = new FrameLayout(parent.getContext());
+ FrameLayout.LayoutParams params =
+ new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
+ frameLayout.setLayoutParams(params);
+ return new HeaderViewHolder(frameLayout);
+ } else {
+ return adapter.onCreateViewHolder(parent, viewType);
+ }
}
- public HeaderRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(attrs, defStyleAttr);
+ @Override
+ @SuppressWarnings("unchecked") // Non-header position always return type CVH
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ if (header != null) {
+ position--;
+ }
+
+ if (holder instanceof HeaderViewHolder) {
+ if (header == null) {
+ throw new IllegalStateException("HeaderViewHolder cannot find mHeader");
+ }
+ if (header.getParent() != null) {
+ ((ViewGroup) header.getParent()).removeView(header);
+ }
+ FrameLayout mHeaderParent = (FrameLayout) holder.itemView;
+ mHeaderParent.addView(header);
+ } else {
+ adapter.onBindViewHolder((CVH) holder, position);
+ }
}
- private void init(AttributeSet attrs, int defStyleAttr) {
- final TypedArray a = getContext().obtainStyledAttributes(attrs,
- R.styleable.SuwHeaderRecyclerView, defStyleAttr, 0);
- mHeaderRes = a.getResourceId(R.styleable.SuwHeaderRecyclerView_suwHeader, 0);
- a.recycle();
+ @Override
+ public int getItemViewType(int position) {
+ if (header != null) {
+ position--;
+ }
+ if (position < 0) {
+ return HEADER_VIEW_TYPE;
+ }
+ return adapter.getItemViewType(position);
}
@Override
- public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
- super.onInitializeAccessibilityEvent(event);
-
- // Decoration-only headers should not count as an item for accessibility, adjust the
- // accessibility event to account for that.
- final int numberOfHeaders = mHeader != null ? 1 : 0;
- event.setItemCount(event.getItemCount() - numberOfHeaders);
- event.setFromIndex(Math.max(event.getFromIndex() - numberOfHeaders, 0));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- event.setToIndex(Math.max(event.getToIndex() - numberOfHeaders, 0));
- }
+ public int getItemCount() {
+ int count = adapter.getItemCount();
+ if (header != null) {
+ count++;
+ }
+ return count;
}
- /**
- * Gets the header view of this RecyclerView, or {@code null} if there are no headers.
- */
- public View getHeader() {
- return mHeader;
+ @Override
+ public long getItemId(int position) {
+ if (header != null) {
+ position--;
+ }
+ if (position < 0) {
+ return Long.MAX_VALUE;
+ }
+ return adapter.getItemId(position);
}
- /**
- * Set the view to use as the header of this recycler view.
- * Note: This must be called before setAdapter.
- */
public void setHeader(View header) {
- mHeader = header;
+ this.header = header;
}
- @Override
- public void setLayoutManager(LayoutManager layout) {
- super.setLayoutManager(layout);
- if (layout != null && mHeader == null && mHeaderRes != 0) {
- // Inflating a child view requires the layout manager to be set. Check here to see if
- // any header item is specified in XML and inflate them.
- final LayoutInflater inflater = LayoutInflater.from(getContext());
- mHeader = inflater.inflate(mHeaderRes, this, false);
- }
+ public RecyclerView.Adapter<CVH> getWrappedAdapter() {
+ return adapter;
}
-
- @Override
- @SuppressWarnings("rawtypes,unchecked") // RecyclerView.setAdapter uses raw type :(
- public void setAdapter(Adapter adapter) {
- if (mHeader != null && adapter != null) {
- final HeaderAdapter headerAdapter = new HeaderAdapter(adapter);
- headerAdapter.setHeader(mHeader);
- adapter = headerAdapter;
- }
- super.setAdapter(adapter);
+ }
+
+ private View header;
+ private int headerRes;
+
+ public HeaderRecyclerView(Context context) {
+ super(context);
+ init(null, 0);
+ }
+
+ public HeaderRecyclerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs, 0);
+ }
+
+ public HeaderRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs, defStyleAttr);
+ }
+
+ private void init(AttributeSet attrs, int defStyleAttr) {
+ final TypedArray a =
+ getContext()
+ .obtainStyledAttributes(attrs, R.styleable.SuwHeaderRecyclerView, defStyleAttr, 0);
+ headerRes = a.getResourceId(R.styleable.SuwHeaderRecyclerView_suwHeader, 0);
+ a.recycle();
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+
+ // Decoration-only headers should not count as an item for accessibility, adjust the
+ // accessibility event to account for that.
+ final int numberOfHeaders = header != null ? 1 : 0;
+ event.setItemCount(event.getItemCount() - numberOfHeaders);
+ event.setFromIndex(Math.max(event.getFromIndex() - numberOfHeaders, 0));
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ event.setToIndex(Math.max(event.getToIndex() - numberOfHeaders, 0));
+ }
+ }
+
+ /** Gets the header view of this RecyclerView, or {@code null} if there are no headers. */
+ public View getHeader() {
+ return header;
+ }
+
+ /**
+ * Set the view to use as the header of this recycler view. Note: This must be called before
+ * setAdapter.
+ */
+ public void setHeader(View header) {
+ this.header = header;
+ }
+
+ @Override
+ public void setLayoutManager(LayoutManager layout) {
+ super.setLayoutManager(layout);
+ if (layout != null && header == null && headerRes != 0) {
+ // Inflating a child view requires the layout manager to be set. Check here to see if
+ // any header item is specified in XML and inflate them.
+ final LayoutInflater inflater = LayoutInflater.from(getContext());
+ header = inflater.inflate(headerRes, this, false);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes,unchecked") // RecyclerView.setAdapter uses raw type :(
+ public void setAdapter(Adapter adapter) {
+ if (header != null && adapter != null) {
+ final HeaderAdapter headerAdapter = new HeaderAdapter(adapter);
+ headerAdapter.setHeader(header);
+ adapter = headerAdapter;
}
+ super.setAdapter(adapter);
+ }
}
diff --git a/library/recyclerview/src/com/android/setupwizardlib/view/StickyHeaderRecyclerView.java b/library/recyclerview/src/com/android/setupwizardlib/view/StickyHeaderRecyclerView.java
index d51ea56..a5fa69c 100644
--- a/library/recyclerview/src/com/android/setupwizardlib/view/StickyHeaderRecyclerView.java
+++ b/library/recyclerview/src/com/android/setupwizardlib/view/StickyHeaderRecyclerView.java
@@ -32,112 +32,114 @@ import android.view.WindowInsets;
* to be drawn when the sticky element hits the top of the view.
*
* <p>There are a few things to note:
+ *
* <ol>
* <li>The view does not work well with padding. b/16190933
* <li>If fitsSystemWindows is true, then this will offset the sticking position by the height of
- * the system decorations at the top of the screen.
+ * the system decorations at the top of the screen.
* </ol>
*/
public class StickyHeaderRecyclerView extends HeaderRecyclerView {
- private View mSticky;
- private int mStatusBarInset = 0;
- private RectF mStickyRect = new RectF();
+ private View sticky;
+ private int statusBarInset = 0;
+ private final RectF stickyRect = new RectF();
- public StickyHeaderRecyclerView(Context context) {
- super(context);
- }
+ public StickyHeaderRecyclerView(Context context) {
+ super(context);
+ }
- public StickyHeaderRecyclerView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
+ public StickyHeaderRecyclerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
- public StickyHeaderRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
+ public StickyHeaderRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- if (mSticky == null) {
- updateStickyView();
- }
- if (mSticky != null) {
- final View headerView = getHeader();
- if (headerView != null && headerView.getHeight() == 0) {
- headerView.layout(0, -headerView.getMeasuredHeight(),
- headerView.getMeasuredWidth(), 0);
- }
- }
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (sticky == null) {
+ updateStickyView();
+ }
+ if (sticky != null) {
+ final View headerView = getHeader();
+ if (headerView != null && headerView.getHeight() == 0) {
+ headerView.layout(0, -headerView.getMeasuredHeight(), headerView.getMeasuredWidth(), 0);
+ }
}
+ }
- @Override
- protected void onMeasure(int widthSpec, int heightSpec) {
- super.onMeasure(widthSpec, heightSpec);
- if (mSticky != null) {
- measureChild(getHeader(), widthSpec, heightSpec);
- }
+ @Override
+ protected void onMeasure(int widthSpec, int heightSpec) {
+ super.onMeasure(widthSpec, heightSpec);
+ if (sticky != null) {
+ measureChild(getHeader(), widthSpec, heightSpec);
}
+ }
- /**
- * Call this method when the "sticky" view has changed, so this view can update its internal
- * states as well.
- */
- public void updateStickyView() {
- final View header = getHeader();
- if (header != null) {
- mSticky = header.findViewWithTag("sticky");
- }
+ /**
+ * Call this method when the "sticky" view has changed, so this view can update its internal
+ * states as well.
+ */
+ public void updateStickyView() {
+ final View header = getHeader();
+ if (header != null) {
+ sticky = header.findViewWithTag("sticky");
}
+ }
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
- if (mSticky != null) {
- final View headerView = getHeader();
- final int saveCount = canvas.save();
- // The view to draw when sticking to the top
- final View drawTarget = headerView != null ? headerView : mSticky;
- // The offset to draw the view at when sticky
- final int drawOffset = headerView != null ? mSticky.getTop() : 0;
- // Position of the draw target, relative to the outside of the scrollView
- final int drawTop = drawTarget.getTop();
- if (drawTop + drawOffset < mStatusBarInset || !drawTarget.isShown()) {
- // RecyclerView does not translate the canvas, so we can simply draw at the top
- mStickyRect.set(0, -drawOffset + mStatusBarInset, drawTarget.getWidth(),
- drawTarget.getHeight() - drawOffset + mStatusBarInset);
- canvas.translate(0, mStickyRect.top);
- canvas.clipRect(0, 0, drawTarget.getWidth(), drawTarget.getHeight());
- drawTarget.draw(canvas);
- } else {
- mStickyRect.setEmpty();
- }
- canvas.restoreToCount(saveCount);
- }
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ if (sticky != null) {
+ final View headerView = getHeader();
+ final int saveCount = canvas.save();
+ // The view to draw when sticking to the top
+ final View drawTarget = headerView != null ? headerView : sticky;
+ // The offset to draw the view at when sticky
+ final int drawOffset = headerView != null ? sticky.getTop() : 0;
+ // Position of the draw target, relative to the outside of the scrollView
+ final int drawTop = drawTarget.getTop();
+ if (drawTop + drawOffset < statusBarInset || !drawTarget.isShown()) {
+ // RecyclerView does not translate the canvas, so we can simply draw at the top
+ stickyRect.set(
+ 0,
+ -drawOffset + statusBarInset,
+ drawTarget.getWidth(),
+ drawTarget.getHeight() - drawOffset + statusBarInset);
+ canvas.translate(0, stickyRect.top);
+ canvas.clipRect(0, 0, drawTarget.getWidth(), drawTarget.getHeight());
+ drawTarget.draw(canvas);
+ } else {
+ stickyRect.setEmpty();
+ }
+ canvas.restoreToCount(saveCount);
}
+ }
- @Override
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- if (getFitsSystemWindows()) {
- mStatusBarInset = insets.getSystemWindowInsetTop();
- insets.replaceSystemWindowInsets(
- insets.getSystemWindowInsetLeft(),
- 0, /* top */
- insets.getSystemWindowInsetRight(),
- insets.getSystemWindowInsetBottom()
- );
- }
- return insets;
+ @Override
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ if (getFitsSystemWindows()) {
+ statusBarInset = insets.getSystemWindowInsetTop();
+ insets.replaceSystemWindowInsets(
+ insets.getSystemWindowInsetLeft(),
+ 0, /* top */
+ insets.getSystemWindowInsetRight(),
+ insets.getSystemWindowInsetBottom());
}
+ return insets;
+ }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (mStickyRect.contains(ev.getX(), ev.getY())) {
- ev.offsetLocation(-mStickyRect.left, -mStickyRect.top);
- return getHeader().dispatchTouchEvent(ev);
- } else {
- return super.dispatchTouchEvent(ev);
- }
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (stickyRect.contains(ev.getX(), ev.getY())) {
+ ev.offsetLocation(-stickyRect.left, -stickyRect.top);
+ return getHeader().dispatchTouchEvent(ev);
+ } else {
+ return super.dispatchTouchEvent(ev);
}
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/items/RecyclerItemAdapterTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/items/RecyclerItemAdapterTest.java
index 6f42e84..bed736e 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/items/RecyclerItemAdapterTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/items/RecyclerItemAdapterTest.java
@@ -32,16 +32,13 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
+import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver;
+import android.widget.FrameLayout;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.widget.FrameLayout;
-
-import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver;
-
import com.android.setupwizardlib.items.RecyclerItemAdapter.PatchedLayerDrawable;
import com.android.setupwizardlib.test.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,111 +47,110 @@ import org.junit.runner.RunWith;
@SmallTest
public class RecyclerItemAdapterTest {
- private Item[] mItems = new Item[5];
- private ItemGroup mItemGroup = new ItemGroup();
-
- @Before
- public void setUp() throws Exception {
- for (int i = 0; i < 5; i++) {
- Item item = new Item();
- item.setTitle("TestTitle" + i);
- item.setId(i);
- // Layout resource: 0 -> 1, 1 -> 11, 2 -> 21, 3 -> 1, 4 -> 11.
- // (Resource IDs cannot be 0)
- item.setLayoutResource((i % 3) * 10 + 1);
- mItems[i] = item;
- mItemGroup.addChild(item);
- }
- }
-
- @Test
- public void testAdapter() {
- RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
- assertEquals("Adapter should have 5 items", 5, adapter.getItemCount());
- assertEquals("Adapter should return the first item", mItems[0], adapter.getItem(0));
- assertEquals("ID should be same as position", 2, adapter.getItemId(2));
-
- // ViewType is same as layout resource for RecyclerItemAdapter
- assertEquals("Second item should have view type 21", 21, adapter.getItemViewType(2));
- }
-
- @Test
- public void testGetRootItemHierarchy() {
- RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
- ItemHierarchy root = adapter.getRootItemHierarchy();
- assertSame("Root item hierarchy should be mItemGroup", mItemGroup, root);
- }
-
- @Test
- public void testPatchedLayerDrawableNoPadding() {
- ShapeDrawable child = new ShapeDrawable(new RectShape());
- child.setPadding(0, 0, 0, 0);
- PatchedLayerDrawable drawable = new PatchedLayerDrawable(new Drawable[] { child });
-
- Rect padding = new Rect();
- assertFalse("Patched layer drawable should not have padding", drawable.getPadding(padding));
- assertEquals(new Rect(0, 0, 0, 0), padding);
- }
-
- @Test
- public void testPatchedLayerDrawableWithPadding() {
- ShapeDrawable child = new ShapeDrawable(new RectShape());
- child.setPadding(10, 10, 10, 10);
- PatchedLayerDrawable drawable = new PatchedLayerDrawable(new Drawable[] { child });
-
- Rect padding = new Rect();
- assertTrue("Patched layer drawable should have padding", drawable.getPadding(padding));
- assertEquals(new Rect(10, 10, 10, 10), padding);
- }
-
- @Test
- public void testAdapterNotifications() {
- RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
- final AdapterDataObserver observer = mock(AdapterDataObserver.class);
- adapter.registerAdapterDataObserver(observer);
-
- mItems[0].setTitle("Child 1");
- verify(observer).onItemRangeChanged(eq(0), eq(1), anyObject());
-
- mItemGroup.removeChild(mItems[1]);
- verify(observer).onItemRangeRemoved(eq(1), eq(1));
-
- mItemGroup.addChild(mItems[1]);
- verify(observer).onItemRangeInserted(eq(4), eq(1));
- }
-
- @Test
- public void testCreateViewHolder() {
- RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
- FrameLayout parent = new FrameLayout(InstrumentationRegistry.getContext());
-
- final ItemViewHolder viewHolder =
- adapter.onCreateViewHolder(parent, R.layout.test_list_item);
- assertNotNull("Background should be set", viewHolder.itemView.getBackground());
- assertEquals("foobar", viewHolder.itemView.getTag());
- }
-
- @Test
- public void testCreateViewHolderNoBackground() {
- RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
- FrameLayout parent = new FrameLayout(InstrumentationRegistry.getContext());
-
- final ItemViewHolder viewHolder =
- adapter.onCreateViewHolder(parent, R.layout.test_list_item_no_background);
- assertNull("Background should be null", viewHolder.itemView.getBackground());
- }
-
- @Test
- public void testCreateViewHolderWithExistingBackground() {
- RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
- FrameLayout parent = new FrameLayout(InstrumentationRegistry.getContext());
-
- final ItemViewHolder viewHolder =
- adapter.onCreateViewHolder(parent, R.layout.test_existing_background);
- Drawable background = viewHolder.itemView.getBackground();
- assertTrue(background instanceof PatchedLayerDrawable);
-
- PatchedLayerDrawable layerDrawable = (PatchedLayerDrawable) background;
- assertTrue(layerDrawable.getDrawable(0) instanceof GradientDrawable);
+ private Item[] mItems = new Item[5];
+ private ItemGroup mItemGroup = new ItemGroup();
+
+ @Before
+ public void setUp() throws Exception {
+ for (int i = 0; i < 5; i++) {
+ Item item = new Item();
+ item.setTitle("TestTitle" + i);
+ item.setId(i);
+ // Layout resource: 0 -> 1, 1 -> 11, 2 -> 21, 3 -> 1, 4 -> 11.
+ // (Resource IDs cannot be 0)
+ item.setLayoutResource((i % 3) * 10 + 1);
+ mItems[i] = item;
+ mItemGroup.addChild(item);
}
+ }
+
+ @Test
+ public void testAdapter() {
+ RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
+ assertEquals("Adapter should have 5 items", 5, adapter.getItemCount());
+ assertEquals("Adapter should return the first item", mItems[0], adapter.getItem(0));
+ assertEquals("ID should be same as position", 2, adapter.getItemId(2));
+
+ // ViewType is same as layout resource for RecyclerItemAdapter
+ assertEquals("Second item should have view type 21", 21, adapter.getItemViewType(2));
+ }
+
+ @Test
+ public void testGetRootItemHierarchy() {
+ RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
+ ItemHierarchy root = adapter.getRootItemHierarchy();
+ assertSame("Root item hierarchy should be mItemGroup", mItemGroup, root);
+ }
+
+ @Test
+ public void testPatchedLayerDrawableNoPadding() {
+ ShapeDrawable child = new ShapeDrawable(new RectShape());
+ child.setPadding(0, 0, 0, 0);
+ PatchedLayerDrawable drawable = new PatchedLayerDrawable(new Drawable[] {child});
+
+ Rect padding = new Rect();
+ assertFalse("Patched layer drawable should not have padding", drawable.getPadding(padding));
+ assertEquals(new Rect(0, 0, 0, 0), padding);
+ }
+
+ @Test
+ public void testPatchedLayerDrawableWithPadding() {
+ ShapeDrawable child = new ShapeDrawable(new RectShape());
+ child.setPadding(10, 10, 10, 10);
+ PatchedLayerDrawable drawable = new PatchedLayerDrawable(new Drawable[] {child});
+
+ Rect padding = new Rect();
+ assertTrue("Patched layer drawable should have padding", drawable.getPadding(padding));
+ assertEquals(new Rect(10, 10, 10, 10), padding);
+ }
+
+ @Test
+ public void testAdapterNotifications() {
+ RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
+ final AdapterDataObserver observer = mock(AdapterDataObserver.class);
+ adapter.registerAdapterDataObserver(observer);
+
+ mItems[0].setTitle("Child 1");
+ verify(observer).onItemRangeChanged(eq(0), eq(1), anyObject());
+
+ mItemGroup.removeChild(mItems[1]);
+ verify(observer).onItemRangeRemoved(eq(1), eq(1));
+
+ mItemGroup.addChild(mItems[1]);
+ verify(observer).onItemRangeInserted(eq(4), eq(1));
+ }
+
+ @Test
+ public void testCreateViewHolder() {
+ RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
+ FrameLayout parent = new FrameLayout(InstrumentationRegistry.getContext());
+
+ final ItemViewHolder viewHolder = adapter.onCreateViewHolder(parent, R.layout.test_list_item);
+ assertNotNull("Background should be set", viewHolder.itemView.getBackground());
+ assertEquals("foobar", viewHolder.itemView.getTag());
+ }
+
+ @Test
+ public void testCreateViewHolderNoBackground() {
+ RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
+ FrameLayout parent = new FrameLayout(InstrumentationRegistry.getContext());
+
+ final ItemViewHolder viewHolder =
+ adapter.onCreateViewHolder(parent, R.layout.test_list_item_no_background);
+ assertNull("Background should be null", viewHolder.itemView.getBackground());
+ }
+
+ @Test
+ public void testCreateViewHolderWithExistingBackground() {
+ RecyclerItemAdapter adapter = new RecyclerItemAdapter(mItemGroup);
+ FrameLayout parent = new FrameLayout(InstrumentationRegistry.getContext());
+
+ final ItemViewHolder viewHolder =
+ adapter.onCreateViewHolder(parent, R.layout.test_existing_background);
+ Drawable background = viewHolder.itemView.getBackground();
+ assertTrue(background instanceof PatchedLayerDrawable);
+
+ PatchedLayerDrawable layerDrawable = (PatchedLayerDrawable) background;
+ assertTrue(layerDrawable.getDrawable(0) instanceof GradientDrawable);
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/template/RecyclerMixinTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/template/RecyclerMixinTest.java
index ece4bf9..f295b91 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/template/RecyclerMixinTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/template/RecyclerMixinTest.java
@@ -30,17 +30,14 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+import android.view.View;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.View;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-
import com.android.setupwizardlib.TemplateLayout;
import com.android.setupwizardlib.test.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,120 +48,119 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class RecyclerMixinTest {
- private Context mContext;
- private TemplateLayout mTemplateLayout;
+ private Context mContext;
+ private TemplateLayout mTemplateLayout;
- private RecyclerView mRecyclerView;
+ private RecyclerView mRecyclerView;
- @Mock
- private Adapter mAdapter;
+ @Mock private Adapter mAdapter;
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
- mContext = InstrumentationRegistry.getTargetContext();
- mTemplateLayout = spy(new TemplateLayout(mContext, R.layout.test_template,
- R.id.suw_layout_content));
+ mContext = InstrumentationRegistry.getTargetContext();
+ mTemplateLayout =
+ spy(new TemplateLayout(mContext, R.layout.test_template, R.id.suw_layout_content));
- mRecyclerView = mock(RecyclerView.class, delegatesTo(new RecyclerView(mContext)));
+ mRecyclerView = mock(RecyclerView.class, delegatesTo(new RecyclerView(mContext)));
- doReturn(true).when(mTemplateLayout).isLayoutDirectionResolved();
- }
+ doReturn(true).when(mTemplateLayout).isLayoutDirectionResolved();
+ }
- @Test
- public void testGetRecyclerView() {
- RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
- assertSame(mRecyclerView, mixin.getRecyclerView());
- }
+ @Test
+ public void testGetRecyclerView() {
+ RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
+ assertSame(mRecyclerView, mixin.getRecyclerView());
+ }
- @Test
- public void testGetAdapter() {
- mRecyclerView.setAdapter(mAdapter);
+ @Test
+ public void testGetAdapter() {
+ mRecyclerView.setAdapter(mAdapter);
- RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
- assertSame(mAdapter, mixin.getAdapter());
- }
+ RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
+ assertSame(mAdapter, mixin.getAdapter());
+ }
- @Test
- public void testSetAdapter() {
- assertNull(mRecyclerView.getAdapter());
+ @Test
+ public void testSetAdapter() {
+ assertNull(mRecyclerView.getAdapter());
- RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
- mixin.setAdapter(mAdapter);
+ RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
+ mixin.setAdapter(mAdapter);
- assertSame(mAdapter, mRecyclerView.getAdapter());
- }
+ assertSame(mAdapter, mRecyclerView.getAdapter());
+ }
- @Test
- public void testDividerLegacyInset() {
- RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
- mixin.setDividerInset(123);
+ @Test
+ public void testDividerLegacyInset() {
+ RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
+ mixin.setDividerInset(123);
- assertEquals(123, mixin.getDividerInset());
+ assertEquals(123, mixin.getDividerInset());
- final Drawable divider = mixin.getDivider();
- InsetDrawable insetDrawable = (InsetDrawable) divider;
- Rect rect = new Rect();
- insetDrawable.getPadding(rect);
+ final Drawable divider = mixin.getDivider();
+ InsetDrawable insetDrawable = (InsetDrawable) divider;
+ Rect rect = new Rect();
+ insetDrawable.getPadding(rect);
- assertEquals(new Rect(123, 0, 0, 0), rect);
- }
+ assertEquals(new Rect(123, 0, 0, 0), rect);
+ }
- @Test
- public void testDividerInsets() {
- RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
- mixin.setDividerInsets(123, 456);
+ @Test
+ public void testDividerInsets() {
+ RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
+ mixin.setDividerInsets(123, 456);
- assertEquals(123, mixin.getDividerInsetStart());
- assertEquals(456, mixin.getDividerInsetEnd());
+ assertEquals(123, mixin.getDividerInsetStart());
+ assertEquals(456, mixin.getDividerInsetEnd());
- final Drawable divider = mixin.getDivider();
- InsetDrawable insetDrawable = (InsetDrawable) divider;
- Rect rect = new Rect();
- insetDrawable.getPadding(rect);
+ final Drawable divider = mixin.getDivider();
+ InsetDrawable insetDrawable = (InsetDrawable) divider;
+ Rect rect = new Rect();
+ insetDrawable.getPadding(rect);
- assertEquals(new Rect(123, 0, 456, 0), rect);
- }
+ assertEquals(new Rect(123, 0, 456, 0), rect);
+ }
- @Test
- public void testDividerInsetLegacyRtl() {
- if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
- doReturn(View.LAYOUT_DIRECTION_RTL).when(mTemplateLayout).getLayoutDirection();
+ @Test
+ public void testDividerInsetLegacyRtl() {
+ if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
+ doReturn(View.LAYOUT_DIRECTION_RTL).when(mTemplateLayout).getLayoutDirection();
- RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
- mixin.setDividerInset(123);
+ RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
+ mixin.setDividerInset(123);
- assertEquals(123, mixin.getDividerInset());
+ assertEquals(123, mixin.getDividerInset());
- final Drawable divider = mixin.getDivider();
- InsetDrawable insetDrawable = (InsetDrawable) divider;
- Rect rect = new Rect();
- insetDrawable.getPadding(rect);
+ final Drawable divider = mixin.getDivider();
+ InsetDrawable insetDrawable = (InsetDrawable) divider;
+ Rect rect = new Rect();
+ insetDrawable.getPadding(rect);
- assertEquals(new Rect(0, 0, 123, 0), rect);
- }
- // else the test passes
+ assertEquals(new Rect(0, 0, 123, 0), rect);
}
+ // else the test passes
+ }
- @Test
- public void testDividerInsetsRtl() {
- if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
- doReturn(View.LAYOUT_DIRECTION_RTL).when(mTemplateLayout).getLayoutDirection();
+ @Test
+ public void testDividerInsetsRtl() {
+ if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
+ doReturn(View.LAYOUT_DIRECTION_RTL).when(mTemplateLayout).getLayoutDirection();
- RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
- mixin.setDividerInsets(123, 456);
+ RecyclerMixin mixin = new RecyclerMixin(mTemplateLayout, mRecyclerView);
+ mixin.setDividerInsets(123, 456);
- assertEquals(123, mixin.getDividerInsetStart());
- assertEquals(456, mixin.getDividerInsetEnd());
+ assertEquals(123, mixin.getDividerInsetStart());
+ assertEquals(456, mixin.getDividerInsetEnd());
- final Drawable divider = mixin.getDivider();
- InsetDrawable insetDrawable = (InsetDrawable) divider;
- Rect rect = new Rect();
- insetDrawable.getPadding(rect);
+ final Drawable divider = mixin.getDivider();
+ InsetDrawable insetDrawable = (InsetDrawable) divider;
+ Rect rect = new Rect();
+ insetDrawable.getPadding(rect);
- assertEquals(new Rect(456, 0, 123, 0), rect);
- }
- // else the test passes
+ assertEquals(new Rect(456, 0, 123, 0), rect);
}
+ // else the test passes
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/DividerItemDecorationTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/DividerItemDecorationTest.java
index 9cf33b9..a3a0cfe 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/DividerItemDecorationTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/DividerItemDecorationTest.java
@@ -28,17 +28,14 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.setupwizardlib.DividerItemDecoration;
-
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,176 +43,179 @@ import org.junit.runner.RunWith;
@SmallTest
public class DividerItemDecorationTest {
- @Test
- public void testDivider() {
- final DividerItemDecoration decoration = new DividerItemDecoration();
- Drawable divider = new ColorDrawable();
- decoration.setDivider(divider);
- assertSame("Divider should be same as set", divider, decoration.getDivider());
- }
+ @Test
+ public void testDivider() {
+ final DividerItemDecoration decoration = new DividerItemDecoration();
+ Drawable divider = new ColorDrawable();
+ decoration.setDivider(divider);
+ assertSame("Divider should be same as set", divider, decoration.getDivider());
+ }
+
+ @Test
+ public void testDividerHeight() {
+ final DividerItemDecoration decoration = new DividerItemDecoration();
+ decoration.setDividerHeight(123);
+ assertEquals("Divider height should be 123", 123, decoration.getDividerHeight());
+ }
+
+ @Test
+ public void testShouldDrawDividerBelowWithEitherCondition() {
+ // Set up the item decoration, with 1px red divider line
+ final DividerItemDecoration decoration = new DividerItemDecoration();
+ Drawable divider = new ColorDrawable(Color.RED);
+ decoration.setDivider(divider);
+ decoration.setDividerHeight(1);
+
+ Bitmap bitmap = drawDecoration(decoration, true, true);
+
+ // Draw the expected result on a bitmap
+ Bitmap expectedBitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444);
+ Canvas expectedCanvas = new Canvas(expectedBitmap);
+ Paint paint = new Paint();
+ paint.setColor(Color.RED);
+ expectedCanvas.drawRect(0, 5, 20, 6, paint);
+ expectedCanvas.drawRect(0, 10, 20, 11, paint);
+ expectedCanvas.drawRect(0, 15, 20, 16, paint);
+ // Compare the two bitmaps
+ assertBitmapEquals(expectedBitmap, bitmap);
+
+ bitmap.recycle();
+ bitmap = drawDecoration(decoration, false, true);
+ // should still be the same.
+ assertBitmapEquals(expectedBitmap, bitmap);
+
+ bitmap.recycle();
+ bitmap = drawDecoration(decoration, true, false);
+ // last item should not have a divider below it now
+ paint.setColor(Color.TRANSPARENT);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ expectedCanvas.drawRect(0, 15, 20, 16, paint);
+ assertBitmapEquals(expectedBitmap, bitmap);
+
+ bitmap.recycle();
+ bitmap = drawDecoration(decoration, false, false);
+ // everything should be transparent now
+ expectedCanvas.drawRect(0, 5, 20, 6, paint);
+ expectedCanvas.drawRect(0, 10, 20, 11, paint);
+ assertBitmapEquals(expectedBitmap, bitmap);
+ }
+
+ @Test
+ public void testShouldDrawDividerBelowWithBothCondition() {
+ // Set up the item decoration, with 1px green divider line
+ final DividerItemDecoration decoration = new DividerItemDecoration();
+ Drawable divider = new ColorDrawable(Color.GREEN);
+ decoration.setDivider(divider);
+ decoration.setDividerHeight(1);
+ decoration.setDividerCondition(DividerItemDecoration.DIVIDER_CONDITION_BOTH);
+
+ Bitmap bitmap = drawDecoration(decoration, true, true);
+ Paint paint = new Paint();
+ paint.setColor(Color.GREEN);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
+ Bitmap expectedBitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444);
+ Canvas expectedCanvas = new Canvas(expectedBitmap);
+ expectedCanvas.drawRect(0, 5, 20, 6, paint);
+ expectedCanvas.drawRect(0, 10, 20, 11, paint);
+ expectedCanvas.drawRect(0, 15, 20, 16, paint);
+ // Should have all the dividers
+ assertBitmapEquals(expectedBitmap, bitmap);
+
+ bitmap.recycle();
+ bitmap = drawDecoration(decoration, false, true);
+ paint.setColor(Color.TRANSPARENT);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ expectedCanvas.drawRect(0, 5, 20, 6, paint);
+ expectedCanvas.drawRect(0, 10, 20, 11, paint);
+ assertBitmapEquals(expectedBitmap, bitmap);
+
+ bitmap.recycle();
+ bitmap = drawDecoration(decoration, true, false);
+ // nothing should be drawn now.
+ expectedCanvas.drawRect(0, 15, 20, 16, paint);
+ assertBitmapEquals(expectedBitmap, bitmap);
+
+ bitmap.recycle();
+ bitmap = drawDecoration(decoration, false, false);
+ assertBitmapEquals(expectedBitmap, bitmap);
+ }
+
+ private Bitmap drawDecoration(
+ DividerItemDecoration decoration,
+ final boolean allowDividerAbove,
+ final boolean allowDividerBelow) {
+ // Set up the canvas to be drawn
+ Bitmap bitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444);
+ Canvas canvas = new Canvas(bitmap);
+
+ final Context context = InstrumentationRegistry.getContext();
+ // Set up recycler view with vertical linear layout manager
+ RecyclerView testRecyclerView = new RecyclerView(context);
+ testRecyclerView.setLayoutManager(new LinearLayoutManager(context));
+
+ // Set up adapter with 3 items, each 5px tall
+ testRecyclerView.setAdapter(
+ new RecyclerView.Adapter() {
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
+ final View itemView = new View(context);
+ itemView.setMinimumWidth(20);
+ itemView.setMinimumHeight(5);
+ return ViewHolder.createInstance(itemView, allowDividerAbove, allowDividerBelow);
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {}
+
+ @Override
+ public int getItemCount() {
+ return 3;
+ }
+ });
- @Test
- public void testDividerHeight() {
- final DividerItemDecoration decoration = new DividerItemDecoration();
- decoration.setDividerHeight(123);
- assertEquals("Divider height should be 123", 123, decoration.getDividerHeight());
+ testRecyclerView.layout(0, 0, 20, 20);
+ decoration.onDraw(canvas, testRecyclerView, null);
+ return bitmap;
+ }
+
+ private void assertBitmapEquals(Bitmap expected, Bitmap actual) {
+ assertEquals("Width should be the same", expected.getWidth(), actual.getWidth());
+ assertEquals("Height should be the same", expected.getHeight(), actual.getHeight());
+ for (int x = 0; x < expected.getWidth(); x++) {
+ for (int y = 0; y < expected.getHeight(); y++) {
+ assertEquals(
+ "Pixel at (" + x + ", " + y + ") should be the same",
+ expected.getPixel(x, y),
+ actual.getPixel(x, y));
+ }
}
+ }
- @Test
- public void testShouldDrawDividerBelowWithEitherCondition() {
- // Set up the item decoration, with 1px red divider line
- final DividerItemDecoration decoration = new DividerItemDecoration();
- Drawable divider = new ColorDrawable(Color.RED);
- decoration.setDivider(divider);
- decoration.setDividerHeight(1);
-
- Bitmap bitmap = drawDecoration(decoration, true, true);
-
- // Draw the expected result on a bitmap
- Bitmap expectedBitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444);
- Canvas expectedCanvas = new Canvas(expectedBitmap);
- Paint paint = new Paint();
- paint.setColor(Color.RED);
- expectedCanvas.drawRect(0, 5, 20, 6, paint);
- expectedCanvas.drawRect(0, 10, 20, 11, paint);
- expectedCanvas.drawRect(0, 15, 20, 16, paint);
- // Compare the two bitmaps
- assertBitmapEquals(expectedBitmap, bitmap);
-
- bitmap.recycle();
- bitmap = drawDecoration(decoration, false, true);
- // should still be the same.
- assertBitmapEquals(expectedBitmap, bitmap);
-
- bitmap.recycle();
- bitmap = drawDecoration(decoration, true, false);
- // last item should not have a divider below it now
- paint.setColor(Color.TRANSPARENT);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
- expectedCanvas.drawRect(0, 15, 20, 16, paint);
- assertBitmapEquals(expectedBitmap, bitmap);
-
- bitmap.recycle();
- bitmap = drawDecoration(decoration, false, false);
- // everything should be transparent now
- expectedCanvas.drawRect(0, 5, 20, 6, paint);
- expectedCanvas.drawRect(0, 10, 20, 11, paint);
- assertBitmapEquals(expectedBitmap, bitmap);
+ private static class ViewHolder extends RecyclerView.ViewHolder
+ implements DividerItemDecoration.DividedViewHolder {
- }
+ private boolean mAllowDividerAbove;
+ private boolean mAllowDividerBelow;
- @Test
- public void testShouldDrawDividerBelowWithBothCondition() {
- // Set up the item decoration, with 1px green divider line
- final DividerItemDecoration decoration = new DividerItemDecoration();
- Drawable divider = new ColorDrawable(Color.GREEN);
- decoration.setDivider(divider);
- decoration.setDividerHeight(1);
- decoration.setDividerCondition(DividerItemDecoration.DIVIDER_CONDITION_BOTH);
-
- Bitmap bitmap = drawDecoration(decoration, true, true);
- Paint paint = new Paint();
- paint.setColor(Color.GREEN);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
- Bitmap expectedBitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444);
- Canvas expectedCanvas = new Canvas(expectedBitmap);
- expectedCanvas.drawRect(0, 5, 20, 6, paint);
- expectedCanvas.drawRect(0, 10, 20, 11, paint);
- expectedCanvas.drawRect(0, 15, 20, 16, paint);
- // Should have all the dividers
- assertBitmapEquals(expectedBitmap, bitmap);
-
- bitmap.recycle();
- bitmap = drawDecoration(decoration, false, true);
- paint.setColor(Color.TRANSPARENT);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
- expectedCanvas.drawRect(0, 5, 20, 6, paint);
- expectedCanvas.drawRect(0, 10, 20, 11, paint);
- assertBitmapEquals(expectedBitmap, bitmap);
-
- bitmap.recycle();
- bitmap = drawDecoration(decoration, true, false);
- // nothing should be drawn now.
- expectedCanvas.drawRect(0, 15, 20, 16, paint);
- assertBitmapEquals(expectedBitmap, bitmap);
-
- bitmap.recycle();
- bitmap = drawDecoration(decoration, false, false);
- assertBitmapEquals(expectedBitmap, bitmap);
+ public static ViewHolder createInstance(
+ View itemView, boolean allowDividerAbove, boolean allowDividerBelow) {
+ return new ViewHolder(itemView, allowDividerAbove, allowDividerBelow);
}
- private Bitmap drawDecoration(DividerItemDecoration decoration, final boolean allowDividerAbove,
- final boolean allowDividerBelow) {
- // Set up the canvas to be drawn
- Bitmap bitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444);
- Canvas canvas = new Canvas(bitmap);
-
- final Context context = InstrumentationRegistry.getContext();
- // Set up recycler view with vertical linear layout manager
- RecyclerView testRecyclerView = new RecyclerView(context);
- testRecyclerView.setLayoutManager(new LinearLayoutManager(context));
-
- // Set up adapter with 3 items, each 5px tall
- testRecyclerView.setAdapter(new RecyclerView.Adapter() {
- @Override
- public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
- final View itemView = new View(context);
- itemView.setMinimumWidth(20);
- itemView.setMinimumHeight(5);
- return ViewHolder.createInstance(itemView, allowDividerAbove, allowDividerBelow);
- }
-
- @Override
- public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
- }
-
- @Override
- public int getItemCount() {
- return 3;
- }
- });
-
- testRecyclerView.layout(0, 0, 20, 20);
- decoration.onDraw(canvas, testRecyclerView, null);
- return bitmap;
+ private ViewHolder(View itemView, boolean allowDividerAbove, boolean allowDividerBelow) {
+ super(itemView);
+ mAllowDividerAbove = allowDividerAbove;
+ mAllowDividerBelow = allowDividerBelow;
}
- private void assertBitmapEquals(Bitmap expected, Bitmap actual) {
- assertEquals("Width should be the same", expected.getWidth(), actual.getWidth());
- assertEquals("Height should be the same", expected.getHeight(), actual.getHeight());
- for (int x = 0; x < expected.getWidth(); x++) {
- for (int y = 0; y < expected.getHeight(); y++) {
- assertEquals("Pixel at (" + x + ", " + y + ") should be the same",
- expected.getPixel(x, y), actual.getPixel(x, y));
- }
- }
+ @Override
+ public boolean isDividerAllowedAbove() {
+ return mAllowDividerAbove;
}
- private static class ViewHolder extends RecyclerView.ViewHolder
- implements DividerItemDecoration.DividedViewHolder {
-
- private boolean mAllowDividerAbove;
- private boolean mAllowDividerBelow;
-
- public static ViewHolder createInstance(View itemView, boolean allowDividerAbove,
- boolean allowDividerBelow) {
- return new ViewHolder(itemView, allowDividerAbove, allowDividerBelow);
- }
-
- private ViewHolder(View itemView, boolean allowDividerAbove, boolean allowDividerBelow) {
- super(itemView);
- mAllowDividerAbove = allowDividerAbove;
- mAllowDividerBelow = allowDividerBelow;
- }
-
- @Override
- public boolean isDividerAllowedAbove() {
- return mAllowDividerAbove;
- }
-
- @Override
- public boolean isDividerAllowedBelow() {
- return mAllowDividerBelow;
- }
+ @Override
+ public boolean isDividerAllowedBelow() {
+ return mAllowDividerBelow;
}
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifPreferenceLayoutTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifPreferenceLayoutTest.java
index 4d2876d..d55ba23 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifPreferenceLayoutTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifPreferenceLayoutTest.java
@@ -24,18 +24,15 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.setupwizardlib.GlifPreferenceLayout;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,62 +41,63 @@ import org.junit.runner.RunWith;
@SmallTest
public class GlifPreferenceLayoutTest {
- private Context mContext;
-
- @Before
- public void setUp() throws Exception {
- mContext = new ContextThemeWrapper(InstrumentationRegistry.getContext(),
- R.style.SuwThemeGlif_Light);
- }
-
- @Test
- public void testDefaultTemplate() {
- GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
- assertPreferenceTemplateInflated(layout);
- }
-
- @Test
- public void testGetRecyclerView() {
- GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
- assertPreferenceTemplateInflated(layout);
- assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext =
+ new ContextThemeWrapper(InstrumentationRegistry.getContext(), R.style.SuwThemeGlif_Light);
+ }
+
+ @Test
+ public void testDefaultTemplate() {
+ GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
+ assertPreferenceTemplateInflated(layout);
+ }
+
+ @Test
+ public void testGetRecyclerView() {
+ GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
+ assertPreferenceTemplateInflated(layout);
+ assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
+ }
+
+ @Test
+ public void testOnCreateRecyclerView() {
+ GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
+ assertPreferenceTemplateInflated(layout);
+ final RecyclerView recyclerView =
+ layout.onCreateRecyclerView(
+ LayoutInflater.from(mContext), layout, null /* savedInstanceState */);
+ assertNotNull("RecyclerView created should not be null", recyclerView);
+ }
+
+ @Test
+ public void testDividerInset() {
+ GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
+ assertPreferenceTemplateInflated(layout);
- @Test
- public void testOnCreateRecyclerView() {
- GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
- assertPreferenceTemplateInflated(layout);
- final RecyclerView recyclerView = layout.onCreateRecyclerView(LayoutInflater.from(mContext),
- layout, null /* savedInstanceState */);
- assertNotNull("RecyclerView created should not be null", recyclerView);
- }
-
- @Test
- public void testDividerInset() {
- GlifPreferenceLayout layout = new GlifPreferenceLayout(mContext);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
- }
- assertPreferenceTemplateInflated(layout);
+ layout.addView(
+ layout.onCreateRecyclerView(
+ LayoutInflater.from(mContext), layout, null /* savedInstanceState */));
- layout.addView(layout.onCreateRecyclerView(LayoutInflater.from(mContext), layout,
- null /* savedInstanceState */));
+ layout.setDividerInset(10);
+ assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
- layout.setDividerInset(10);
- assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
+ final Drawable divider = layout.getDivider();
+ assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
+ }
- final Drawable divider = layout.getDivider();
- assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
- }
+ private void assertPreferenceTemplateInflated(GlifPreferenceLayout layout) {
+ View contentContainer = layout.findViewById(R.id.suw_layout_content);
+ assertTrue(
+ "@id/suw_layout_content should be a ViewGroup", contentContainer instanceof ViewGroup);
- private void assertPreferenceTemplateInflated(GlifPreferenceLayout layout) {
- View contentContainer = layout.findViewById(R.id.suw_layout_content);
- assertTrue("@id/suw_layout_content should be a ViewGroup",
- contentContainer instanceof ViewGroup);
-
- assertNotNull("Header text view should not be null",
- layout.findManagedViewById(R.id.suw_layout_title));
- assertNotNull("Icon view should not be null",
- layout.findManagedViewById(R.id.suw_layout_icon));
- }
+ assertNotNull(
+ "Header text view should not be null", layout.findManagedViewById(R.id.suw_layout_title));
+ assertNotNull("Icon view should not be null", layout.findManagedViewById(R.id.suw_layout_icon));
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifRecyclerLayoutTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifRecyclerLayoutTest.java
index a68faf0..5db7db5 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifRecyclerLayoutTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/GlifRecyclerLayoutTest.java
@@ -26,20 +26,17 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.setupwizardlib.GlifRecyclerLayout;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,130 +45,127 @@ import org.junit.runner.RunWith;
@SmallTest
public class GlifRecyclerLayoutTest {
- private Context mContext;
-
- @Before
- public void setUp() throws Exception {
- mContext = new ContextThemeWrapper(InstrumentationRegistry.getContext(),
- R.style.SuwThemeGlif_Light);
- }
-
- @Test
- public void testDefaultTemplate() {
- GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
- }
-
- @Test
- public void testInflateFromXml() {
- LayoutInflater inflater = LayoutInflater.from(mContext);
- GlifRecyclerLayout layout = (GlifRecyclerLayout)
- inflater.inflate(R.layout.test_glif_recycler_layout, null);
- assertRecyclerTemplateInflated(layout);
- }
-
- @Test
- public void testGetRecyclerView() {
- GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
- assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
- }
-
- @Test
- public void testAdapter() {
- GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
-
- final RecyclerView.Adapter adapter = createTestAdapter(1);
- layout.setAdapter(adapter);
-
- final RecyclerView.Adapter gotAdapter = layout.getAdapter();
- // Note: The wrapped adapter should be returned, not the HeaderAdapter.
- assertSame("Adapter got from GlifRecyclerLayout should be same as set",
- adapter, gotAdapter);
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext =
+ new ContextThemeWrapper(InstrumentationRegistry.getContext(), R.style.SuwThemeGlif_Light);
+ }
+
+ @Test
+ public void testDefaultTemplate() {
+ GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+ }
+
+ @Test
+ public void testInflateFromXml() {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ GlifRecyclerLayout layout =
+ (GlifRecyclerLayout) inflater.inflate(R.layout.test_glif_recycler_layout, null);
+ assertRecyclerTemplateInflated(layout);
+ }
+
+ @Test
+ public void testGetRecyclerView() {
+ GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+ assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
+ }
+
+ @Test
+ public void testAdapter() {
+ GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+
+ final RecyclerView.Adapter adapter = createTestAdapter(1);
+ layout.setAdapter(adapter);
+
+ final RecyclerView.Adapter gotAdapter = layout.getAdapter();
+ // Note: The wrapped adapter should be returned, not the HeaderAdapter.
+ assertSame("Adapter got from GlifRecyclerLayout should be same as set", adapter, gotAdapter);
+ }
+
+ @Test
+ public void testLayout() {
+ GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+
+ layout.setAdapter(createTestAdapter(3));
+
+ layout.measure(
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
+ layout.layout(0, 0, 500, 500);
+ // Test that the layout code doesn't crash.
+ }
+
+ @Test
+ public void testDividerInsetLegacy() {
+ GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
+ assertRecyclerTemplateInflated(layout);
- @Test
- public void testLayout() {
- GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
+ layout.setDividerInset(10);
+ assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
- layout.setAdapter(createTestAdapter(3));
+ final Drawable divider = layout.getDivider();
+ assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
+ }
- layout.measure(
- MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
- layout.layout(0, 0, 500, 500);
- // Test that the layout code doesn't crash.
+ @Test
+ public void testDividerInsets() {
+ GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
-
- @Test
- public void testDividerInsetLegacy() {
- GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
- }
- assertRecyclerTemplateInflated(layout);
-
- layout.setDividerInset(10);
- assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
-
- final Drawable divider = layout.getDivider();
- assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
- }
-
- @Test
- public void testDividerInsets() {
- GlifRecyclerLayout layout = new GlifRecyclerLayout(mContext);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
- }
- assertRecyclerTemplateInflated(layout);
-
- layout.setDividerInsets(10, 15);
- assertEquals("Divider inset start should be 10", 10, layout.getDividerInsetStart());
- assertEquals("Divider inset end should be 15", 15, layout.getDividerInsetEnd());
-
- final Drawable divider = layout.getDivider();
- assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
- }
-
- @Test
- public void testTemplateWithNoRecyclerView() {
- try {
- new GlifRecyclerLayout(mContext, R.layout.suw_glif_template);
- fail("Creating GlifRecyclerLayout with no recycler view should throw exception");
- } catch (Exception e) {
- // pass
- }
- }
-
- private void assertRecyclerTemplateInflated(GlifRecyclerLayout layout) {
- View recyclerView = layout.findViewById(R.id.suw_recycler_view);
- assertTrue("@id/suw_recycler_view should be a RecyclerView",
- recyclerView instanceof RecyclerView);
-
- assertNotNull("Header text view should not be null",
- layout.findManagedViewById(R.id.suw_layout_title));
- assertNotNull("Icon view should not be null",
- layout.findManagedViewById(R.id.suw_layout_icon));
- }
-
- private Adapter createTestAdapter(final int itemCount) {
- return new RecyclerView.Adapter() {
- @Override
- public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
- return new RecyclerView.ViewHolder(new View(parent.getContext())) {};
- }
-
- @Override
- public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
- }
-
- @Override
- public int getItemCount() {
- return itemCount;
- }
- };
+ assertRecyclerTemplateInflated(layout);
+
+ layout.setDividerInsets(10, 15);
+ assertEquals("Divider inset start should be 10", 10, layout.getDividerInsetStart());
+ assertEquals("Divider inset end should be 15", 15, layout.getDividerInsetEnd());
+
+ final Drawable divider = layout.getDivider();
+ assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
+ }
+
+ @Test
+ public void testTemplateWithNoRecyclerView() {
+ try {
+ new GlifRecyclerLayout(mContext, R.layout.suw_glif_template);
+ fail("Creating GlifRecyclerLayout with no recycler view should throw exception");
+ } catch (Exception e) {
+ // pass
}
+ }
+
+ private void assertRecyclerTemplateInflated(GlifRecyclerLayout layout) {
+ View recyclerView = layout.findViewById(R.id.suw_recycler_view);
+ assertTrue(
+ "@id/suw_recycler_view should be a RecyclerView", recyclerView instanceof RecyclerView);
+
+ assertNotNull(
+ "Header text view should not be null", layout.findManagedViewById(R.id.suw_layout_title));
+ assertNotNull("Icon view should not be null", layout.findManagedViewById(R.id.suw_layout_icon));
+ }
+
+ private Adapter createTestAdapter(final int itemCount) {
+ return new RecyclerView.Adapter() {
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
+ return new RecyclerView.ViewHolder(new View(parent.getContext())) {};
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {}
+
+ @Override
+ public int getItemCount() {
+ return itemCount;
+ }
+ };
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/HeaderRecyclerViewTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/HeaderRecyclerViewTest.java
index 9af68a7..3d0f9da 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/HeaderRecyclerViewTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/HeaderRecyclerViewTest.java
@@ -19,160 +19,143 @@ package com.android.setupwizardlib.test;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.setupwizardlib.view.HeaderRecyclerView.HeaderAdapter;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-/**
- * Test for {@link com.android.setupwizardlib.view.HeaderRecyclerView}
- */
+/** Test for {@link com.android.setupwizardlib.view.HeaderRecyclerView} */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class HeaderRecyclerViewTest {
- private TestAdapter mWrappedAdapter;
- private HeaderAdapter mHeaderAdapter;
-
- @Mock
- private RecyclerView.AdapterDataObserver mObserver;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mWrappedAdapter = new TestAdapter();
-
- mHeaderAdapter = new HeaderAdapter(mWrappedAdapter);
- mHeaderAdapter.registerAdapterDataObserver(mObserver);
- }
-
- /**
- * Test that notifyDataSetChanged gets propagated by HeaderRecyclerView's adapter.
- */
- @Test
- public void testNotifyChanged() {
- mWrappedAdapter.notifyDataSetChanged();
-
- verify(mObserver).onChanged();
+ private TestAdapter mWrappedAdapter;
+ private HeaderAdapter mHeaderAdapter;
+
+ @Mock private RecyclerView.AdapterDataObserver mObserver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mWrappedAdapter = new TestAdapter();
+
+ mHeaderAdapter = new HeaderAdapter(mWrappedAdapter);
+ mHeaderAdapter.registerAdapterDataObserver(mObserver);
+ }
+
+ /** Test that notifyDataSetChanged gets propagated by HeaderRecyclerView's adapter. */
+ @Test
+ public void testNotifyChanged() {
+ mWrappedAdapter.notifyDataSetChanged();
+
+ verify(mObserver).onChanged();
+ }
+
+ /** Test that notifyItemChanged gets propagated by HeaderRecyclerView's adapter. */
+ @Test
+ public void testNotifyItemChangedNoHeader() {
+ mWrappedAdapter.notifyItemChanged(12);
+
+ verify(mObserver).onItemRangeChanged(eq(12), eq(1), eq(null));
+ }
+
+ /**
+ * Test that notifyItemChanged gets propagated by HeaderRecyclerView's adapter and adds 1 to the
+ * position for the extra header items.
+ */
+ @Test
+ public void testNotifyItemChangedWithHeader() {
+ mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
+ mWrappedAdapter.notifyItemChanged(12);
+
+ verify(mObserver).onItemRangeChanged(eq(13), eq(1), eq(null));
+ }
+
+ /** Test that notifyItemInserted gets propagated by HeaderRecyclerView's adapter. */
+ @Test
+ public void testNotifyItemInsertedNoHeader() {
+ mWrappedAdapter.notifyItemInserted(12);
+
+ verify(mObserver).onItemRangeInserted(eq(12), eq(1));
+ }
+
+ /**
+ * Test that notifyItemInserted gets propagated by HeaderRecyclerView's adapter and adds 1 to the
+ * position for the extra header item.
+ */
+ @Test
+ public void testNotifyItemInsertedWithHeader() {
+ mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
+ mWrappedAdapter.notifyItemInserted(12);
+
+ verify(mObserver).onItemRangeInserted(eq(13), eq(1));
+ }
+
+ /** Test that notifyItemRemoved gets propagated by HeaderRecyclerView's adapter. */
+ @Test
+ public void testNotifyItemRemovedNoHeader() {
+ mWrappedAdapter.notifyItemRemoved(12);
+
+ verify(mObserver).onItemRangeRemoved(eq(12), eq(1));
+ }
+
+ /**
+ * Test that notifyItemRemoved gets propagated by HeaderRecyclerView's adapter and adds 1 to the
+ * position for the extra header item.
+ */
+ @Test
+ public void testNotifyItemRemovedWithHeader() {
+ mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
+ mWrappedAdapter.notifyItemRemoved(12);
+
+ verify(mObserver).onItemRangeRemoved(eq(13), eq(1));
+ }
+
+ /** Test that notifyItemMoved gets propagated by HeaderRecyclerView's adapter. */
+ @Test
+ public void testNotifyItemMovedNoHeader() {
+ mWrappedAdapter.notifyItemMoved(12, 18);
+
+ verify(mObserver).onItemRangeMoved(eq(12), eq(18), eq(1));
+ }
+
+ /**
+ * Test that notifyItemMoved gets propagated by HeaderRecyclerView's adapter and adds 1 to the
+ * position for the extra header item.
+ */
+ @Test
+ public void testNotifyItemMovedWithHeader() {
+ mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
+ mWrappedAdapter.notifyItemMoved(12, 18);
+
+ verify(mObserver).onItemRangeMoved(eq(13), eq(19), eq(1));
+ }
+
+ /**
+ * Test adapter to be wrapped inside {@link HeaderAdapter} to to send item change notifications.
+ */
+ public static class TestAdapter extends RecyclerView.Adapter {
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
+ return null;
}
- /**
- * Test that notifyItemChanged gets propagated by HeaderRecyclerView's adapter.
- */
- @Test
- public void testNotifyItemChangedNoHeader() {
- mWrappedAdapter.notifyItemChanged(12);
-
- verify(mObserver).onItemRangeChanged(eq(12), eq(1), eq(null));
- }
-
- /**
- * Test that notifyItemChanged gets propagated by HeaderRecyclerView's adapter and adds 1 to the
- * position for the extra header items.
- */
- @Test
- public void testNotifyItemChangedWithHeader() {
- mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
- mWrappedAdapter.notifyItemChanged(12);
-
- verify(mObserver).onItemRangeChanged(eq(13), eq(1), eq(null));
- }
-
- /**
- * Test that notifyItemInserted gets propagated by HeaderRecyclerView's adapter.
- */
- @Test
- public void testNotifyItemInsertedNoHeader() {
- mWrappedAdapter.notifyItemInserted(12);
-
- verify(mObserver).onItemRangeInserted(eq(12), eq(1));
- }
-
- /**
- * Test that notifyItemInserted gets propagated by HeaderRecyclerView's adapter and adds 1 to
- * the position for the extra header item.
- */
- @Test
- public void testNotifyItemInsertedWithHeader() {
- mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
- mWrappedAdapter.notifyItemInserted(12);
-
- verify(mObserver).onItemRangeInserted(eq(13), eq(1));
- }
-
- /**
- * Test that notifyItemRemoved gets propagated by HeaderRecyclerView's adapter.
- */
- @Test
- public void testNotifyItemRemovedNoHeader() {
- mWrappedAdapter.notifyItemRemoved(12);
-
- verify(mObserver).onItemRangeRemoved(eq(12), eq(1));
- }
-
- /**
- * Test that notifyItemRemoved gets propagated by HeaderRecyclerView's adapter and adds 1 to
- * the position for the extra header item.
- */
- @Test
- public void testNotifyItemRemovedWithHeader() {
- mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
- mWrappedAdapter.notifyItemRemoved(12);
-
- verify(mObserver).onItemRangeRemoved(eq(13), eq(1));
- }
-
- /**
- * Test that notifyItemMoved gets propagated by HeaderRecyclerView's adapter.
- */
- @Test
- public void testNotifyItemMovedNoHeader() {
- mWrappedAdapter.notifyItemMoved(12, 18);
-
- verify(mObserver).onItemRangeMoved(eq(12), eq(18), eq(1));
- }
-
- /**
- * Test that notifyItemMoved gets propagated by HeaderRecyclerView's adapter and adds 1 to
- * the position for the extra header item.
- */
- @Test
- public void testNotifyItemMovedWithHeader() {
- mHeaderAdapter.setHeader(new View(InstrumentationRegistry.getTargetContext()));
- mWrappedAdapter.notifyItemMoved(12, 18);
-
- verify(mObserver).onItemRangeMoved(eq(13), eq(19), eq(1));
- }
-
- /**
- * Test adapter to be wrapped inside {@link HeaderAdapter} to to send item change notifications.
- */
- public static class TestAdapter extends RecyclerView.Adapter {
-
- @Override
- public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
- return null;
- }
-
- @Override
- public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
- }
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {}
- @Override
- public int getItemCount() {
- return 0;
- }
+ @Override
+ public int getItemCount() {
+ return 0;
}
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardPreferenceLayoutTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardPreferenceLayoutTest.java
index 316793f..39929dc 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardPreferenceLayoutTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardPreferenceLayoutTest.java
@@ -24,18 +24,15 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.setupwizardlib.SetupWizardPreferenceLayout;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,62 +41,65 @@ import org.junit.runner.RunWith;
@SmallTest
public class SetupWizardPreferenceLayoutTest {
- private Context mContext;
-
- @Before
- public void setUp() throws Exception {
- mContext = new ContextThemeWrapper(InstrumentationRegistry.getContext(),
- R.style.SuwThemeMaterial_Light);
- }
-
- @Test
- public void testDefaultTemplate() {
- SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
- assertPreferenceTemplateInflated(layout);
- }
-
- @Test
- public void testGetRecyclerView() {
- SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
- assertPreferenceTemplateInflated(layout);
- assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext =
+ new ContextThemeWrapper(
+ InstrumentationRegistry.getContext(), R.style.SuwThemeMaterial_Light);
+ }
+
+ @Test
+ public void testDefaultTemplate() {
+ SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
+ assertPreferenceTemplateInflated(layout);
+ }
+
+ @Test
+ public void testGetRecyclerView() {
+ SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
+ assertPreferenceTemplateInflated(layout);
+ assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
+ }
+
+ @Test
+ public void testOnCreateRecyclerView() {
+ SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
+ assertPreferenceTemplateInflated(layout);
+ final RecyclerView recyclerView =
+ layout.onCreateRecyclerView(
+ LayoutInflater.from(mContext), layout, null /* savedInstanceState */);
+ assertNotNull("RecyclerView created should not be null", recyclerView);
+ }
+
+ @Test
+ public void testDividerInset() {
+ SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
+ assertPreferenceTemplateInflated(layout);
- @Test
- public void testOnCreateRecyclerView() {
- SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
- assertPreferenceTemplateInflated(layout);
- final RecyclerView recyclerView = layout.onCreateRecyclerView(LayoutInflater.from(mContext),
- layout, null /* savedInstanceState */);
- assertNotNull("RecyclerView created should not be null", recyclerView);
- }
-
- @Test
- public void testDividerInset() {
- SetupWizardPreferenceLayout layout = new SetupWizardPreferenceLayout(mContext);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
- }
- assertPreferenceTemplateInflated(layout);
+ layout.addView(
+ layout.onCreateRecyclerView(
+ LayoutInflater.from(mContext), layout, null /* savedInstanceState */));
- layout.addView(layout.onCreateRecyclerView(LayoutInflater.from(mContext), layout,
- null /* savedInstanceState */));
+ layout.setDividerInset(10);
+ assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
- layout.setDividerInset(10);
- assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
+ final Drawable divider = layout.getDivider();
+ assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
+ }
- final Drawable divider = layout.getDivider();
- assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
- }
+ private void assertPreferenceTemplateInflated(SetupWizardPreferenceLayout layout) {
+ View contentContainer = layout.findViewById(R.id.suw_layout_content);
+ assertTrue(
+ "@id/suw_layout_content should be a ViewGroup", contentContainer instanceof ViewGroup);
- private void assertPreferenceTemplateInflated(SetupWizardPreferenceLayout layout) {
- View contentContainer = layout.findViewById(R.id.suw_layout_content);
- assertTrue("@id/suw_layout_content should be a ViewGroup",
- contentContainer instanceof ViewGroup);
-
- assertNotNull("Header text view should not be null",
- layout.findManagedViewById(R.id.suw_layout_title));
- assertNotNull("Decoration view should not be null",
- layout.findManagedViewById(R.id.suw_layout_decor));
- }
+ assertNotNull(
+ "Header text view should not be null", layout.findManagedViewById(R.id.suw_layout_title));
+ assertNotNull(
+ "Decoration view should not be null", layout.findManagedViewById(R.id.suw_layout_decor));
+ }
}
diff --git a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardRecyclerLayoutTest.java b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardRecyclerLayoutTest.java
index bbe773b..46a665d 100644
--- a/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardRecyclerLayoutTest.java
+++ b/library/recyclerview/test/instrumentation/src/com/android/setupwizardlib/test/SetupWizardRecyclerLayoutTest.java
@@ -26,21 +26,18 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.setupwizardlib.SetupWizardRecyclerLayout;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,133 +46,129 @@ import org.junit.runner.RunWith;
@SmallTest
public class SetupWizardRecyclerLayoutTest {
- private Context mContext;
-
- @Before
- public void setUp() throws Exception {
- mContext = new ContextThemeWrapper(InstrumentationRegistry.getContext(),
- R.style.SuwThemeMaterial_Light);
- }
-
- @Test
- public void testDefaultTemplate() {
- SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
- }
-
- @Test
- public void testInflateFromXml() {
- LayoutInflater inflater = LayoutInflater.from(mContext);
- SetupWizardRecyclerLayout layout = (SetupWizardRecyclerLayout)
- inflater.inflate(R.layout.test_recycler_layout, null);
- assertRecyclerTemplateInflated(layout);
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext =
+ new ContextThemeWrapper(
+ InstrumentationRegistry.getContext(), R.style.SuwThemeMaterial_Light);
+ }
+
+ @Test
+ public void testDefaultTemplate() {
+ SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+ }
+
+ @Test
+ public void testInflateFromXml() {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ SetupWizardRecyclerLayout layout =
+ (SetupWizardRecyclerLayout) inflater.inflate(R.layout.test_recycler_layout, null);
+ assertRecyclerTemplateInflated(layout);
+ }
+
+ @Test
+ public void testGetRecyclerView() {
+ SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+ assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
+ }
+
+ @Test
+ public void testAdapter() {
+ SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+
+ final Adapter adapter = createTestAdapter(1);
+ layout.setAdapter(adapter);
+
+ final Adapter gotAdapter = layout.getAdapter();
+ // Note: The wrapped adapter should be returned, not the HeaderAdapter.
+ assertSame("Adapter got from SetupWizardLayout should be same as set", adapter, gotAdapter);
+ }
+
+ @Test
+ public void testLayout() {
+ SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
+ assertRecyclerTemplateInflated(layout);
+
+ layout.setAdapter(createTestAdapter(3));
+
+ layout.measure(
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
+ layout.layout(0, 0, 500, 500);
+ // Test that the layout code doesn't crash.
+ }
+
+ @Test
+ public void testDividerInsetLegacy() {
+ SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
+ assertRecyclerTemplateInflated(layout);
- @Test
- public void testGetRecyclerView() {
- SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
- assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
- }
-
- @Test
- public void testAdapter() {
- SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
-
- final Adapter adapter = createTestAdapter(1);
- layout.setAdapter(adapter);
-
- final Adapter gotAdapter = layout.getAdapter();
- // Note: The wrapped adapter should be returned, not the HeaderAdapter.
- assertSame("Adapter got from SetupWizardLayout should be same as set",
- adapter, gotAdapter);
- }
-
- @Test
- public void testLayout() {
- SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
- assertRecyclerTemplateInflated(layout);
-
- layout.setAdapter(createTestAdapter(3));
-
- layout.measure(
- MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY));
- layout.layout(0, 0, 500, 500);
- // Test that the layout code doesn't crash.
- }
-
- @Test
- public void testDividerInsetLegacy() {
- SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
- }
- assertRecyclerTemplateInflated(layout);
+ layout.setDividerInset(10);
+ assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
- layout.setDividerInset(10);
- assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
+ final Drawable divider = layout.getDivider();
+ assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
+ }
- final Drawable divider = layout.getDivider();
- assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
+ @Test
+ public void testDividerInsets() {
+ SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
-
- @Test
- public void testDividerInsets() {
- SetupWizardRecyclerLayout layout = new SetupWizardRecyclerLayout(mContext);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
- }
- assertRecyclerTemplateInflated(layout);
-
- layout.setDividerInsets(10, 15);
- assertEquals("Divider inset start should be 10", 10, layout.getDividerInsetStart());
- assertEquals("Divider inset end should be 15", 15, layout.getDividerInsetEnd());
-
- final Drawable divider = layout.getDivider();
- assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
- }
-
- @Test
- public void testTemplateWithNoRecyclerView() {
- try {
- new SetupWizardRecyclerLayout(
- mContext,
- R.layout.suw_glif_template,
- R.id.suw_recycler_view);
- fail("Creating SetupWizardRecyclerLayout with no recycler view should throw exception");
- } catch (Exception e) {
- // pass
- }
- }
-
- private void assertRecyclerTemplateInflated(SetupWizardRecyclerLayout layout) {
- View recyclerView = layout.findViewById(R.id.suw_recycler_view);
- assertTrue("@id/suw_recycler_view should be a RecyclerView",
- recyclerView instanceof RecyclerView);
-
- assertNotNull("Header text view should not be null",
- layout.findManagedViewById(R.id.suw_layout_title));
- assertNotNull("Decoration view should not be null",
- layout.findManagedViewById(R.id.suw_layout_decor));
- }
-
- private Adapter createTestAdapter(final int itemCount) {
- return new Adapter() {
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
- return new ViewHolder(new View(parent.getContext())) {};
- }
-
- @Override
- public void onBindViewHolder(ViewHolder viewHolder, int position) {
- }
-
- @Override
- public int getItemCount() {
- return itemCount;
- }
- };
+ assertRecyclerTemplateInflated(layout);
+
+ layout.setDividerInsets(10, 15);
+ assertEquals("Divider inset start should be 10", 10, layout.getDividerInsetStart());
+ assertEquals("Divider inset end should be 15", 15, layout.getDividerInsetEnd());
+
+ final Drawable divider = layout.getDivider();
+ assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
+ }
+
+ @Test
+ public void testTemplateWithNoRecyclerView() {
+ try {
+ new SetupWizardRecyclerLayout(mContext, R.layout.suw_glif_template, R.id.suw_recycler_view);
+ fail("Creating SetupWizardRecyclerLayout with no recycler view should throw exception");
+ } catch (Exception e) {
+ // pass
}
+ }
+
+ private void assertRecyclerTemplateInflated(SetupWizardRecyclerLayout layout) {
+ View recyclerView = layout.findViewById(R.id.suw_recycler_view);
+ assertTrue(
+ "@id/suw_recycler_view should be a RecyclerView", recyclerView instanceof RecyclerView);
+
+ assertNotNull(
+ "Header text view should not be null", layout.findManagedViewById(R.id.suw_layout_title));
+ assertNotNull(
+ "Decoration view should not be null", layout.findManagedViewById(R.id.suw_layout_decor));
+ }
+
+ private Adapter createTestAdapter(final int itemCount) {
+ return new Adapter() {
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
+ return new ViewHolder(new View(parent.getContext())) {};
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder viewHolder, int position) {}
+
+ @Override
+ public int getItemCount() {
+ return itemCount;
+ }
+ };
+ }
}
diff --git a/library/recyclerview/test/robotest/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegateTest.java b/library/recyclerview/test/robotest/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegateTest.java
index 6fa4c54..bcb51a8 100644
--- a/library/recyclerview/test/robotest/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegateTest.java
+++ b/library/recyclerview/test/robotest/src/com/android/setupwizardlib/template/RecyclerViewScrollHandlingDelegateTest.java
@@ -26,63 +26,60 @@ import static org.robolectric.RuntimeEnvironment.application;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
-
-import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
-@Config(sdk = { Config.OLDEST_SDK, Config.NEWEST_SDK })
-@RunWith(SuwLibRobolectricTestRunner.class)
+@Config(sdk = {Config.OLDEST_SDK, Config.NEWEST_SDK})
+@RunWith(RobolectricTestRunner.class)
public class RecyclerViewScrollHandlingDelegateTest {
- @Mock
- private RequireScrollMixin mRequireScrollMixin;
-
- private RecyclerView mRecyclerView;
- private RecyclerViewScrollHandlingDelegate mDelegate;
- private ArgumentCaptor<OnScrollListener> mListenerCaptor;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- mRecyclerView = spy(new RecyclerView(application));
- doReturn(20).when(mRecyclerView).computeVerticalScrollRange();
- doReturn(0).when(mRecyclerView).computeVerticalScrollExtent();
- doReturn(0).when(mRecyclerView).computeVerticalScrollOffset();
- mListenerCaptor = ArgumentCaptor.forClass(OnScrollListener.class);
- doNothing().when(mRecyclerView).addOnScrollListener(mListenerCaptor.capture());
-
- mDelegate = new RecyclerViewScrollHandlingDelegate(mRequireScrollMixin, mRecyclerView);
- mRecyclerView.layout(0, 0, 50, 50);
- }
-
- @Test
- public void testRequireScroll() {
- mDelegate.startListening();
- verify(mRequireScrollMixin).notifyScrollabilityChange(true);
- }
-
- @Test
- public void testScrolledToBottom() {
- mDelegate.startListening();
- verify(mRequireScrollMixin).notifyScrollabilityChange(true);
-
- doReturn(20).when(mRecyclerView).computeVerticalScrollOffset();
- mListenerCaptor.getValue().onScrolled(mRecyclerView, 0, 20);
-
- verify(mRequireScrollMixin).notifyScrollabilityChange(false);
- }
-
- @Test
- public void testClickScrollButton() {
- mDelegate.pageScrollDown();
- verify(mRecyclerView).smoothScrollBy(anyInt(), eq(50));
- }
+ @Mock private RequireScrollMixin mRequireScrollMixin;
+
+ private RecyclerView mRecyclerView;
+ private RecyclerViewScrollHandlingDelegate mDelegate;
+ private ArgumentCaptor<OnScrollListener> mListenerCaptor;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mRecyclerView = spy(new RecyclerView(application));
+ doReturn(20).when(mRecyclerView).computeVerticalScrollRange();
+ doReturn(0).when(mRecyclerView).computeVerticalScrollExtent();
+ doReturn(0).when(mRecyclerView).computeVerticalScrollOffset();
+ mListenerCaptor = ArgumentCaptor.forClass(OnScrollListener.class);
+ doNothing().when(mRecyclerView).addOnScrollListener(mListenerCaptor.capture());
+
+ mDelegate = new RecyclerViewScrollHandlingDelegate(mRequireScrollMixin, mRecyclerView);
+ mRecyclerView.layout(0, 0, 50, 50);
+ }
+
+ @Test
+ public void testRequireScroll() {
+ mDelegate.startListening();
+ verify(mRequireScrollMixin).notifyScrollabilityChange(true);
+ }
+
+ @Test
+ public void testScrolledToBottom() {
+ mDelegate.startListening();
+ verify(mRequireScrollMixin).notifyScrollabilityChange(true);
+
+ doReturn(20).when(mRecyclerView).computeVerticalScrollOffset();
+ mListenerCaptor.getValue().onScrolled(mRecyclerView, 0, 20);
+
+ verify(mRequireScrollMixin).notifyScrollabilityChange(false);
+ }
+
+ @Test
+ public void testClickScrollButton() {
+ mDelegate.pageScrollDown();
+ verify(mRecyclerView).smoothScrollBy(anyInt(), eq(50));
+ }
}