diff options
Diffstat (limited to 'library/recyclerview/src/com/android/setupwizardlib/template/RecyclerMixin.java')
-rw-r--r-- | library/recyclerview/src/com/android/setupwizardlib/template/RecyclerMixin.java | 393 |
1 files changed, 188 insertions, 205 deletions
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(); + } } |