Home | History | Annotate | Download | only in list
      1 /*
      2  * Copyright (C) 2013 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.dialer.list;
     17 
     18 import android.app.Activity;
     19 import android.content.Intent;
     20 import android.content.res.Resources;
     21 import android.os.Bundle;
     22 import android.text.TextUtils;
     23 import android.view.View;
     24 import android.view.animation.Interpolator;
     25 import android.widget.AbsListView;
     26 import android.widget.AbsListView.OnScrollListener;
     27 import android.widget.ListView;
     28 
     29 import com.android.contacts.common.list.ContactEntryListAdapter;
     30 import com.android.contacts.common.list.ContactListItemView;
     31 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
     32 import com.android.contacts.common.list.PhoneNumberPickerFragment;
     33 import com.android.contacts.common.util.ViewUtil;
     34 import com.android.contacts.commonbind.analytics.AnalyticsUtil;
     35 import com.android.dialer.DialtactsActivity;
     36 import com.android.dialer.R;
     37 import com.android.dialer.util.DialerUtils;
     38 import com.android.phone.common.animation.AnimUtils;
     39 
     40 public class SearchFragment extends PhoneNumberPickerFragment {
     41 
     42     private OnListFragmentScrolledListener mActivityScrollListener;
     43 
     44     /*
     45      * Stores the untouched user-entered string that is used to populate the add to contacts
     46      * intent.
     47      */
     48     private String mAddToContactNumber;
     49     private int mActionBarHeight;
     50     private int mShadowHeight;
     51     private int mPaddingTop;
     52     private int mShowDialpadDuration;
     53     private int mHideDialpadDuration;
     54 
     55     private HostInterface mActivity;
     56 
     57     public interface HostInterface {
     58         public boolean isActionBarShowing();
     59         public boolean isDialpadShown();
     60         public int getActionBarHideOffset();
     61         public int getActionBarHeight();
     62     }
     63 
     64     @Override
     65     public void onAttach(Activity activity) {
     66         super.onAttach(activity);
     67 
     68         setQuickContactEnabled(true);
     69         setAdjustSelectionBoundsEnabled(false);
     70         setDarkTheme(false);
     71         setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(false /* opposite */));
     72         setUseCallableUri(true);
     73 
     74         try {
     75             mActivityScrollListener = (OnListFragmentScrolledListener) activity;
     76         } catch (ClassCastException e) {
     77             throw new ClassCastException(activity.toString()
     78                     + " must implement OnListFragmentScrolledListener");
     79         }
     80     }
     81 
     82     @Override
     83     public void onStart() {
     84         super.onStart();
     85         if (isSearchMode()) {
     86             getAdapter().setHasHeader(0, false);
     87         }
     88 
     89         mActivity = (HostInterface) getActivity();
     90 
     91         final Resources res = getResources();
     92         mActionBarHeight = mActivity.getActionBarHeight();
     93         mShadowHeight  = res.getDrawable(R.drawable.search_shadow).getIntrinsicHeight();
     94         mPaddingTop = res.getDimensionPixelSize(R.dimen.search_list_padding_top);
     95         mShowDialpadDuration = res.getInteger(R.integer.dialpad_slide_in_duration);
     96         mHideDialpadDuration = res.getInteger(R.integer.dialpad_slide_out_duration);
     97 
     98         final View parentView = getView();
     99 
    100         final ListView listView = getListView();
    101 
    102         listView.setBackgroundColor(res.getColor(R.color.background_dialer_results));
    103         listView.setClipToPadding(false);
    104         setVisibleScrollbarEnabled(false);
    105         listView.setOnScrollListener(new OnScrollListener() {
    106             @Override
    107             public void onScrollStateChanged(AbsListView view, int scrollState) {
    108                 mActivityScrollListener.onListFragmentScrollStateChange(scrollState);
    109             }
    110 
    111             @Override
    112             public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
    113                     int totalItemCount) {
    114             }
    115         });
    116 
    117         updatePosition(false /* animate */);
    118     }
    119 
    120     @Override
    121     public void onViewCreated(View view, Bundle savedInstanceState) {
    122         super.onViewCreated(view, savedInstanceState);
    123         ViewUtil.addBottomPaddingToListViewForFab(getListView(), getResources());
    124     }
    125 
    126     @Override
    127     protected void setSearchMode(boolean flag) {
    128         super.setSearchMode(flag);
    129         // This hides the "All contacts with phone numbers" header in the search fragment
    130         final ContactEntryListAdapter adapter = getAdapter();
    131         if (adapter != null) {
    132             adapter.setHasHeader(0, false);
    133         }
    134     }
    135 
    136     public void setAddToContactNumber(String addToContactNumber) {
    137         mAddToContactNumber = addToContactNumber;
    138     }
    139 
    140     @Override
    141     protected ContactEntryListAdapter createListAdapter() {
    142         DialerPhoneNumberListAdapter adapter = new DialerPhoneNumberListAdapter(getActivity());
    143         adapter.setDisplayPhotos(true);
    144         adapter.setUseCallableUri(super.usesCallableUri());
    145         return adapter;
    146     }
    147 
    148     @Override
    149     protected void onItemClick(int position, long id) {
    150         final DialerPhoneNumberListAdapter adapter = (DialerPhoneNumberListAdapter) getAdapter();
    151         final int shortcutType = adapter.getShortcutTypeFromPosition(position);
    152         final OnPhoneNumberPickerActionListener listener;
    153 
    154         switch (shortcutType) {
    155             case DialerPhoneNumberListAdapter.SHORTCUT_INVALID:
    156                 super.onItemClick(position, id);
    157                 break;
    158             case DialerPhoneNumberListAdapter.SHORTCUT_DIRECT_CALL:
    159                 listener = getOnPhoneNumberPickerListener();
    160                 if (listener != null) {
    161                     listener.onCallNumberDirectly(getQueryString());
    162                 }
    163                 break;
    164             case DialerPhoneNumberListAdapter.SHORTCUT_ADD_NUMBER_TO_CONTACTS:
    165                 final String number = TextUtils.isEmpty(mAddToContactNumber) ?
    166                         adapter.getFormattedQueryString() : mAddToContactNumber;
    167                 final Intent intent = DialtactsActivity.getAddNumberToContactIntent(number);
    168                 DialerUtils.startActivityWithErrorToast(getActivity(), intent,
    169                         R.string.add_contact_not_available);
    170                 break;
    171             case DialerPhoneNumberListAdapter.SHORTCUT_MAKE_VIDEO_CALL:
    172                 listener = getOnPhoneNumberPickerListener();
    173                 if (listener != null) {
    174                     listener.onCallNumberDirectly(getQueryString(), true /* isVideoCall */);
    175                 }
    176                 break;
    177         }
    178     }
    179 
    180     /**
    181      * Updates the position and padding of the search fragment, depending on whether the dialpad is
    182      * shown. This can be optionally animated.
    183      * @param animate
    184      */
    185     public void updatePosition(boolean animate) {
    186         // Use negative shadow height instead of 0 to account for the 9-patch's shadow.
    187         int startTranslationValue =
    188                 mActivity.isDialpadShown() ? mActionBarHeight - mShadowHeight: -mShadowHeight;
    189         int endTranslationValue = 0;
    190         // Prevents ListView from being translated down after a rotation when the ActionBar is up.
    191         if (animate || mActivity.isActionBarShowing()) {
    192             endTranslationValue =
    193                     mActivity.isDialpadShown() ? 0 : mActionBarHeight -mShadowHeight;
    194         }
    195         if (animate) {
    196             Interpolator interpolator =
    197                     mActivity.isDialpadShown() ? AnimUtils.EASE_IN : AnimUtils.EASE_OUT ;
    198             int duration =
    199                     mActivity.isDialpadShown() ? mShowDialpadDuration : mHideDialpadDuration;
    200             getView().setTranslationY(startTranslationValue);
    201             getView().animate()
    202                     .translationY(endTranslationValue)
    203                     .setInterpolator(interpolator)
    204                     .setDuration(duration);
    205         } else {
    206             getView().setTranslationY(endTranslationValue);
    207         }
    208 
    209         // There is padding which should only be applied when the dialpad is not shown.
    210         int paddingTop = mActivity.isDialpadShown() ? 0 : mPaddingTop;
    211         final ListView listView = getListView();
    212         listView.setPaddingRelative(
    213                 listView.getPaddingStart(),
    214                 paddingTop,
    215                 listView.getPaddingEnd(),
    216                 listView.getPaddingBottom());
    217     }
    218 }
    219