Home | History | Annotate | Download | only in list
      1 /*
      2  * Copyright (C) 2011 Google Inc.
      3  * Licensed to The Android Open Source Project.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package com.android.contacts.list;
     18 
     19 import com.android.contacts.R;
     20 
     21 import android.content.Context;
     22 import android.content.res.Resources;
     23 import android.database.DataSetObserver;
     24 import android.view.View;
     25 import android.view.ViewGroup;
     26 import android.widget.BaseAdapter;
     27 import android.widget.FrameLayout;
     28 import android.widget.SectionIndexer;
     29 
     30 /**
     31  * An adapter that combines items from {@link ContactTileAdapter} and
     32  * {@link ContactEntryListAdapter} into a single list. In between those two results,
     33  * an account filter header will be inserted.
     34  */
     35 public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIndexer {
     36 
     37     private class CustomDataSetObserver extends DataSetObserver {
     38         @Override
     39         public void onChanged() {
     40             notifyDataSetChanged();
     41         }
     42     }
     43 
     44     private final ContactTileAdapter mContactTileAdapter;
     45     private final ContactEntryListAdapter mContactEntryListAdapter;
     46     private final View mAccountFilterHeaderContainer;
     47 
     48     private final int mItemPaddingLeft;
     49     private final int mItemPaddingRight;
     50 
     51     // Make frequent header consistent with account filter header.
     52     private final int mFrequentHeaderPaddingTop;
     53 
     54     private final DataSetObserver mObserver;
     55 
     56     public PhoneFavoriteMergedAdapter(Context context,
     57             ContactTileAdapter contactTileAdapter,
     58             View accountFilterHeaderContainer,
     59             ContactEntryListAdapter contactEntryListAdapter) {
     60         Resources resources = context.getResources();
     61         mItemPaddingLeft = resources.getDimensionPixelSize(R.dimen.detail_item_side_margin);
     62         mItemPaddingRight = resources.getDimensionPixelSize(R.dimen.list_visible_scrollbar_padding);
     63         mFrequentHeaderPaddingTop = resources.getDimensionPixelSize(
     64                 R.dimen.contact_browser_list_top_margin);
     65         mContactTileAdapter = contactTileAdapter;
     66         mContactEntryListAdapter = contactEntryListAdapter;
     67 
     68         mAccountFilterHeaderContainer = accountFilterHeaderContainer;
     69 
     70         mObserver = new CustomDataSetObserver();
     71         mContactTileAdapter.registerDataSetObserver(mObserver);
     72         mContactEntryListAdapter.registerDataSetObserver(mObserver);
     73     }
     74 
     75     @Override
     76     public int getCount() {
     77         final int contactTileAdapterCount = mContactTileAdapter.getCount();
     78         final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
     79         if (mContactEntryListAdapter.isLoading()) {
     80             // Hide "all" contacts during its being loaded.
     81             return contactTileAdapterCount + 1;
     82         } else {
     83             return contactTileAdapterCount + contactEntryListAdapterCount + 1;
     84         }
     85     }
     86 
     87     @Override
     88     public Object getItem(int position) {
     89         final int contactTileAdapterCount = mContactTileAdapter.getCount();
     90         final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
     91         if (position < contactTileAdapterCount) {
     92             return mContactTileAdapter.getItem(position);
     93         } else if (position == contactTileAdapterCount) {
     94             return mAccountFilterHeaderContainer;
     95         } else {
     96             final int localPosition = position - contactTileAdapterCount - 1;
     97             return mContactTileAdapter.getItem(localPosition);
     98         }
     99     }
    100 
    101     @Override
    102     public long getItemId(int position) {
    103         return position;
    104     }
    105 
    106     @Override
    107     public int getViewTypeCount() {
    108         return (mContactTileAdapter.getViewTypeCount()
    109                 + mContactEntryListAdapter.getViewTypeCount()
    110                 + 1);
    111     }
    112 
    113     @Override
    114     public int getItemViewType(int position) {
    115         final int contactTileAdapterCount = mContactTileAdapter.getCount();
    116         final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
    117         if (position < contactTileAdapterCount) {
    118             return mContactTileAdapter.getItemViewType(position);
    119         } else if (position == contactTileAdapterCount) {
    120             return mContactTileAdapter.getViewTypeCount()
    121                     + mContactEntryListAdapter.getViewTypeCount();
    122         } else {
    123             final int localPosition = position - contactTileAdapterCount - 1;
    124             final int type = mContactEntryListAdapter.getItemViewType(localPosition);
    125             // IGNORE_ITEM_VIEW_TYPE must be handled differently.
    126             return (type < 0) ? type : type + mContactTileAdapter.getViewTypeCount();
    127         }
    128     }
    129 
    130     @Override
    131     public View getView(int position, View convertView, ViewGroup parent) {
    132         final int contactTileAdapterCount = mContactTileAdapter.getCount();
    133         final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
    134 
    135         // Obtain a View relevant for that position, and adjust its horizontal padding. Each
    136         // View has different implementation, so we use different way to control those padding.
    137         if (position < contactTileAdapterCount) {
    138             final View view = mContactTileAdapter.getView(position, convertView, parent);
    139             final int frequentHeaderPosition = mContactTileAdapter.getFrequentHeaderPosition();
    140             if (position < frequentHeaderPosition) {  // "starred" contacts
    141                 // No padding adjustment.
    142             } else if (position == frequentHeaderPosition) {
    143                 view.setPadding(mItemPaddingLeft, mFrequentHeaderPaddingTop,
    144                         mItemPaddingRight, view.getPaddingBottom());
    145             } else {
    146                 // Views for "frequent" contacts use FrameLayout's margins instead of padding.
    147                 final FrameLayout frameLayout = (FrameLayout) view;
    148                 final View child = frameLayout.getChildAt(0);
    149                 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
    150                         FrameLayout.LayoutParams.WRAP_CONTENT,
    151                         FrameLayout.LayoutParams.WRAP_CONTENT);
    152                 params.setMargins(mItemPaddingLeft, 0, mItemPaddingRight, 0);
    153                 child.setLayoutParams(params);
    154             }
    155             return view;
    156         } else if (position == contactTileAdapterCount) {
    157             mAccountFilterHeaderContainer.setPadding(mItemPaddingLeft,
    158                     mAccountFilterHeaderContainer.getPaddingTop(),
    159                     mItemPaddingRight,
    160                     mAccountFilterHeaderContainer.getPaddingBottom());
    161             return mAccountFilterHeaderContainer;
    162         } else {
    163             final int localPosition = position - contactTileAdapterCount - 1;
    164             final ContactListItemView itemView = (ContactListItemView)
    165                     mContactEntryListAdapter.getView(localPosition, convertView, null);
    166             itemView.setPadding(mItemPaddingLeft, itemView.getPaddingTop(),
    167                     mItemPaddingRight, itemView.getPaddingBottom());
    168             itemView.setSelectionBoundsHorizontalMargin(mItemPaddingLeft, mItemPaddingRight);
    169             return itemView;
    170         }
    171     }
    172 
    173     @Override
    174     public boolean areAllItemsEnabled() {
    175         return (mContactTileAdapter.areAllItemsEnabled()
    176                 && mAccountFilterHeaderContainer.isEnabled()
    177                 && mContactEntryListAdapter.areAllItemsEnabled());
    178     }
    179 
    180     @Override
    181     public boolean isEnabled(int position) {
    182         final int contactTileAdapterCount = mContactTileAdapter.getCount();
    183         final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
    184         if (position < contactTileAdapterCount) {
    185             return mContactTileAdapter.isEnabled(position);
    186         } else if (position == contactTileAdapterCount) {
    187             // This will be handled by View's onClick event instead of ListView's onItemClick event.
    188             return false;
    189         } else {
    190             final int localPosition = position - contactTileAdapterCount - 1;
    191             return mContactEntryListAdapter.isEnabled(localPosition);
    192         }
    193     }
    194 
    195     @Override
    196     public int getPositionForSection(int sectionIndex) {
    197         final int contactTileAdapterCount = mContactTileAdapter.getCount();
    198         final int localPosition = mContactEntryListAdapter.getPositionForSection(sectionIndex);
    199         return contactTileAdapterCount + 1 + localPosition;
    200     }
    201 
    202     @Override
    203     public int getSectionForPosition(int position) {
    204         final int contactTileAdapterCount = mContactTileAdapter.getCount();
    205         if (position <= contactTileAdapterCount) {
    206             return 0;
    207         } else {
    208             final int localPosition = position - contactTileAdapterCount - 1;
    209             return mContactEntryListAdapter.getSectionForPosition(localPosition);
    210         }
    211     }
    212 
    213     @Override
    214     public Object[] getSections() {
    215         return mContactEntryListAdapter.getSections();
    216     }
    217 
    218     public boolean shouldShowFirstScroller(int firstVisibleItem) {
    219         final int contactTileAdapterCount = mContactTileAdapter.getCount();
    220         return firstVisibleItem > contactTileAdapterCount;
    221     }
    222 }