1 package com.android.car.app; 2 3 import android.content.Context; 4 import android.graphics.PorterDuff; 5 import android.graphics.drawable.Drawable; 6 import android.support.annotation.NonNull; 7 import android.support.annotation.Nullable; 8 import android.support.annotation.StringRes; 9 import android.support.car.ui.PagedListView; 10 import android.support.v7.widget.RecyclerView; 11 import android.view.LayoutInflater; 12 import android.view.View; 13 import android.view.ViewGroup; 14 15 import com.android.car.stream.ui.R; 16 17 /** 18 * Base Adapter for displaying items in the CarDrawerActivity's Drawer which uses a PagedListView. 19 * <p> 20 * Subclasses must set the title that will be displayed when displaying the contents of the 21 * Drawer via {@link #setTitle(CharSequence)}. The title can be updated at any point later. The 22 * title of the root-adapter will also be the main title showed in the toolbar when the drawer is 23 * closed. 24 * <p> 25 * This class also takes care of implementing the PageListView.ItemCamp contract and subclasses 26 * should implement {@link #getActualItemCount()}. 27 */ 28 public abstract class CarDrawerAdapter extends RecyclerView.Adapter<DrawerItemViewHolder> implements 29 PagedListView.ItemCap, 30 DrawerItemClickListener { 31 interface TitleChangeListener { 32 void onTitleChanged(CharSequence newTitle); 33 } 34 35 private final boolean mShowDisabledListOnEmpty; 36 private final boolean mUseSmallLayout; 37 private final Drawable mEmptyListDrawable; 38 private int mMaxItems = -1; 39 private CharSequence mTitle; 40 private TitleChangeListener mTitleChangeListener; 41 42 protected CarDrawerAdapter( 43 Context context, boolean showDisabledListOnEmpty,boolean useSmallLayout) { 44 mShowDisabledListOnEmpty = showDisabledListOnEmpty; 45 mUseSmallLayout = useSmallLayout; 46 final int iconColor = context.getColor(R.color.car_tint); 47 mEmptyListDrawable = context.getDrawable(R.drawable.ic_list_view_disable); 48 mEmptyListDrawable.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); 49 } 50 51 CharSequence getTitle() { 52 return mTitle; 53 } 54 55 /** 56 * Updates the title to display in the toolbar for this Adapter. 57 * 58 * @param title Title string. 59 */ 60 public final void setTitle(@NonNull CharSequence title) { 61 if (title == null) { 62 throw new IllegalArgumentException("title is null!"); 63 } 64 mTitle = title; 65 if (mTitleChangeListener != null) { 66 mTitleChangeListener.onTitleChanged(mTitle); 67 } 68 } 69 70 void setTitleChangeListener(@Nullable TitleChangeListener listener) { 71 mTitleChangeListener = listener; 72 } 73 74 // ItemCap implementation. 75 @Override 76 public final void setMaxItems(int maxItems) { 77 mMaxItems = maxItems; 78 } 79 80 private boolean shouldShowDisabledListItem() { 81 return mShowDisabledListOnEmpty && getActualItemCount() == 0; 82 } 83 84 // Honors ItemCap and mShowDisabledListOnEmpty. 85 @Override 86 public final int getItemCount() { 87 if (shouldShowDisabledListItem()) { 88 return 1; 89 } 90 return mMaxItems >= 0 ? Math.min(mMaxItems, getActualItemCount()) : getActualItemCount(); 91 } 92 93 /** 94 * @return Actual number of items in this adapter. 95 */ 96 protected abstract int getActualItemCount(); 97 98 @Override 99 public final int getItemViewType(int position) { 100 if (shouldShowDisabledListItem()) { 101 return R.layout.car_list_item_empty; 102 } 103 return mUseSmallLayout 104 ? R.layout.car_menu_list_item_small : R.layout.car_menu_list_item_normal; 105 } 106 107 @Override 108 public final DrawerItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 109 View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false); 110 return new DrawerItemViewHolder(view); 111 } 112 113 @Override 114 public final void onBindViewHolder(DrawerItemViewHolder holder, int position) { 115 if (shouldShowDisabledListItem()) { 116 holder.getTitle().setText(null); 117 holder.getIcon().setImageDrawable(mEmptyListDrawable); 118 holder.setItemClickListener(null); 119 } else { 120 holder.setItemClickListener(this); 121 populateViewHolder(holder, position); 122 } 123 } 124 125 /** 126 * Subclasses should set all elements in {@code holder} to populate the drawer-item. 127 * If some element is not used, it should be nulled out since these ViewHolder/View's are 128 * recycled. 129 */ 130 protected abstract void populateViewHolder(DrawerItemViewHolder holder, int position); 131 132 /** 133 * Called when this adapter has been popped off the stack and is no longer needed. Subclasses 134 * can override to do any necessary cleanup. 135 */ 136 public void cleanup() {} 137 } 138