• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 package com.android.contacts.list;
17 
18 import com.android.contacts.ContactPhotoManager;
19 import com.android.contacts.ContactTileLoaderFactory;
20 import com.android.contacts.R;
21 import com.android.contacts.list.ContactTileAdapter.DisplayType;
22 import com.android.contacts.util.PhoneCapabilityTester;
23 
24 import android.app.Activity;
25 import android.app.Fragment;
26 import android.app.LoaderManager;
27 import android.app.LoaderManager.LoaderCallbacks;
28 import android.content.CursorLoader;
29 import android.content.Loader;
30 import android.content.res.Resources;
31 import android.database.Cursor;
32 import android.graphics.Rect;
33 import android.net.Uri;
34 import android.os.Bundle;
35 import android.util.Log;
36 import android.view.LayoutInflater;
37 import android.view.View;
38 import android.view.ViewGroup;
39 import android.widget.ListView;
40 import android.widget.TextView;
41 
42 /**
43  * Fragment containing a list of starred contacts followed by a list of frequently contacted.
44  *
45  * TODO: Make this an abstract class so that the favorites, frequent, and group list functionality
46  * can be separated out. This will make it easier to customize any of those lists if necessary
47  * (i.e. adding header views to the ListViews in the fragment). This work was started
48  * by creating {@link ContactTileFrequentFragment}.
49  */
50 public class ContactTileListFragment extends Fragment {
51     private static final String TAG = ContactTileListFragment.class.getSimpleName();
52 
53     public interface Listener {
onContactSelected(Uri contactUri, Rect targetRect)54         void onContactSelected(Uri contactUri, Rect targetRect);
onCallNumberDirectly(String phoneNumber)55         void onCallNumberDirectly(String phoneNumber);
56     }
57 
58     private Listener mListener;
59     private ContactTileAdapter mAdapter;
60     private DisplayType mDisplayType;
61     private TextView mEmptyView;
62     private ListView mListView;
63 
64     private boolean mOptionsMenuHasFrequents;
65 
66     @Override
onAttach(Activity activity)67     public void onAttach(Activity activity) {
68         super.onAttach(activity);
69 
70         Resources res = getResources();
71         int columnCount = res.getInteger(R.integer.contact_tile_column_count_in_favorites);
72 
73         mAdapter = new ContactTileAdapter(activity, mAdapterListener,
74                 columnCount, mDisplayType);
75         mAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity));
76     }
77 
78     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)79     public View onCreateView(LayoutInflater inflater, ViewGroup container,
80             Bundle savedInstanceState) {
81         return inflateAndSetupView(inflater, container, savedInstanceState,
82                 R.layout.contact_tile_list);
83     }
84 
inflateAndSetupView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState, int layoutResourceId)85     protected View inflateAndSetupView(LayoutInflater inflater, ViewGroup container,
86             Bundle savedInstanceState, int layoutResourceId) {
87         View listLayout = inflater.inflate(layoutResourceId, container, false);
88 
89         mEmptyView = (TextView) listLayout.findViewById(R.id.contact_tile_list_empty);
90         mListView = (ListView) listLayout.findViewById(R.id.contact_tile_list);
91 
92         mListView.setItemsCanFocus(true);
93         mListView.setAdapter(mAdapter);
94         return listLayout;
95     }
96 
97     @Override
onStart()98     public void onStart() {
99         super.onStart();
100 
101         // initialize the loader for this display type and destroy all others
102         final DisplayType[] loaderTypes = mDisplayType.values();
103         for (int i = 0; i < loaderTypes.length; i++) {
104             if (loaderTypes[i] == mDisplayType) {
105                 getLoaderManager().initLoader(mDisplayType.ordinal(), null,
106                         mContactTileLoaderListener);
107             } else {
108                 getLoaderManager().destroyLoader(loaderTypes[i].ordinal());
109             }
110         }
111     }
112 
113     /**
114      * Returns whether there are any frequents with the side effect of setting the
115      * internal flag mOptionsMenuHasFrequents to the value.  This should be called externally
116      * by the activity that is about to prepare the options menu with the clear frequents
117      * menu item.
118      */
hasFrequents()119     public boolean hasFrequents() {
120         mOptionsMenuHasFrequents = internalHasFrequents();
121         return mOptionsMenuHasFrequents;
122     }
123 
124     /**
125      * Returns whether there are any frequents.
126      */
internalHasFrequents()127     private boolean internalHasFrequents() {
128         return mAdapter.getNumFrequents() > 0;
129     }
130 
setColumnCount(int columnCount)131     public void setColumnCount(int columnCount) {
132         mAdapter.setColumnCount(columnCount);
133     }
134 
setDisplayType(DisplayType displayType)135     public void setDisplayType(DisplayType displayType) {
136         mDisplayType = displayType;
137         mAdapter.setDisplayType(mDisplayType);
138     }
139 
enableQuickContact(boolean enableQuickContact)140     public void enableQuickContact(boolean enableQuickContact) {
141         mAdapter.enableQuickContact(enableQuickContact);
142     }
143 
144     private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener =
145             new LoaderCallbacks<Cursor>() {
146 
147         @Override
148         public CursorLoader onCreateLoader(int id, Bundle args) {
149             switch (mDisplayType) {
150               case STARRED_ONLY:
151                   return ContactTileLoaderFactory.createStarredLoader(getActivity());
152               case STREQUENT:
153                   return ContactTileLoaderFactory.createStrequentLoader(getActivity());
154               case STREQUENT_PHONE_ONLY:
155                   return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity());
156               case FREQUENT_ONLY:
157                   return ContactTileLoaderFactory.createFrequentLoader(getActivity());
158               default:
159                   throw new IllegalStateException(
160                       "Unrecognized DisplayType " + mDisplayType);
161             }
162         }
163 
164         @Override
165         public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
166             mAdapter.setContactCursor(data);
167             mEmptyView.setText(getEmptyStateText());
168             mListView.setEmptyView(mEmptyView);
169 
170             // invalidate the menu options if needed
171             invalidateOptionsMenuIfNeeded();
172         }
173 
174         @Override
175         public void onLoaderReset(Loader<Cursor> loader) {}
176     };
177 
isOptionsMenuChanged()178     private boolean isOptionsMenuChanged() {
179         return mOptionsMenuHasFrequents != internalHasFrequents();
180     }
181 
invalidateOptionsMenuIfNeeded()182     private void invalidateOptionsMenuIfNeeded() {
183         if (isOptionsMenuChanged()) {
184             getActivity().invalidateOptionsMenu();
185         }
186     }
187 
getEmptyStateText()188     private String getEmptyStateText() {
189         String emptyText;
190         switch (mDisplayType) {
191             case STREQUENT:
192             case STREQUENT_PHONE_ONLY:
193             case STARRED_ONLY:
194                 emptyText = getString(R.string.listTotalAllContactsZeroStarred);
195                 break;
196             case FREQUENT_ONLY:
197             case GROUP_MEMBERS:
198                 emptyText = getString(R.string.noContacts);
199                 break;
200             default:
201                 throw new IllegalArgumentException("Unrecognized DisplayType " + mDisplayType);
202         }
203         return emptyText;
204     }
205 
setListener(Listener listener)206     public void setListener(Listener listener) {
207         mListener = listener;
208     }
209 
210     private ContactTileView.Listener mAdapterListener =
211             new ContactTileView.Listener() {
212         @Override
213         public void onContactSelected(Uri contactUri, Rect targetRect) {
214             if (mListener != null) {
215                 mListener.onContactSelected(contactUri, targetRect);
216             }
217         }
218 
219         @Override
220         public void onCallNumberDirectly(String phoneNumber) {
221             if (mListener != null) {
222                 mListener.onCallNumberDirectly(phoneNumber);
223             }
224         }
225 
226         @Override
227         public int getApproximateTileWidth() {
228             return getView().getWidth() / mAdapter.getColumnCount();
229         }
230     };
231 }
232