diff options
Diffstat (limited to 'androidx/car/widget/ListItem.java')
-rw-r--r-- | androidx/car/widget/ListItem.java | 731 |
1 files changed, 60 insertions, 671 deletions
diff --git a/androidx/car/widget/ListItem.java b/androidx/car/widget/ListItem.java index d292d6b2..74ff2dd5 100644 --- a/androidx/car/widget/ListItem.java +++ b/androidx/car/widget/ListItem.java @@ -1,701 +1,90 @@ -/* - * Copyright 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package androidx.car.widget; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.support.annotation.DrawableRes; -import android.support.annotation.IntDef; import android.support.v7.widget.RecyclerView; -import android.text.TextUtils; -import android.view.View; -import android.widget.RelativeLayout; -import java.lang.annotation.Retention; -import java.util.ArrayList; -import java.util.List; - -import androidx.car.R; +import java.util.function.Function; /** - * Class to build a list item. - * - * <p>An item supports primary action and supplemental action(s). + * Definition of items that can be inserted into {@link ListItemAdapter}. * - * <p>An item visually composes of 3 parts; each part may contain multiple views. - * <ul> - * <li>{@code Primary Action}: represented by an icon of following types. - * <ul> - * <li>Primary Icon - icon size could be large or small. - * <li>No Icon - * <li>Empty Icon - different from No Icon by how much margin {@code Text} offsets - * </ul> - * <li>{@code Text}: supports any combination of the follow text views. - * <ul> - * <li>Title - * <li>Body - * </ul> - * <li>{@code Supplemental Action(s)}: represented by one of the following types; aligned toward - * the end of item. - * <ul> - * <li>Supplemental Icon - * <li>One Action Button - * <li>Two Action Buttons - * </ul> - * </ul> - * - * {@link ListItem} can be built through its {@link ListItem.Builder}. It binds data - * to {@link ListItemAdapter.ViewHolder} based on components selected. + * @param <VH> ViewHolder. */ -public class ListItem { +public abstract class ListItem<VH extends RecyclerView.ViewHolder> { - private Builder mBuilder; + // Whether the item should calculate view layout params. This usually happens when the item is + // updated after bind() is called. Calling bind() resets to false. + private boolean mDirty; - private ListItem(Builder builder) { - mBuilder = builder; - } + // Tag for indicating whether to hide the divider. + private boolean mHideDivider; + + /** + * Classes that extends {@code ListItem} should register its view type in + * {@link ListItemAdapter#registerListItemViewType(int, int, Function)}. + * + * @return type of this ListItem. + */ + abstract int getViewType(); + + /** + * Called when ListItem is bound to its ViewHolder. + */ + public abstract void bind(VH viewHolder); /** - * Applies all {@link ViewBinder} to {@code viewHolder}. + * Marks this item so that sub-views in ViewHolder will need layout params re-calculated + * in next bind(). + * + * This method should be called in each setter. */ - void bind(ListItemAdapter.ViewHolder viewHolder) { - setAllSubViewsGone(viewHolder); - for (ViewBinder binder : mBuilder.mBinders) { - binder.bind(viewHolder); - } + protected void markDirty() { + mDirty = true; } - void setAllSubViewsGone(ListItemAdapter.ViewHolder vh) { - View[] subviews = new View[] { - vh.getPrimaryIcon(), - vh.getTitle(), vh.getBody(), - vh.getSupplementalIcon(), vh.getSupplementalIconDivider(), - vh.getAction1(), vh.getAction1Divider(), vh.getAction2(), vh.getAction2Divider()}; - for (View v : subviews) { - v.setVisibility(View.GONE); - } + /** + * Marks this item as not dirty - no need to calculate sub-view layout params in bind(). + */ + protected void markClean() { + mDirty = false; } /** - * Functional interface to provide a way to interact with views in - * {@link ListItemAdapter.ViewHolder}. {@code ViewBinder}s added to a - * {@code ListItem} will be called when {@code ListItem} {@code bind}s to - * {@link ListItemAdapter.ViewHolder}. + * @return {@code true} if this item needs to calculate sub-view layout params. */ - public interface ViewBinder { - /** - * Provides a way to interact with views in view holder. - */ - void bind(ListItemAdapter.ViewHolder viewHolder); + protected boolean isDirty() { + return mDirty; } /** - * Builds a {@link ListItem}. + * Whether hide the item divider coming after this {@code ListItem}. * - * <p>With conflicting methods are called, e.g. setting primary action to both primary icon and - * no icon, the last called method wins. + * <p>Note: For this to work, one must invoke + * {@code PagedListView.setDividerVisibilityManager(adapter} for {@link ListItemAdapter} and + * have dividers enabled on {@link PagedListView}. */ - public static class Builder { - - @Retention(SOURCE) - @IntDef({ - PRIMARY_ACTION_TYPE_NO_ICON, PRIMARY_ACTION_TYPE_EMPTY_ICON, - PRIMARY_ACTION_TYPE_LARGE_ICON, PRIMARY_ACTION_TYPE_SMALL_ICON}) - private @interface PrimaryActionType {} - - private static final int PRIMARY_ACTION_TYPE_NO_ICON = 0; - private static final int PRIMARY_ACTION_TYPE_EMPTY_ICON = 1; - private static final int PRIMARY_ACTION_TYPE_LARGE_ICON = 2; - private static final int PRIMARY_ACTION_TYPE_SMALL_ICON = 3; - - @Retention(SOURCE) - @IntDef({SUPPLEMENTAL_ACTION_NO_ACTION, SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON, - SUPPLEMENTAL_ACTION_ONE_ACTION, SUPPLEMENTAL_ACTION_TWO_ACTIONS}) - private @interface SupplementalActionType {} - - private static final int SUPPLEMENTAL_ACTION_NO_ACTION = 0; - private static final int SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON = 1; - private static final int SUPPLEMENTAL_ACTION_ONE_ACTION = 2; - private static final int SUPPLEMENTAL_ACTION_TWO_ACTIONS = 3; - - private final Context mContext; - private final List<ViewBinder> mBinders = new ArrayList<>(); - // Store custom binders separately so they will bind after binders are created in build(). - private final List<ViewBinder> mCustomBinders = new ArrayList<>(); - - private View.OnClickListener mOnClickListener; - - @PrimaryActionType private int mPrimaryActionType = PRIMARY_ACTION_TYPE_NO_ICON; - private int mPrimaryActionIconResId; - private Drawable mPrimaryActionIconDrawable; - - private String mTitle; - private String mBody; - private boolean mIsBodyPrimary; - - @SupplementalActionType private int mSupplementalActionType = SUPPLEMENTAL_ACTION_NO_ACTION; - private int mSupplementalIconResId; - private View.OnClickListener mSupplementalIconOnClickListener; - private boolean mShowSupplementalIconDivider; - - private String mAction1Text; - private View.OnClickListener mAction1OnClickListener; - private boolean mShowAction1Divider; - private String mAction2Text; - private View.OnClickListener mAction2OnClickListener; - private boolean mShowAction2Divider; - - public Builder(Context context) { - mContext = context; - } - - /** - * Builds a {@link ListItem}. Adds {@link ViewBinder}s that will adjust layout in - * {@link ListItemAdapter.ViewHolder} depending on sub-views used. - */ - public ListItem build() { - setItemLayoutHeight(); - setPrimaryAction(); - setText(); - setSupplementalActions(); - setOnClickListener(); - - mBinders.addAll(mCustomBinders); - - return new ListItem(this); - } - - /** - * Sets the height of item depending on which text field is set. - */ - private void setItemLayoutHeight() { - if (TextUtils.isEmpty(mBody)) { - // If the item only has title or no text, it uses fixed-height as single line. - int height = (int) mContext.getResources().getDimension( - R.dimen.car_single_line_list_item_height); - mBinders.add((vh) -> { - RecyclerView.LayoutParams layoutParams = - (RecyclerView.LayoutParams) vh.itemView.getLayoutParams(); - layoutParams.height = height; - vh.itemView.setLayoutParams(layoutParams); - }); - } else { - // If body is present, the item should be at least as tall as min height, and wraps - // content. - int minHeight = (int) mContext.getResources().getDimension( - R.dimen.car_double_line_list_item_height); - mBinders.add((vh) -> { - vh.itemView.setMinimumHeight(minHeight); - vh.getContainerLayout().setMinimumHeight(minHeight); - - RecyclerView.LayoutParams layoutParams = - (RecyclerView.LayoutParams) vh.itemView.getLayoutParams(); - layoutParams.height = RecyclerView.LayoutParams.WRAP_CONTENT; - vh.itemView.setLayoutParams(layoutParams); - }); - } - } - - private void setPrimaryAction() { - setPrimaryIconContent(); - setPrimaryIconLayout(); - } - - private void setText() { - setTextContent(); - setTextVerticalMargin(); - // Only setting start margin because text end is relative to the start of supplemental - // actions. - setTextStartMargin(); - } - - private void setOnClickListener() { - if (mOnClickListener != null) { - mBinders.add(vh -> vh.itemView.setOnClickListener(mOnClickListener)); - } - } - - private void setPrimaryIconContent() { - switch (mPrimaryActionType) { - case PRIMARY_ACTION_TYPE_SMALL_ICON: - case PRIMARY_ACTION_TYPE_LARGE_ICON: - mBinders.add((vh) -> { - vh.getPrimaryIcon().setVisibility(View.VISIBLE); - - if (mPrimaryActionIconDrawable != null) { - vh.getPrimaryIcon().setImageDrawable(mPrimaryActionIconDrawable); - } else if (mPrimaryActionIconResId != 0) { - vh.getPrimaryIcon().setImageResource(mPrimaryActionIconResId); - } - }); - break; - case PRIMARY_ACTION_TYPE_EMPTY_ICON: - case PRIMARY_ACTION_TYPE_NO_ICON: - // Do nothing. - break; - default: - throw new IllegalStateException("Unrecognizable primary action type."); - } - } - - /** - * Sets layout params of primary icon. - * - * <p>Large icon will have no start margin, and always align center vertically. - * - * <p>Small icon will have start margin. When body text is present small icon uses a top - * margin otherwise align center vertically. - */ - private void setPrimaryIconLayout() { - // Set all relevant fields in layout params to avoid carried over params when the item - // gets bound to a recycled view holder. - switch (mPrimaryActionType) { - case PRIMARY_ACTION_TYPE_SMALL_ICON: - mBinders.add(vh -> { - int iconSize = mContext.getResources().getDimensionPixelSize( - R.dimen.car_primary_icon_size); - // Icon size. - RelativeLayout.LayoutParams layoutParams = - (RelativeLayout.LayoutParams) vh.getPrimaryIcon().getLayoutParams(); - layoutParams.height = iconSize; - layoutParams.width = iconSize; - - // Start margin. - layoutParams.setMarginStart(mContext.getResources().getDimensionPixelSize( - R.dimen.car_keyline_1)); - - if (!TextUtils.isEmpty(mBody)) { - // Set top margin. - layoutParams.removeRule(RelativeLayout.CENTER_VERTICAL); - layoutParams.topMargin = mContext.getResources().getDimensionPixelSize( - R.dimen.car_padding_4); - } else { - // Centered vertically. - layoutParams.addRule(RelativeLayout.CENTER_VERTICAL); - layoutParams.topMargin = 0; - } - vh.getPrimaryIcon().setLayoutParams(layoutParams); - }); - break; - case PRIMARY_ACTION_TYPE_LARGE_ICON: - mBinders.add(vh -> { - int iconSize = mContext.getResources().getDimensionPixelSize( - R.dimen.car_single_line_list_item_height); - // Icon size. - RelativeLayout.LayoutParams layoutParams = - (RelativeLayout.LayoutParams) vh.getPrimaryIcon().getLayoutParams(); - layoutParams.height = iconSize; - layoutParams.width = iconSize; - - // No start margin. - layoutParams.setMarginStart(0); - - // Always centered vertically. - layoutParams.addRule(RelativeLayout.CENTER_VERTICAL); - layoutParams.topMargin = 0; - - vh.getPrimaryIcon().setLayoutParams(layoutParams); - }); - break; - case PRIMARY_ACTION_TYPE_EMPTY_ICON: - case PRIMARY_ACTION_TYPE_NO_ICON: - // Do nothing. - break; - default: - throw new IllegalStateException("Unrecognizable primary action type."); - } - } - - private void setTextContent() { - if (!TextUtils.isEmpty(mTitle)) { - mBinders.add(vh -> { - vh.getTitle().setVisibility(View.VISIBLE); - vh.getTitle().setText(mTitle); - }); - } - if (!TextUtils.isEmpty(mBody)) { - mBinders.add(vh -> { - vh.getBody().setVisibility(View.VISIBLE); - vh.getBody().setText(mBody); - }); - } - - if (mIsBodyPrimary) { - mBinders.add((vh) -> { - vh.getTitle().setTextAppearance(R.style.CarBody2); - vh.getBody().setTextAppearance(R.style.CarBody1); - }); - } else { - mBinders.add((vh) -> { - vh.getTitle().setTextAppearance(R.style.CarBody1); - vh.getBody().setTextAppearance(R.style.CarBody2); - }); - } - } - - /** - * Sets start margin of text view depending on icon type. - */ - private void setTextStartMargin() { - final int startMarginResId; - switch (mPrimaryActionType) { - case PRIMARY_ACTION_TYPE_NO_ICON: - startMarginResId = R.dimen.car_keyline_1; - break; - case PRIMARY_ACTION_TYPE_EMPTY_ICON: - startMarginResId = R.dimen.car_keyline_3; - break; - case PRIMARY_ACTION_TYPE_SMALL_ICON: - startMarginResId = R.dimen.car_keyline_3; - break; - case PRIMARY_ACTION_TYPE_LARGE_ICON: - startMarginResId = R.dimen.car_keyline_4; - break; - default: - throw new IllegalStateException("Unrecognizable primary action type."); - } - int startMargin = mContext.getResources().getDimensionPixelSize(startMarginResId); - mBinders.add(vh -> { - RelativeLayout.LayoutParams titleLayoutParams = - (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams(); - titleLayoutParams.setMarginStart(startMargin); - vh.getTitle().setLayoutParams(titleLayoutParams); - - RelativeLayout.LayoutParams bodyLayoutParams = - (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams(); - bodyLayoutParams.setMarginStart(startMargin); - vh.getBody().setLayoutParams(bodyLayoutParams); - }); - } - - /** - * Sets top/bottom margins of {@code Title} and {@code Body}. - */ - private void setTextVerticalMargin() { - // Set all relevant fields in layout params to avoid carried over params when the item - // gets bound to a recycled view holder. - if (!TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mBody)) { - // Title only - view is aligned center vertically by itself. - mBinders.add(vh -> { - RelativeLayout.LayoutParams layoutParams = - (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams(); - layoutParams.addRule(RelativeLayout.CENTER_VERTICAL); - layoutParams.topMargin = 0; - vh.getTitle().setLayoutParams(layoutParams); - }); - } else if (TextUtils.isEmpty(mTitle) && !TextUtils.isEmpty(mBody)) { - mBinders.add(vh -> { - // Body uses top and bottom margin. - int margin = mContext.getResources().getDimensionPixelSize( - R.dimen.car_padding_3); - RelativeLayout.LayoutParams layoutParams = - (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams(); - layoutParams.addRule(RelativeLayout.CENTER_VERTICAL); - layoutParams.removeRule(RelativeLayout.BELOW); - layoutParams.topMargin = margin; - layoutParams.bottomMargin = margin; - vh.getBody().setLayoutParams(layoutParams); - }); - } else { - mBinders.add(vh -> { - // Title has a top margin - Resources resources = mContext.getResources(); - int padding1 = resources.getDimensionPixelSize(R.dimen.car_padding_1); - int padding3 = resources.getDimensionPixelSize(R.dimen.car_padding_3); - - RelativeLayout.LayoutParams titleLayoutParams = - (RelativeLayout.LayoutParams) vh.getTitle().getLayoutParams(); - titleLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL); - titleLayoutParams.topMargin = padding3; - vh.getTitle().setLayoutParams(titleLayoutParams); - // Body is below title with a margin, and has bottom margin. - RelativeLayout.LayoutParams bodyLayoutParams = - (RelativeLayout.LayoutParams) vh.getBody().getLayoutParams(); - bodyLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL); - bodyLayoutParams.addRule(RelativeLayout.BELOW, R.id.title); - bodyLayoutParams.topMargin = padding1; - bodyLayoutParams.bottomMargin = padding3; - vh.getBody().setLayoutParams(bodyLayoutParams); - }); - } - } - - /** - * Sets up view(s) for supplemental action. - */ - private void setSupplementalActions() { - switch (mSupplementalActionType) { - case SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON: - mBinders.add((vh) -> { - vh.getSupplementalIcon().setVisibility(View.VISIBLE); - if (mShowSupplementalIconDivider) { - vh.getSupplementalIconDivider().setVisibility(View.VISIBLE); - } - - vh.getSupplementalIcon().setImageResource(mSupplementalIconResId); - vh.getSupplementalIcon().setOnClickListener( - mSupplementalIconOnClickListener); - vh.getSupplementalIcon().setClickable( - mSupplementalIconOnClickListener != null); - }); - break; - case SUPPLEMENTAL_ACTION_TWO_ACTIONS: - mBinders.add((vh) -> { - vh.getAction2().setVisibility(View.VISIBLE); - if (mShowAction2Divider) { - vh.getAction2Divider().setVisibility(View.VISIBLE); - } - - vh.getAction2().setText(mAction2Text); - vh.getAction2().setOnClickListener(mAction2OnClickListener); - }); - // Fall through - case SUPPLEMENTAL_ACTION_ONE_ACTION: - mBinders.add((vh) -> { - vh.getAction1().setVisibility(View.VISIBLE); - if (mShowAction1Divider) { - vh.getAction1Divider().setVisibility(View.VISIBLE); - } - - vh.getAction1().setText(mAction1Text); - vh.getAction1().setOnClickListener(mAction1OnClickListener); - }); - break; - case SUPPLEMENTAL_ACTION_NO_ACTION: - // Do nothing - break; - default: - throw new IllegalArgumentException("Unrecognized supplemental action type."); - } - } - - /** - * Sets {@link View.OnClickListener} of {@code ListItem}. - * - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withOnClickListener(View.OnClickListener listener) { - mOnClickListener = listener; - return this; - } - - /** - * Sets {@code Primary Action} to be represented by an icon. - * - * @param iconResId the resource identifier of the drawable. - * @param useLargeIcon the size of primary icon. Large Icon is a square as tall as an item - * with only title set; useful for album cover art. - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withPrimaryActionIcon(@DrawableRes int iconResId, boolean useLargeIcon) { - return withPrimaryActionIcon(null, iconResId, useLargeIcon); - } - - /** - * Sets {@code Primary Action} to be represented by an icon. - * - * @param drawable the Drawable to set, or null to clear the content. - * @param useLargeIcon the size of primary icon. Large Icon is a square as tall as an item - * with only title set; useful for album cover art. - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withPrimaryActionIcon(Drawable drawable, boolean useLargeIcon) { - return withPrimaryActionIcon(drawable, 0, useLargeIcon); - } - - private Builder withPrimaryActionIcon(Drawable drawable, @DrawableRes int iconResId, - boolean useLargeIcon) { - mPrimaryActionType = useLargeIcon - ? PRIMARY_ACTION_TYPE_LARGE_ICON - : PRIMARY_ACTION_TYPE_SMALL_ICON; - mPrimaryActionIconResId = iconResId; - mPrimaryActionIconDrawable = drawable; - return this; - } - - /** - * Sets {@code Primary Action} to be empty icon. - * - * {@code Text} would have a start margin as if {@code Primary Action} were set to - * primary icon. - * - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withPrimaryActionEmptyIcon() { - mPrimaryActionType = PRIMARY_ACTION_TYPE_EMPTY_ICON; - return this; - } - - /** - * Sets {@code Primary Action} to have no icon. Text would align to the start of item. - * - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withPrimaryActionNoIcon() { - mPrimaryActionType = PRIMARY_ACTION_TYPE_NO_ICON; - return this; - } - - /** - * Sets the title of item. - * - * <p>Primary text is {@code title} by default. It can be set by - * {@link #withBody(String, boolean)} - * - * @param title text to display as title. - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withTitle(String title) { - mTitle = title; - return this; - } - - /** - * Sets the body text of item. - * - * <p>Text beyond length required by regulation will be truncated. Defaults {@code Title} - * text as the primary. - * - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withBody(String body) { - return withBody(body, false); - } - - /** - * Sets the body text of item. - * - * <p>Text beyond length required by regulation will be truncated. - * - * @param asPrimary sets {@code Body Text} as primary text of item. - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withBody(String body, boolean asPrimary) { - int limit = mContext.getResources().getInteger( - R.integer.car_list_item_text_length_limit); - if (body.length() < limit) { - mBody = body; - } else { - mBody = body.substring(0, limit) + mContext.getString(R.string.ellipsis); - } - mIsBodyPrimary = asPrimary; - return this; - } - - /** - * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}. - * - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withSupplementalIcon(int iconResId, boolean showDivider) { - return withSupplementalIcon(iconResId, showDivider, null); - } - - /** - * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}. - * - * @param iconResId drawable resource id. - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withSupplementalIcon(int iconResId, boolean showDivider, - View.OnClickListener listener) { - mSupplementalActionType = SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON; - - mSupplementalIconResId = iconResId; - mSupplementalIconOnClickListener = listener; - mShowSupplementalIconDivider = showDivider; - return this; - } - - /** - * Sets {@code Supplemental Action} to be represented by an {@code Action Button}. - * - * @param text button text to display. - * @return This Builder object to allow for chaining calls to set methods. - */ - public Builder withAction(String text, boolean showDivider, View.OnClickListener listener) { - if (TextUtils.isEmpty(text)) { - throw new IllegalArgumentException("Action text cannot be empty."); - } - if (listener == null) { - throw new IllegalArgumentException("Action OnClickListener cannot be null."); - } - mSupplementalActionType = SUPPLEMENTAL_ACTION_ONE_ACTION; - - mAction1Text = text; - mAction1OnClickListener = listener; - mShowAction1Divider = showDivider; - return this; - } - - /** - * Sets {@code Supplemental Action} to be represented by two {@code Action Button}s. - * - * <p>These two action buttons will be aligned towards item end. - * - * @param action1Text button text to display - this button will be closer to item end. - * @param action2Text button text to display. - */ - public Builder withActions(String action1Text, boolean showAction1Divider, - View.OnClickListener action1OnClickListener, - String action2Text, boolean showAction2Divider, - View.OnClickListener action2OnClickListener) { - if (TextUtils.isEmpty(action1Text) || TextUtils.isEmpty(action2Text)) { - throw new IllegalArgumentException("Action text cannot be empty."); - } - if (action1OnClickListener == null || action2OnClickListener == null) { - throw new IllegalArgumentException("Action OnClickListener cannot be null."); - } - mSupplementalActionType = SUPPLEMENTAL_ACTION_TWO_ACTIONS; + public void setHideDivider(boolean hideDivider) { + mHideDivider = hideDivider; + markDirty(); + } - mAction1Text = action1Text; - mAction1OnClickListener = action1OnClickListener; - mShowAction1Divider = showAction1Divider; - mAction2Text = action2Text; - mAction2OnClickListener = action2OnClickListener; - mShowAction2Divider = showAction2Divider; - return this; - } + /** + * @return {@code true} if the divider that comes after this ListItem should be hidden. + * Defaults to false. + */ + public boolean shouldHideDivider() { + return mHideDivider; + }; + /** + * Functional interface to provide a way to interact with views in {@code ViewHolder}. + * {@code ListItem} calls all added ViewBinders when it {@code bind}s to {@code ViewHolder}. + * + * @param <VH> extends {@link RecyclerView.ViewHolder}. + */ + public interface ViewBinder<VH extends RecyclerView.ViewHolder> { /** - * Adds {@link ViewBinder} to interact with sub-views in - * {@link ListItemAdapter.ViewHolder}. These ViewBinders will always bind after - * other {@link Builder} methods have bond. - * - * <p>Make sure to call with...() method on the intended sub-view first. - * - * <p>Example: - * <pre> - * {@code - * new Builder() - * .withTitle("title") - * .withViewBinder((viewHolder) -> { - * viewHolder.getTitle().doMoreStuff(); - * }) - * .build(); - * } - * </pre> + * Provides a way to interact with views in view holder. */ - public Builder withViewBinder(ViewBinder binder) { - mCustomBinders.add(binder); - return this; - } + void bind(VH viewHolder); } } |