Home | History | Annotate | Download | only in drawer
      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.contacts.drawer;
     18 
     19 import android.app.Activity;
     20 import android.graphics.PorterDuff;
     21 import android.support.annotation.LayoutRes;
     22 import android.view.LayoutInflater;
     23 import android.view.View;
     24 import android.view.ViewGroup;
     25 import android.widget.BaseAdapter;
     26 import android.widget.ImageView;
     27 import android.widget.TextView;
     28 
     29 import com.android.contacts.R;
     30 import com.android.contacts.activities.PeopleActivity.ContactsView;
     31 import com.android.contacts.group.GroupListItem;
     32 import com.android.contacts.list.ContactListFilter;
     33 import com.android.contacts.model.account.AccountDisplayInfo;
     34 import com.android.contacts.model.account.AccountDisplayInfoFactory;
     35 import com.android.contacts.util.SharedPreferenceUtil;
     36 import com.android.contactsbind.HelpUtils;
     37 import com.android.contactsbind.ObjectFactory;
     38 
     39 import java.util.ArrayList;
     40 import java.util.List;
     41 
     42 public class DrawerAdapter extends BaseAdapter {
     43 
     44     private static final int VIEW_TYPE_PRIMARY_ITEM = 0;
     45     private static final int VIEW_TYPE_MISC_ITEM = 1;
     46     private static final int VIEW_TYPE_HEADER_ITEM = 2;
     47     private static final int VIEW_TYPE_GROUP_ENTRY = 3;
     48     private static final int VIEW_TYPE_ACCOUNT_ENTRY = 4;
     49     private static final int VIEW_TYPE_CREATE_LABEL = 5;
     50     private static final int VIEW_TYPE_NAV_SPACER = 6;
     51     private static final int VIEW_TYPE_NAV_DIVIDER = 7;
     52 
     53     // This count must be updated if we add more view types.
     54     private static final int VIEW_TYPE_COUNT = 9;
     55 
     56     private static final int TYPEFACE_STYLE_ACTIVATE = R.style.DrawerItemTextActiveStyle;
     57     private static final int TYPEFACE_STYLE_INACTIVE = R.style.DrawerItemTextInactiveStyle;
     58 
     59     private final Activity mActivity;
     60     private final LayoutInflater mInflater;
     61     private ContactsView mSelectedView;
     62     private boolean mAreGroupWritableAccountsAvailable;
     63 
     64     // The group/account that was last clicked.
     65     private long mSelectedGroupId;
     66     private ContactListFilter mSelectedAccount;
     67 
     68     // Adapter elements, ordered in this way mItemsList. The ordering is based on:
     69     //  [Navigation spacer item]
     70     //  [Primary items] (Contacts, Suggestions)
     71     //  [Group Header]
     72     //  [Groups]
     73     //  [Create Label button]
     74     //  [Account Header]
     75     //  [Accounts]
     76     //  [Misc items] (a divider, Settings, Help & Feedback)
     77     //  [Navigation spacer item]
     78     private NavSpacerItem mNavSpacerItem = null;
     79     private List<PrimaryItem> mPrimaryItems = new ArrayList<>();
     80     private HeaderItem mGroupHeader = null;
     81     private List<GroupEntryItem> mGroupEntries = new ArrayList<>();
     82     private BaseDrawerItem mCreateLabelButton = null;
     83     private HeaderItem mAccountHeader = null;
     84     private List<AccountEntryItem> mAccountEntries = new ArrayList<>();
     85     private List<BaseDrawerItem> mMiscItems = new ArrayList<>();
     86 
     87     private List<BaseDrawerItem> mItemsList = new ArrayList<>();
     88     private AccountDisplayInfoFactory mAccountDisplayFactory;
     89 
     90     public DrawerAdapter(Activity activity) {
     91         super();
     92         mInflater = LayoutInflater.from(activity);
     93         mActivity = activity;
     94         initializeDrawerMenuItems();
     95     }
     96 
     97     private void initializeDrawerMenuItems() {
     98         // Spacer item for dividing sections in drawer
     99         mNavSpacerItem = new NavSpacerItem(R.id.nav_drawer_spacer);
    100         // Primary items
    101         mPrimaryItems.add(new PrimaryItem(R.id.nav_all_contacts, R.string.contactsList,
    102                 R.drawable.quantum_ic_account_circle_vd_theme_24, ContactsView.ALL_CONTACTS));
    103         if (ObjectFactory.getAssistantFragment() != null) {
    104             mPrimaryItems.add(new PrimaryItem(R.id.nav_assistant, R.string.menu_assistant,
    105                     R.drawable.quantum_ic_assistant_vd_theme_24, ContactsView.ASSISTANT));
    106         }
    107         // Group Header
    108         mGroupHeader = new HeaderItem(R.id.nav_groups, R.string.menu_title_groups);
    109         // Account Header
    110         mAccountHeader = new HeaderItem(R.id.nav_filters, R.string.menu_title_filters);
    111         // Create Label Button
    112         mCreateLabelButton = new BaseDrawerItem(VIEW_TYPE_CREATE_LABEL, R.id.nav_create_label,
    113                 R.string.menu_new_group_action_bar, R.drawable.quantum_ic_add_vd_theme_24);
    114         // Misc Items
    115         mMiscItems.add(new DividerItem());
    116         mMiscItems.add(new MiscItem(R.id.nav_settings, R.string.menu_settings,
    117                 R.drawable.quantum_ic_settings_vd_theme_24));
    118         if (HelpUtils.isHelpAndFeedbackAvailable()) {
    119             mMiscItems.add(new MiscItem(R.id.nav_help, R.string.menu_help,
    120                     R.drawable.quantum_ic_help_vd_theme_24));
    121         }
    122         rebuildItemsList();
    123     }
    124 
    125     private void rebuildItemsList() {
    126         mItemsList.clear();
    127         mItemsList.add(mNavSpacerItem);
    128         mItemsList.addAll(mPrimaryItems);
    129         if (mAreGroupWritableAccountsAvailable || !mGroupEntries.isEmpty()) {
    130             mItemsList.add(mGroupHeader);
    131         }
    132         mItemsList.addAll(mGroupEntries);
    133         if (mAreGroupWritableAccountsAvailable) {
    134             mItemsList.add(mCreateLabelButton);
    135         }
    136         if (mAccountEntries.size() > 0) {
    137             mItemsList.add(mAccountHeader);
    138         }
    139         mItemsList.addAll(mAccountEntries);
    140         mItemsList.addAll(mMiscItems);
    141         mItemsList.add(mNavSpacerItem);
    142     }
    143 
    144     public void setGroups(List<GroupListItem> groupListItems, boolean areGroupWritable) {
    145         final ArrayList<GroupEntryItem> groupEntries = new ArrayList<GroupEntryItem>();
    146         for (GroupListItem group : groupListItems) {
    147             groupEntries.add(new GroupEntryItem(R.id.nav_group, group));
    148         }
    149         mGroupEntries.clear();
    150         mGroupEntries.addAll(groupEntries);
    151         mAreGroupWritableAccountsAvailable = areGroupWritable;
    152         notifyChangeAndRebuildList();
    153     }
    154 
    155     public void setAccounts(List<ContactListFilter> accountFilterItems) {
    156         ArrayList<AccountEntryItem> accountItems = new ArrayList<AccountEntryItem>();
    157         for (ContactListFilter filter : accountFilterItems) {
    158             accountItems.add(new AccountEntryItem(R.id.nav_filter, filter));
    159         }
    160         mAccountDisplayFactory = AccountDisplayInfoFactory.fromListFilters(mActivity,
    161                 accountFilterItems);
    162         mAccountEntries.clear();
    163         mAccountEntries.addAll(accountItems);
    164         // TODO investigate performance of calling notifyDataSetChanged
    165         notifyChangeAndRebuildList();
    166     }
    167 
    168     @Override
    169     public int getCount() {
    170         return  mItemsList.size();
    171     }
    172 
    173     public BaseDrawerItem getItem(int position) {
    174         return mItemsList.get(position);
    175     }
    176 
    177     @Override
    178     public long getItemId(int position) {
    179         return getItem(position).id;
    180     }
    181 
    182     @Override
    183     public int getViewTypeCount() {
    184         return VIEW_TYPE_COUNT;
    185     }
    186 
    187     @Override
    188     public View getView(int position, View view, ViewGroup viewGroup) {
    189         final BaseDrawerItem drawerItem = getItem(position);
    190         switch (drawerItem.viewType) {
    191             case VIEW_TYPE_PRIMARY_ITEM:
    192                 return getPrimaryItemView((PrimaryItem) drawerItem, view, viewGroup);
    193             case VIEW_TYPE_HEADER_ITEM:
    194                 return getHeaderItemView((HeaderItem) drawerItem, view, viewGroup);
    195             case VIEW_TYPE_CREATE_LABEL:
    196                 return getDrawerItemView(drawerItem, view, viewGroup);
    197             case VIEW_TYPE_GROUP_ENTRY:
    198                 return getGroupEntryView((GroupEntryItem) drawerItem, view, viewGroup);
    199             case VIEW_TYPE_ACCOUNT_ENTRY:
    200                 return getAccountItemView((AccountEntryItem) drawerItem, view, viewGroup);
    201             case VIEW_TYPE_MISC_ITEM:
    202                 return getDrawerItemView(drawerItem, view, viewGroup);
    203             case VIEW_TYPE_NAV_SPACER:
    204                 return getBaseItemView(R.layout.nav_drawer_spacer, view, viewGroup);
    205             case VIEW_TYPE_NAV_DIVIDER:
    206                 return getBaseItemView(R.layout.drawer_horizontal_divider, view, viewGroup);
    207         }
    208         throw new IllegalStateException("Unknown drawer item " + drawerItem);
    209     }
    210 
    211     private View getBaseItemView(@LayoutRes int layoutResID, View result,ViewGroup parent) {
    212         if (result == null) {
    213             result = mInflater.inflate(layoutResID, parent, false);
    214         }
    215         return result;
    216     }
    217 
    218     private View getPrimaryItemView(PrimaryItem item, View result, ViewGroup parent) {
    219         if (result == null) {
    220             result = mInflater.inflate(R.layout.drawer_primary_item, parent, false);
    221         }
    222         final TextView titleView = (TextView) result.findViewById(R.id.title);
    223         titleView.setText(item.text);
    224         final ImageView iconView = (ImageView) result.findViewById(R.id.icon);
    225         iconView.setImageResource(item.icon);
    226         final TextView newBadge = (TextView) result.findViewById(R.id.assistant_new_badge);
    227         final boolean showWelcomeBadge = !SharedPreferenceUtil.isWelcomeCardDismissed(mActivity);
    228         newBadge.setVisibility(item.contactsView == ContactsView.ASSISTANT && showWelcomeBadge
    229                 ? View.VISIBLE : View.GONE);
    230         result.setActivated(item.contactsView == mSelectedView);
    231         updateSelectedStatus(titleView, iconView, item.contactsView == mSelectedView);
    232         result.setId(item.id);
    233         return result;
    234     }
    235 
    236     private View getHeaderItemView(HeaderItem item, View result, ViewGroup parent) {
    237         if (result == null) {
    238             result = mInflater.inflate(R.layout.drawer_header, parent, false);
    239         }
    240         final TextView textView = (TextView) result.findViewById(R.id.title);
    241         textView.setText(item.text);
    242         result.setId(item.id);
    243         return result;
    244     }
    245 
    246     private View getGroupEntryView(GroupEntryItem item, View result, ViewGroup parent) {
    247         if (result == null || !(result.getTag() instanceof GroupEntryItem)) {
    248             result = mInflater.inflate(R.layout.drawer_item, parent, false);
    249             result.setId(item.id);
    250         }
    251 
    252         final GroupListItem groupListItem = item.group;
    253         final TextView title = (TextView) result.findViewById(R.id.title);
    254         title.setText(groupListItem.getTitle());
    255         final ImageView icon = (ImageView) result.findViewById(R.id.icon);
    256         icon.setImageResource(R.drawable.quantum_ic_label_vd_theme_24);
    257         final boolean activated = groupListItem.getGroupId() == mSelectedGroupId &&
    258                 mSelectedView == ContactsView.GROUP_VIEW;
    259         updateSelectedStatus(title, icon, activated);
    260         result.setActivated(activated);
    261 
    262         result.setTag(groupListItem);
    263         result.setContentDescription(
    264                 mActivity.getString(R.string.navigation_drawer_label, groupListItem.getTitle()));
    265         return result;
    266     }
    267 
    268     private View getAccountItemView(AccountEntryItem item, View result, ViewGroup parent) {
    269         if (result == null || !(result.getTag() instanceof ContactListFilter)) {
    270             result = mInflater.inflate(R.layout.drawer_item, parent, false);
    271             result.setId(item.id);
    272         }
    273         final ContactListFilter account = item.account;
    274         final TextView textView = ((TextView) result.findViewById(R.id.title));
    275         textView.setText(account.accountName);
    276         final boolean activated = account.equals(mSelectedAccount)
    277                 && mSelectedView == ContactsView.ACCOUNT_VIEW;
    278         textView.setTextAppearance(mActivity, activated
    279                 ? TYPEFACE_STYLE_ACTIVATE : TYPEFACE_STYLE_INACTIVE);
    280 
    281         final ImageView icon = (ImageView) result.findViewById(R.id.icon);
    282         final AccountDisplayInfo displayableAccount =
    283                 mAccountDisplayFactory.getAccountDisplayInfoFor(item.account);
    284         icon.setScaleType(ImageView.ScaleType.FIT_CENTER);
    285         icon.setImageDrawable(displayableAccount.getIcon());
    286 
    287         result.setTag(account);
    288         result.setActivated(activated);
    289         result.setContentDescription(
    290                 displayableAccount.getTypeLabel() + " " + item.account.accountName);
    291         return result;
    292     }
    293 
    294     private View getDrawerItemView(BaseDrawerItem item, View result, ViewGroup parent) {
    295         if (result == null) {
    296             result = mInflater.inflate(R.layout.drawer_item, parent, false);
    297         }
    298 
    299         final TextView textView = (TextView) result.findViewById(R.id.title);
    300         textView.setText(item.text);
    301         final ImageView iconView = (ImageView) result.findViewById(R.id.icon);
    302         iconView.setImageResource(item.icon);
    303         result.setId(item.id);
    304         updateSelectedStatus(textView, iconView, false);
    305         return result;
    306     }
    307 
    308     @Override
    309     public int getItemViewType(int position) {
    310         return getItem(position).viewType;
    311     }
    312 
    313     private void updateSelectedStatus(TextView textView, ImageView imageView, boolean activated) {
    314         textView.setTextAppearance(mActivity, activated
    315                 ? TYPEFACE_STYLE_ACTIVATE : TYPEFACE_STYLE_INACTIVE);
    316         if (activated) {
    317             imageView.setColorFilter(mActivity.getResources().getColor(R.color.primary_color),
    318                     PorterDuff.Mode.SRC_ATOP);
    319         } else {
    320             imageView.clearColorFilter();
    321         }
    322     }
    323 
    324     private void notifyChangeAndRebuildList() {
    325         rebuildItemsList();
    326         notifyDataSetChanged();
    327     }
    328 
    329     public void setSelectedContactsView(ContactsView contactsView) {
    330         if (mSelectedView == contactsView) {
    331             return;
    332         }
    333         mSelectedView = contactsView;
    334         notifyChangeAndRebuildList();
    335     }
    336 
    337 
    338     public void setSelectedGroupId(long groupId) {
    339         if (mSelectedGroupId == groupId) {
    340             return;
    341         }
    342         mSelectedGroupId = groupId;
    343         notifyChangeAndRebuildList();
    344     }
    345 
    346     public long getSelectedGroupId() {
    347         return mSelectedGroupId;
    348     }
    349 
    350     public void setSelectedAccount(ContactListFilter filter) {
    351         if (mSelectedAccount == filter) {
    352             return;
    353         }
    354         mSelectedAccount = filter;
    355         notifyChangeAndRebuildList();
    356     }
    357 
    358     public ContactListFilter getSelectedAccount() {
    359         return mSelectedAccount;
    360     }
    361 
    362     public static class BaseDrawerItem {
    363         public final int viewType;
    364         public final int id;
    365         public final int text;
    366         public final int icon;
    367 
    368         public BaseDrawerItem(int adapterViewType, int viewId, int textResId, int iconResId) {
    369             viewType = adapterViewType;
    370             id = viewId;
    371             text = textResId;
    372             icon = iconResId;
    373         }
    374     }
    375 
    376     // Navigation drawer item for Contacts or Suggestions view which contains a name, an icon and
    377     // contacts view.
    378     public static class PrimaryItem extends BaseDrawerItem {
    379         public final ContactsView contactsView;
    380 
    381         public PrimaryItem(int id, int pageName, int iconId, ContactsView contactsView) {
    382             super(VIEW_TYPE_PRIMARY_ITEM, id, pageName, iconId);
    383             this.contactsView = contactsView;
    384         }
    385     }
    386 
    387     // Navigation drawer item for Settings, help and feedback, etc.
    388     public static class MiscItem extends BaseDrawerItem {
    389         public MiscItem(int id, int textId, int iconId) {
    390             super(VIEW_TYPE_MISC_ITEM, id, textId, iconId);
    391         }
    392     }
    393 
    394     // Header for a list of sub-items in the drawer.
    395     public static class HeaderItem extends BaseDrawerItem {
    396         public HeaderItem(int id, int textId) {
    397             super(VIEW_TYPE_HEADER_ITEM, id, textId, /* iconResId */ 0);
    398         }
    399     }
    400 
    401     // Navigation drawer item for spacer item for dividing sections in the drawer.
    402     public static class NavSpacerItem extends BaseDrawerItem {
    403         public NavSpacerItem(int id) {
    404             super(VIEW_TYPE_NAV_SPACER, id, /* textResId */ 0, /* iconResId */ 0);
    405         }
    406     }
    407 
    408     // Divider for drawing a line between sections in the drawer.
    409     public static class DividerItem extends BaseDrawerItem {
    410         public DividerItem() {
    411             super(VIEW_TYPE_NAV_DIVIDER, /* id */ 0, /* textResId */ 0, /* iconResId */ 0);
    412         }
    413     }
    414 
    415     // Navigation drawer item for a group.
    416     public static class GroupEntryItem extends BaseDrawerItem {
    417         private final GroupListItem group;
    418 
    419         public GroupEntryItem(int id, GroupListItem group) {
    420             super(VIEW_TYPE_GROUP_ENTRY, id, /* textResId */ 0, /* iconResId */ 0);
    421             this.group = group;
    422         }
    423     }
    424 
    425     // Navigation drawer item for an account.
    426     public static class AccountEntryItem extends BaseDrawerItem {
    427         private final ContactListFilter account;
    428 
    429         public AccountEntryItem(int id, ContactListFilter account) {
    430             super(VIEW_TYPE_ACCOUNT_ENTRY, id, /* textResId */ 0, /* iconResId */ 0);
    431             this.account = account;
    432         }
    433     }
    434 }
    435