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