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