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