PhoneFavoriteMergedAdapter.java revision 2eb1be625832f77ba9c6a3e9dc13b2ecf3f25214
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 */
17package com.android.contacts.list;
18
19import com.android.contacts.R;
20
21import android.content.Context;
22import android.content.res.Resources;
23import android.database.DataSetObserver;
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.BaseAdapter;
27import android.widget.FrameLayout;
28import 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 */
35public 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            return mAccountFilterHeaderContainer.isEnabled();
188        } else {
189            final int localPosition = position - contactTileAdapterCount + 1;
190            return mContactEntryListAdapter.isEnabled(localPosition);
191        }
192    }
193
194    @Override
195    public int getPositionForSection(int sectionIndex) {
196        final int contactTileAdapterCount = mContactTileAdapter.getCount();
197        final int localPosition = mContactEntryListAdapter.getPositionForSection(sectionIndex);
198        return contactTileAdapterCount + 1 + localPosition;
199    }
200
201    @Override
202    public int getSectionForPosition(int position) {
203        final int contactTileAdapterCount = mContactTileAdapter.getCount();
204        if (position <= contactTileAdapterCount) {
205            return 0;
206        } else {
207            final int localPosition = position - contactTileAdapterCount - 1;
208            return mContactEntryListAdapter.getSectionForPosition(localPosition);
209        }
210    }
211
212    @Override
213    public Object[] getSections() {
214        return mContactEntryListAdapter.getSections();
215    }
216
217    public boolean shouldShowFirstScroller(int firstVisibleItem) {
218        final int contactTileAdapterCount = mContactTileAdapter.getCount();
219        return firstVisibleItem > contactTileAdapterCount;
220    }
221}