• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.content.CursorLoader;
19 import android.content.Intent;
20 import android.database.Cursor;
21 import android.provider.ContactsContract.Contacts;
22 import android.text.TextUtils;
23 import android.util.Log;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.View.OnClickListener;
27 import android.view.ViewGroup;
28 import android.view.accessibility.AccessibilityEvent;
29 import android.widget.Button;
30 import android.widget.FrameLayout;
31 import android.widget.ListView;
32 import android.widget.TextView;
33 
34 import com.android.contacts.R;
35 import com.android.contacts.common.list.ContactListAdapter;
36 import com.android.contacts.common.list.ContactListFilter;
37 import com.android.contacts.common.list.ContactListFilterController;
38 import com.android.contacts.common.list.DefaultContactListAdapter;
39 import com.android.contacts.common.list.ProfileAndContactsLoader;
40 import com.android.contacts.editor.ContactEditorFragment;
41 import com.android.contacts.common.util.AccountFilterUtil;
42 
43 /**
44  * Fragment containing a contact list used for browsing (as compared to
45  * picking a contact with one of the PICK intents).
46  */
47 public class DefaultContactBrowseListFragment extends ContactBrowseListFragment {
48     private static final String TAG = DefaultContactBrowseListFragment.class.getSimpleName();
49 
50     private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
51 
52     private TextView mCounterHeaderView;
53     private View mSearchHeaderView;
54     private View mAccountFilterHeader;
55     private FrameLayout mProfileHeaderContainer;
56     private View mProfileHeader;
57     private Button mProfileMessage;
58     private FrameLayout mMessageContainer;
59     private TextView mProfileTitle;
60     private View mSearchProgress;
61     private TextView mSearchProgressText;
62 
63     private class FilterHeaderClickListener implements OnClickListener {
64         @Override
onClick(View view)65         public void onClick(View view) {
66             AccountFilterUtil.startAccountFilterActivityForResult(
67                         DefaultContactBrowseListFragment.this,
68                         REQUEST_CODE_ACCOUNT_FILTER,
69                         getFilter());
70         }
71     }
72     private OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener();
73 
DefaultContactBrowseListFragment()74     public DefaultContactBrowseListFragment() {
75         setPhotoLoaderEnabled(true);
76         setSectionHeaderDisplayEnabled(true);
77         setVisibleScrollbarEnabled(true);
78     }
79 
80     @Override
createCursorLoader()81     public CursorLoader createCursorLoader() {
82         return new ProfileAndContactsLoader(getActivity());
83     }
84 
85     @Override
onItemClick(int position, long id)86     protected void onItemClick(int position, long id) {
87         viewContact(getAdapter().getContactUri(position));
88     }
89 
90     @Override
createListAdapter()91     protected ContactListAdapter createListAdapter() {
92         DefaultContactListAdapter adapter = new DefaultContactListAdapter(getContext());
93         adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
94         adapter.setDisplayPhotos(getResources().getBoolean(R.bool.config_browse_list_show_images));
95         return adapter;
96     }
97 
98     @Override
inflateView(LayoutInflater inflater, ViewGroup container)99     protected View inflateView(LayoutInflater inflater, ViewGroup container) {
100         return inflater.inflate(R.layout.contact_list_content, null);
101     }
102 
103     @Override
onCreateView(LayoutInflater inflater, ViewGroup container)104     protected void onCreateView(LayoutInflater inflater, ViewGroup container) {
105         super.onCreateView(inflater, container);
106 
107         mAccountFilterHeader = getView().findViewById(R.id.account_filter_header_container);
108         mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
109         mCounterHeaderView = (TextView) getView().findViewById(R.id.contacts_count);
110 
111         // Create an empty user profile header and hide it for now (it will be visible if the
112         // contacts list will have no user profile).
113         addEmptyUserProfileHeader(inflater);
114         showEmptyUserProfile(false);
115 
116         // Putting the header view inside a container will allow us to make
117         // it invisible later. See checkHeaderViewVisibility()
118         FrameLayout headerContainer = new FrameLayout(inflater.getContext());
119         mSearchHeaderView = inflater.inflate(R.layout.search_header, null, false);
120         headerContainer.addView(mSearchHeaderView);
121         getListView().addHeaderView(headerContainer, null, false);
122         checkHeaderViewVisibility();
123 
124         mSearchProgress = getView().findViewById(R.id.search_progress);
125         mSearchProgressText = (TextView) mSearchHeaderView.findViewById(R.id.totalContactsText);
126     }
127 
128     @Override
setSearchMode(boolean flag)129     protected void setSearchMode(boolean flag) {
130         super.setSearchMode(flag);
131         checkHeaderViewVisibility();
132         if (!flag) showSearchProgress(false);
133     }
134 
135     /** Show or hide the directory-search progress spinner. */
showSearchProgress(boolean show)136     private void showSearchProgress(boolean show) {
137         mSearchProgress.setVisibility(show ? View.VISIBLE : View.GONE);
138     }
139 
checkHeaderViewVisibility()140     private void checkHeaderViewVisibility() {
141         if (mCounterHeaderView != null) {
142             mCounterHeaderView.setVisibility(isSearchMode() ? View.GONE : View.VISIBLE);
143         }
144         updateFilterHeaderView();
145 
146         // Hide the search header by default. See showCount().
147         if (mSearchHeaderView != null) {
148             mSearchHeaderView.setVisibility(View.GONE);
149         }
150     }
151 
152     @Override
setFilter(ContactListFilter filter)153     public void setFilter(ContactListFilter filter) {
154         super.setFilter(filter);
155         updateFilterHeaderView();
156     }
157 
updateFilterHeaderView()158     private void updateFilterHeaderView() {
159         if (mAccountFilterHeader == null) {
160             return; // Before onCreateView -- just ignore it.
161         }
162         final ContactListFilter filter = getFilter();
163         if (filter != null && !isSearchMode()) {
164             final boolean shouldShowHeader = AccountFilterUtil.updateAccountFilterTitleForPeople(
165                     mAccountFilterHeader, filter, false);
166             mAccountFilterHeader.setVisibility(shouldShowHeader ? View.VISIBLE : View.GONE);
167         } else {
168             mAccountFilterHeader.setVisibility(View.GONE);
169         }
170     }
171 
172     @Override
showCount(int partitionIndex, Cursor data)173     protected void showCount(int partitionIndex, Cursor data) {
174         if (!isSearchMode() && data != null) {
175             int count = data.getCount();
176             if (count != 0) {
177                 count -= (mUserProfileExists ? 1: 0);
178                 String format = getResources().getQuantityText(
179                         R.plurals.listTotalAllContacts, count).toString();
180                 // Do not count the user profile in the contacts count
181                 if (mUserProfileExists) {
182                     getAdapter().setContactsCount(String.format(format, count));
183                 } else {
184                     mCounterHeaderView.setText(String.format(format, count));
185                 }
186             } else {
187                 ContactListFilter filter = getFilter();
188                 int filterType = filter != null ? filter.filterType
189                         : ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS;
190                 switch (filterType) {
191                     case ContactListFilter.FILTER_TYPE_ACCOUNT:
192                         mCounterHeaderView.setText(getString(
193                                 R.string.listTotalAllContactsZeroGroup, filter.accountName));
194                         break;
195                     case ContactListFilter.FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY:
196                         mCounterHeaderView.setText(R.string.listTotalPhoneContactsZero);
197                         break;
198                     case ContactListFilter.FILTER_TYPE_STARRED:
199                         mCounterHeaderView.setText(R.string.listTotalAllContactsZeroStarred);
200                         break;
201                     case ContactListFilter.FILTER_TYPE_CUSTOM:
202                         mCounterHeaderView.setText(R.string.listTotalAllContactsZeroCustom);
203                         break;
204                     default:
205                         mCounterHeaderView.setText(R.string.listTotalAllContactsZero);
206                         break;
207                 }
208             }
209         } else {
210             ContactListAdapter adapter = getAdapter();
211             if (adapter == null) {
212                 return;
213             }
214 
215             // In search mode we only display the header if there is nothing found
216             if (TextUtils.isEmpty(getQueryString()) || !adapter.areAllPartitionsEmpty()) {
217                 mSearchHeaderView.setVisibility(View.GONE);
218                 showSearchProgress(false);
219             } else {
220                 mSearchHeaderView.setVisibility(View.VISIBLE);
221                 if (adapter.isLoading()) {
222                     mSearchProgressText.setText(R.string.search_results_searching);
223                     showSearchProgress(true);
224                 } else {
225                     mSearchProgressText.setText(R.string.listFoundAllContactsZero);
226                     mSearchProgressText.sendAccessibilityEvent(
227                             AccessibilityEvent.TYPE_VIEW_SELECTED);
228                     showSearchProgress(false);
229                 }
230             }
231             showEmptyUserProfile(false);
232         }
233     }
234 
235     @Override
setProfileHeader()236     protected void setProfileHeader() {
237         mUserProfileExists = getAdapter().hasProfile();
238         showEmptyUserProfile(!mUserProfileExists && !isSearchMode());
239     }
240 
241     @Override
onActivityResult(int requestCode, int resultCode, Intent data)242     public void onActivityResult(int requestCode, int resultCode, Intent data) {
243         if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) {
244             if (getActivity() != null) {
245                 AccountFilterUtil.handleAccountFilterResult(
246                         ContactListFilterController.getInstance(getActivity()), resultCode, data);
247             } else {
248                 Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()");
249             }
250         }
251     }
252 
showEmptyUserProfile(boolean show)253     private void showEmptyUserProfile(boolean show) {
254         // Changing visibility of just the mProfileHeader doesn't do anything unless
255         // you change visibility of its children, hence the call to mCounterHeaderView
256         // and mProfileTitle
257         mProfileHeaderContainer.setVisibility(show ? View.VISIBLE : View.GONE);
258         mProfileHeader.setVisibility(show ? View.VISIBLE : View.GONE);
259         mCounterHeaderView.setVisibility(show ? View.VISIBLE : View.GONE);
260         mProfileTitle.setVisibility(show ? View.VISIBLE : View.GONE);
261         mMessageContainer.setVisibility(show ? View.VISIBLE : View.GONE);
262         mProfileMessage.setVisibility(show ? View.VISIBLE : View.GONE);
263     }
264 
265     /**
266      * This method creates a pseudo user profile contact. When the returned query doesn't have
267      * a profile, this methods creates 2 views that are inserted as headers to the listview:
268      * 1. A header view with the "ME" title and the contacts count.
269      * 2. A button that prompts the user to create a local profile
270      */
addEmptyUserProfileHeader(LayoutInflater inflater)271     private void addEmptyUserProfileHeader(LayoutInflater inflater) {
272 
273         ListView list = getListView();
274         // Put a header with the "ME" name and a view for the number of contacts
275         // The view is embedded in a frame view since you cannot change the visibility of a
276         // view in a ListView without having a parent view.
277         mProfileHeaderContainer = new FrameLayout(inflater.getContext());
278         mProfileHeader = inflater.inflate(R.layout.user_profile_header, null, false);
279         mCounterHeaderView = (TextView) mProfileHeader.findViewById(R.id.contacts_count);
280         mProfileTitle = (TextView) mProfileHeader.findViewById(R.id.profile_title);
281         mProfileTitle.setAllCaps(true);
282         mProfileHeaderContainer.addView(mProfileHeader);
283         list.addHeaderView(mProfileHeaderContainer, null, false);
284 
285         // Add a selectable view with a message inviting the user to create a local profile
286         mMessageContainer = new FrameLayout(inflater.getContext());
287         mProfileMessage = (Button)inflater.inflate(R.layout.user_profile_button, null, false);
288         mMessageContainer.addView(mProfileMessage);
289         list.addHeaderView(mMessageContainer, null, true);
290 
291         mProfileMessage.setOnClickListener(new View.OnClickListener() {
292             public void onClick(View v) {
293                 Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
294                 intent.putExtra(ContactEditorFragment.INTENT_EXTRA_NEW_LOCAL_PROFILE, true);
295                 startActivity(intent);
296             }
297         });
298     }
299 }
300