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