Home | History | Annotate | Download | only in group
      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 
     17 package com.android.contacts.group;
     18 
     19 import android.app.Activity;
     20 import android.app.Fragment;
     21 import android.app.LoaderManager;
     22 import android.app.LoaderManager.LoaderCallbacks;
     23 import android.content.Context;
     24 import android.content.CursorLoader;
     25 import android.content.Intent;
     26 import android.content.Loader;
     27 import android.database.Cursor;
     28 import android.net.Uri;
     29 import android.os.Bundle;
     30 import android.provider.ContactsContract;
     31 import android.provider.Settings;
     32 import android.view.LayoutInflater;
     33 import android.view.MotionEvent;
     34 import android.view.View;
     35 import android.view.View.OnClickListener;
     36 import android.view.View.OnFocusChangeListener;
     37 import android.view.View.OnTouchListener;
     38 import android.view.ViewGroup;
     39 import android.view.inputmethod.InputMethodManager;
     40 import android.widget.AdapterView;
     41 import android.widget.AdapterView.OnItemClickListener;
     42 import android.widget.ListView;
     43 import android.widget.TextView;
     44 
     45 import com.android.contacts.GroupListLoader;
     46 import com.android.contacts.R;
     47 import com.android.contacts.common.util.ImplicitIntentsUtil;
     48 import com.android.contacts.group.GroupBrowseListAdapter.GroupListItemViewCache;
     49 import com.android.contacts.common.ContactsUtils;
     50 import com.android.contacts.common.list.AutoScrollListView;
     51 
     52 /**
     53  * Fragment to display the list of groups.
     54  */
     55 public class GroupBrowseListFragment extends Fragment
     56         implements OnFocusChangeListener, OnTouchListener {
     57 
     58     /**
     59      * Action callbacks that can be sent by a group list.
     60      */
     61     public interface OnGroupBrowserActionListener  {
     62 
     63         /**
     64          * Opens the specified group for viewing.
     65          *
     66          * @param groupUri for the group that the user wishes to view.
     67          */
     68         void onViewGroupAction(Uri groupUri);
     69 
     70     }
     71 
     72     private static final String TAG = "GroupBrowseListFragment";
     73 
     74     private static final int LOADER_GROUPS = 1;
     75 
     76     private Context mContext;
     77     private Cursor mGroupListCursor;
     78 
     79     private boolean mSelectionToScreenRequested;
     80 
     81     private static final String EXTRA_KEY_GROUP_URI = "groups.groupUri";
     82 
     83     private View mRootView;
     84     private AutoScrollListView mListView;
     85     private TextView mEmptyView;
     86     private View mAddAccountsView;
     87     private View mAddAccountButton;
     88 
     89     private GroupBrowseListAdapter mAdapter;
     90     private boolean mSelectionVisible;
     91     private Uri mSelectedGroupUri;
     92 
     93     private int mVerticalScrollbarPosition = View.SCROLLBAR_POSITION_RIGHT;
     94 
     95     private OnGroupBrowserActionListener mListener;
     96 
     97     public GroupBrowseListFragment() {
     98     }
     99 
    100     @Override
    101     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    102             Bundle savedInstanceState) {
    103         if (savedInstanceState != null) {
    104             mSelectedGroupUri = savedInstanceState.getParcelable(EXTRA_KEY_GROUP_URI);
    105             if (mSelectedGroupUri != null) {
    106                 // The selection may be out of screen, if rotated from portrait to landscape,
    107                 // so ensure it's visible.
    108                 mSelectionToScreenRequested = true;
    109             }
    110         }
    111 
    112         mRootView = inflater.inflate(R.layout.group_browse_list_fragment, null);
    113         mEmptyView = (TextView)mRootView.findViewById(R.id.empty);
    114 
    115         mAdapter = new GroupBrowseListAdapter(mContext);
    116         mAdapter.setSelectionVisible(mSelectionVisible);
    117         mAdapter.setSelectedGroup(mSelectedGroupUri);
    118 
    119         mListView = (AutoScrollListView) mRootView.findViewById(R.id.list);
    120         mListView.setOnFocusChangeListener(this);
    121         mListView.setOnTouchListener(this);
    122         mListView.setAdapter(mAdapter);
    123         mListView.setOnItemClickListener(new OnItemClickListener() {
    124             @Override
    125             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    126                 GroupListItemViewCache groupListItem = (GroupListItemViewCache) view.getTag();
    127                 if (groupListItem != null) {
    128                     viewGroup(groupListItem.getUri());
    129                 }
    130             }
    131         });
    132 
    133         mListView.setEmptyView(mEmptyView);
    134         configureVerticalScrollbar();
    135 
    136         mAddAccountsView = mRootView.findViewById(R.id.add_accounts);
    137         mAddAccountButton = mRootView.findViewById(R.id.add_account_button);
    138         mAddAccountButton.setOnClickListener(new OnClickListener() {
    139             @Override
    140             public void onClick(View v) {
    141                 Intent intent = new Intent(Settings.ACTION_ADD_ACCOUNT);
    142                 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    143                 intent.putExtra(Settings.EXTRA_AUTHORITIES,
    144                         new String[] { ContactsContract.AUTHORITY });
    145                 ImplicitIntentsUtil.startActivityOutsideApp(getActivity(), intent);
    146             }
    147         });
    148         setAddAccountsVisibility(!ContactsUtils.areGroupWritableAccountsAvailable(mContext));
    149 
    150         return mRootView;
    151     }
    152 
    153     public void setVerticalScrollbarPosition(int position) {
    154         mVerticalScrollbarPosition = position;
    155         if (mListView != null) {
    156             configureVerticalScrollbar();
    157         }
    158     }
    159 
    160     private void configureVerticalScrollbar() {
    161         mListView.setVerticalScrollbarPosition(mVerticalScrollbarPosition);
    162         mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
    163         int leftPadding = 0;
    164         int rightPadding = 0;
    165         if (mVerticalScrollbarPosition == View.SCROLLBAR_POSITION_LEFT) {
    166             leftPadding = mContext.getResources().getDimensionPixelOffset(
    167                     R.dimen.list_visible_scrollbar_padding);
    168         } else {
    169             rightPadding = mContext.getResources().getDimensionPixelOffset(
    170                     R.dimen.list_visible_scrollbar_padding);
    171         }
    172         mListView.setPadding(leftPadding, mListView.getPaddingTop(),
    173                 rightPadding, mListView.getPaddingBottom());
    174     }
    175 
    176     @Override
    177     public void onAttach(Activity activity) {
    178         super.onAttach(activity);
    179         mContext = activity;
    180     }
    181 
    182     @Override
    183     public void onDetach() {
    184         super.onDetach();
    185         mContext = null;
    186     }
    187 
    188     @Override
    189     public void onStart() {
    190         getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener);
    191         super.onStart();
    192     }
    193 
    194     /**
    195      * The listener for the group meta data loader for all groups.
    196      */
    197     private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener =
    198             new LoaderCallbacks<Cursor>() {
    199 
    200         @Override
    201         public CursorLoader onCreateLoader(int id, Bundle args) {
    202             mEmptyView.setText(null);
    203             return new GroupListLoader(mContext);
    204         }
    205 
    206         @Override
    207         public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    208             mGroupListCursor = data;
    209             bindGroupList();
    210         }
    211 
    212         public void onLoaderReset(Loader<Cursor> loader) {
    213         }
    214     };
    215 
    216     private void bindGroupList() {
    217         mEmptyView.setText(R.string.noGroups);
    218         setAddAccountsVisibility(!ContactsUtils.areGroupWritableAccountsAvailable(mContext));
    219         if (mGroupListCursor == null) {
    220             return;
    221         }
    222         mAdapter.setCursor(mGroupListCursor);
    223 
    224         if (mSelectionToScreenRequested) {
    225             mSelectionToScreenRequested = false;
    226             requestSelectionToScreen();
    227         }
    228 
    229         mSelectedGroupUri = mAdapter.getSelectedGroup();
    230         if (mSelectionVisible && mSelectedGroupUri != null) {
    231             viewGroup(mSelectedGroupUri);
    232         }
    233     }
    234 
    235     public void setListener(OnGroupBrowserActionListener listener) {
    236         mListener = listener;
    237     }
    238 
    239     public void setSelectionVisible(boolean flag) {
    240         mSelectionVisible = flag;
    241         if (mAdapter != null) {
    242             mAdapter.setSelectionVisible(mSelectionVisible);
    243         }
    244     }
    245 
    246     private void setSelectedGroup(Uri groupUri) {
    247         mSelectedGroupUri = groupUri;
    248         mAdapter.setSelectedGroup(groupUri);
    249         mListView.invalidateViews();
    250     }
    251 
    252     private void viewGroup(Uri groupUri) {
    253         setSelectedGroup(groupUri);
    254         if (mListener != null) mListener.onViewGroupAction(groupUri);
    255     }
    256 
    257     public void setSelectedUri(Uri groupUri) {
    258         viewGroup(groupUri);
    259         mSelectionToScreenRequested = true;
    260     }
    261 
    262     protected void requestSelectionToScreen() {
    263         if (!mSelectionVisible) {
    264             return; // If selection isn't visible we don't care.
    265         }
    266         int selectedPosition = mAdapter.getSelectedGroupPosition();
    267         if (selectedPosition != -1) {
    268             mListView.requestPositionToScreen(selectedPosition,
    269                     true /* smooth scroll requested */);
    270         }
    271     }
    272 
    273     private void hideSoftKeyboard() {
    274         if (mContext == null) {
    275             return;
    276         }
    277         // Hide soft keyboard, if visible
    278         InputMethodManager inputMethodManager = (InputMethodManager)
    279                 mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
    280         inputMethodManager.hideSoftInputFromWindow(mListView.getWindowToken(), 0);
    281     }
    282 
    283     /**
    284      * Dismisses the soft keyboard when the list takes focus.
    285      */
    286     @Override
    287     public void onFocusChange(View view, boolean hasFocus) {
    288         if (view == mListView && hasFocus) {
    289             hideSoftKeyboard();
    290         }
    291     }
    292 
    293     /**
    294      * Dismisses the soft keyboard when the list is touched.
    295      */
    296     @Override
    297     public boolean onTouch(View view, MotionEvent event) {
    298         if (view == mListView) {
    299             hideSoftKeyboard();
    300         }
    301         return false;
    302     }
    303 
    304     @Override
    305     public void onSaveInstanceState(Bundle outState) {
    306         super.onSaveInstanceState(outState);
    307         outState.putParcelable(EXTRA_KEY_GROUP_URI, mSelectedGroupUri);
    308     }
    309 
    310     public void setAddAccountsVisibility(boolean visible) {
    311         if (mAddAccountsView != null) {
    312             mAddAccountsView.setVisibility(visible ? View.VISIBLE : View.GONE);
    313         }
    314     }
    315 }
    316