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