Home | History | Annotate | Download | only in list
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.car.list;
     18 
     19 import static java.lang.annotation.RetentionPolicy.SOURCE;
     20 
     21 import android.annotation.CallSuper;
     22 import android.annotation.IntDef;
     23 import android.annotation.NonNull;
     24 import android.support.v7.widget.RecyclerView;
     25 import android.support.v7.widget.RecyclerView.ViewHolder;
     26 import android.view.View;
     27 import android.view.ViewGroup;
     28 
     29 import java.lang.annotation.Retention;
     30 import java.util.ArrayList;
     31 
     32 import androidx.car.widget.PagedListView;
     33 
     34 /**
     35  * Renders all types of LineItem to a view to be displayed as a row in a list.
     36  */
     37 public class TypedPagedListAdapter extends RecyclerView.Adapter<ViewHolder>
     38         implements PagedListView.ItemCap {
     39 
     40     private ArrayList<LineItem> mContentList;
     41 
     42     /**
     43      * Constructor instance of {@link TypedPagedListAdapter} with an empty content list
     44      */
     45     public TypedPagedListAdapter() {
     46         this(new ArrayList<>());
     47     }
     48 
     49     /**
     50      * Constructor instance of {@link TypedPagedListAdapter} with content list
     51      *
     52      * @param contentList what is contained in the adapter
     53      */
     54     public TypedPagedListAdapter(ArrayList<LineItem> contentList) {
     55         mContentList = contentList;
     56     }
     57 
     58     /**
     59      * Sets current content list to new content list and calls
     60      * {@link RecyclerView.Adapter#notifyDataSetChanged()}
     61      *
     62      * @param contentList New content list
     63      */
     64     public void setList(@NonNull ArrayList<LineItem> contentList) {
     65         mContentList = contentList;
     66         notifyDataSetChanged();
     67     }
     68 
     69     /**
     70      * Adds all items to the content list at given index and calls
     71      * {@link RecyclerView.Adapter#notifyDataSetChanged()}
     72      *
     73      * @param index index at which to insert the first element from the specified list
     74      * @param lineItems list containing items to add
     75      *
     76      * @throws IndexOutOfBoundsException thrown when index is out of bounds
     77      */
     78     public void addAll(int index, @NonNull ArrayList<LineItem> lineItems) {
     79         if (index < 0 || index > mContentList.size()) {
     80             throw new IndexOutOfBoundsException(
     81                     "Index: " + index + ", Size: " + mContentList.size());
     82         }
     83         mContentList.addAll(index, lineItems);
     84         notifyDataSetChanged();
     85     }
     86 
     87     /**
     88      * Removes an item from the content list at the given index and calls
     89      * {@link RecyclerView.Adapter#notifyDataSetChanged()}
     90      *
     91      * @param index the index of the item to be removed
     92      */
     93     public void remove(int index) {
     94         if (index >= mContentList.size()) {
     95             throw  new IndexOutOfBoundsException(
     96                     "Index: " + index + ", Size: " + mContentList.size());
     97         }
     98         mContentList.remove(index);
     99         notifyItemRemoved(index);
    100     }
    101 
    102     /**
    103      * Return true if empty, false if not.
    104      */
    105     public boolean isEmpty() {
    106         return mContentList.isEmpty();
    107     }
    108 
    109     /**
    110      * Definition for items that are able to be inserted into the TypedPagedListAdapter
    111      *
    112      * @param  viewHolder for use with {@link TypedPagedListAdapter}
    113      */
    114     public abstract static class LineItem<VH extends RecyclerView.ViewHolder> {
    115         @Retention(SOURCE)
    116         @IntDef({TEXT_TYPE,
    117                 TOGGLE_TYPE,
    118                 ICON_TEXT_TYPE,
    119                 SEEKBAR_TYPE,
    120                 ICON_TOGGLE_TYPE,
    121                 CHECKBOX_TYPE,
    122                 EDIT_TEXT_TYPE,
    123                 SINGLE_TEXT_TYPE,
    124                 SPINNER_TYPE,
    125                 PASSWORD_TYPE,
    126                 ACTION_BUTTON_TYPE})
    127         public @interface LineItemType {}
    128 
    129         // with one title and one description
    130         static final int TEXT_TYPE = 1;
    131 
    132         // with one tile, one description, and a toggle on the right.
    133         static final int TOGGLE_TYPE = 2;
    134 
    135         // with one icon, one tile and one description.
    136         static final int ICON_TEXT_TYPE = 3;
    137 
    138         // with one tile and one seekbar.
    139         static final int SEEKBAR_TYPE = 4;
    140 
    141         // with one icon, title, description and a toggle.
    142         static final int ICON_TOGGLE_TYPE = 5;
    143 
    144         // with one icon, title and a checkbox.
    145         static final int CHECKBOX_TYPE = 6;
    146 
    147         // with one title and a EditText.
    148         static final int EDIT_TEXT_TYPE = 7;
    149 
    150         // with one title.
    151         static final int SINGLE_TEXT_TYPE = 8;
    152 
    153         // with a spinner.
    154         static final int SPINNER_TYPE = 9;
    155 
    156         // with a password input window and a checkbox for show password or not.
    157         static final int PASSWORD_TYPE = 10;
    158 
    159         // with one title, one description, a start icon, and an end action button with icon
    160         static final int ACTION_BUTTON_TYPE = 11;
    161         /**
    162          * Returns the LineItemType of this LineItem
    163          *
    164          * @return LineItem's type
    165          */
    166         @LineItemType
    167         abstract int getType();
    168 
    169         /**
    170          * Called when binding the LineItem to its ViewHolder, sets up onClick to be called
    171          * when the item is clicked.
    172          *
    173          * @param holder The holder for the LineItem
    174          */
    175         @CallSuper
    176         void bindViewHolder(VH holder) {
    177             holder.itemView.setOnClickListener(this::onClick);
    178         }
    179 
    180         /**
    181          * Returns the description of this LineItem
    182          */
    183         public abstract CharSequence getDesc();
    184 
    185         /**
    186          * Returns true if this item is ready to receive touch. If it's set to false,
    187          * this item maybe not clickable or temporarily not functional.
    188          */
    189         public boolean isEnabled() {
    190             return true;
    191         }
    192 
    193         /**
    194          * Returns true if some component on this item can be clicked.
    195          */
    196         public boolean isClickable() {
    197             return isExpandable();
    198         }
    199 
    200         /**
    201          * Returns true if this item can launch another activity or fragment.
    202          */
    203         public abstract boolean isExpandable();
    204 
    205         /**
    206          * Called when the LineItem is clicked, default behavior is nothing.
    207          *
    208          * @param view Passed in by the view's onClick listener
    209          */
    210         public void onClick(View view) {
    211             // do nothing
    212         }
    213     }
    214 
    215     @Override
    216     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    217         switch (viewType) {
    218             case LineItem.TEXT_TYPE:
    219                 return TextLineItem.createViewHolder(parent);
    220             case LineItem.TOGGLE_TYPE:
    221                 return ToggleLineItem.createViewHolder(parent);
    222             case LineItem.ICON_TEXT_TYPE:
    223                 return IconTextLineItem.createViewHolder(parent);
    224             case LineItem.SEEKBAR_TYPE:
    225                 return SeekbarLineItem.createViewHolder(parent);
    226             case LineItem.ICON_TOGGLE_TYPE:
    227                 return IconToggleLineItem.createViewHolder(parent);
    228             case LineItem.CHECKBOX_TYPE:
    229                 return CheckBoxLineItem.createViewHolder(parent);
    230             case LineItem.EDIT_TEXT_TYPE:
    231                 return EditTextLineItem.createViewHolder(parent);
    232             case LineItem.SINGLE_TEXT_TYPE:
    233                 return SingleTextLineItem.createViewHolder(parent);
    234             case LineItem.SPINNER_TYPE:
    235                 return SpinnerLineItem.createViewHolder(parent);
    236             case LineItem.PASSWORD_TYPE:
    237                 return PasswordLineItem.createViewHolder(parent);
    238             case LineItem.ACTION_BUTTON_TYPE:
    239                 return ActionIconButtonLineItem.createViewHolder(parent);
    240             default:
    241                 throw new IllegalStateException("ViewType not supported: " + viewType);
    242         }
    243     }
    244 
    245     @Override
    246     public void onBindViewHolder(ViewHolder holder, int position) {
    247         mContentList.get(position).bindViewHolder(holder);
    248     }
    249 
    250     @Override
    251     public int getItemViewType(int position) {
    252         return mContentList.get(position).getType();
    253     }
    254 
    255     @Override
    256     public int getItemCount() {
    257         return mContentList.size();
    258     }
    259 
    260     @Override
    261     public void setMaxItems(int maxItems) {
    262         // No limit in this list.
    263     }
    264 }
    265