• 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.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          */
onViewGroupAction(Uri groupUri)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 
GroupBrowseListFragment()97     public GroupBrowseListFragment() {
98     }
99 
100     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)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 
setVerticalScrollbarPosition(int position)153     public void setVerticalScrollbarPosition(int position) {
154         mVerticalScrollbarPosition = position;
155         if (mListView != null) {
156             configureVerticalScrollbar();
157         }
158     }
159 
configureVerticalScrollbar()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
onAttach(Activity activity)177     public void onAttach(Activity activity) {
178         super.onAttach(activity);
179         mContext = activity;
180     }
181 
182     @Override
onDetach()183     public void onDetach() {
184         super.onDetach();
185         mContext = null;
186     }
187 
188     @Override
onStart()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 
bindGroupList()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 
setListener(OnGroupBrowserActionListener listener)235     public void setListener(OnGroupBrowserActionListener listener) {
236         mListener = listener;
237     }
238 
setSelectionVisible(boolean flag)239     public void setSelectionVisible(boolean flag) {
240         mSelectionVisible = flag;
241         if (mAdapter != null) {
242             mAdapter.setSelectionVisible(mSelectionVisible);
243         }
244     }
245 
setSelectedGroup(Uri groupUri)246     private void setSelectedGroup(Uri groupUri) {
247         mSelectedGroupUri = groupUri;
248         mAdapter.setSelectedGroup(groupUri);
249         mListView.invalidateViews();
250     }
251 
viewGroup(Uri groupUri)252     private void viewGroup(Uri groupUri) {
253         setSelectedGroup(groupUri);
254         if (mListener != null) mListener.onViewGroupAction(groupUri);
255     }
256 
setSelectedUri(Uri groupUri)257     public void setSelectedUri(Uri groupUri) {
258         viewGroup(groupUri);
259         mSelectionToScreenRequested = true;
260     }
261 
requestSelectionToScreen()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 
hideSoftKeyboard()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
onFocusChange(View view, boolean hasFocus)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
onTouch(View view, MotionEvent event)297     public boolean onTouch(View view, MotionEvent event) {
298         if (view == mListView) {
299             hideSoftKeyboard();
300         }
301         return false;
302     }
303 
304     @Override
onSaveInstanceState(Bundle outState)305     public void onSaveInstanceState(Bundle outState) {
306         super.onSaveInstanceState(outState);
307         outState.putParcelable(EXTRA_KEY_GROUP_URI, mSelectedGroupUri);
308     }
309 
setAddAccountsVisibility(boolean visible)310     public void setAddAccountsVisibility(boolean visible) {
311         if (mAddAccountsView != null) {
312             mAddAccountsView.setVisibility(visible ? View.VISIBLE : View.GONE);
313         }
314     }
315 }
316