1eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton/* 2eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * Copyright (C) 2010 Google Inc. 3eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * 4eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 5eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * you may not use this file except in compliance with the License. 6eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * You may obtain a copy of the License at 7eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * 8eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 9eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * 10eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * Unless required by applicable law or agreed to in writing, software 11eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 12eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * See the License for the specific language governing permissions and 14eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * limitations under the License 15eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton */ 16eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 17eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonpackage com.android.loaderapp.fragments; 18eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 199b694a3b8f0339356c304ae078f63ae91df42226Jeff Hamiltonimport com.android.loaderapp.CursorFactoryListAdapter; 20eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport com.android.loaderapp.R; 219b694a3b8f0339356c304ae078f63ae91df42226Jeff Hamiltonimport com.android.loaderapp.CursorFactoryListAdapter.ResourceViewFactory; 22eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport com.android.loaderapp.model.ContactsListLoader; 23eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 249b694a3b8f0339356c304ae078f63ae91df42226Jeff Hamiltonimport android.app.LoaderManagingFragment; 259b694a3b8f0339356c304ae078f63ae91df42226Jeff Hamiltonimport android.content.Loader; 26eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.content.res.Configuration; 27eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.database.Cursor; 28eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.net.Uri; 29eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.os.Bundle; 30eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.provider.ContactsContract.Contacts; 31eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.view.LayoutInflater; 32eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.view.View; 33eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.view.ViewGroup; 34eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.widget.AdapterView; 35eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.widget.ListView; 36eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonimport android.widget.AdapterView.OnItemClickListener; 37eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 38eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamiltonpublic class ContactsListFragment extends LoaderManagingFragment<Cursor> 39eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton implements OnItemClickListener { 40eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton private static final int LOADER_LIST = 1; 41eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 42eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public static final int MODE_NULL = 0; 43eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public static final int MODE_VISIBLE = 1; 44eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public static final int MODE_STREQUENT = 2; 45eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public static final int MODE_GROUP = 3; 46eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 47eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton private static final int DEFAULT_MODE = MODE_VISIBLE; 48eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 49eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public interface Controller { 50eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public void onContactSelected(Uri contact); 51eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 52eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 53eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton Controller mController; 54eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton ListView mList; 55eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton CursorFactoryListAdapter mAdapter; 56eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton int mMode; 57eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton String mGroupName; 58eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 59eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public ContactsListFragment() { 60eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton super(); 61eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mMode = DEFAULT_MODE; 62eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 63eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 64eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public ContactsListFragment(int mode) { 65eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton super(); 66eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mMode = mode; 67eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 68eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 69eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton @Override 70eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public void onInitializeLoaders() { 71eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton if (mMode != MODE_NULL) { 72eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton startLoading(LOADER_LIST, null); 73eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 74eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 75eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 76eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton @Override 77eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton protected Loader onCreateLoader(int id, Bundle args) { 78eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton switch (mMode) { 79eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton case MODE_GROUP: 80eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return ContactsListLoader.newContactGroupLoader(getActivity(), mGroupName); 81eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton case MODE_STREQUENT: 82eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return ContactsListLoader.newStrequentContactsLoader(getActivity()); 83eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton default: 84eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return ContactsListLoader.newVisibleContactsLoader(getActivity()); 85eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 86eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 87eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 88eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton @Override 89eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 90eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mAdapter.changeCursor(data); 91eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 92eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 93eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton @Override 94b8f21e4c3acceba68a69088e1c4dc489321737f2Jeff Hamilton public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 95eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton ListView list = (ListView) inflater.inflate(R.layout.contacts_list, container, false); 96eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton list.setOnItemClickListener(this); 97eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mAdapter = new CursorFactoryListAdapter(getActivity(), 98eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton new ResourceViewFactory(getListItemResId())); 99eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton list.setAdapter(mAdapter); 100eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mList = list; 101eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return list; 102eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 103eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 104eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public void setMode(int mode) { 105eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton boolean reload = mode != mMode; 106eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mMode = mode; 107eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton if (reload) { 108eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton startLoading(LOADER_LIST, null); 109eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 110eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 111eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 112eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public void setGroupMode(String groupName) { 113eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton boolean reload = (MODE_GROUP != mMode) || !groupName.equals(mGroupName); 114eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mMode = MODE_GROUP; 115eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mGroupName = groupName; 116eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton if (reload) { 117eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton startLoading(LOADER_LIST, null); 118eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 119eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 1207a5e3bc28faed91ec17d1da9c82253a8679c1f4dJeff Hamilton 121eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public void setController(Controller controller) { 122eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mController = controller; 123eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 124eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 1257a5e3bc28faed91ec17d1da9c82253a8679c1f4dJeff Hamilton public int getMode() { 1267a5e3bc28faed91ec17d1da9c82253a8679c1f4dJeff Hamilton return mMode; 1277a5e3bc28faed91ec17d1da9c82253a8679c1f4dJeff Hamilton } 1287a5e3bc28faed91ec17d1da9c82253a8679c1f4dJeff Hamilton 129eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton /** 130eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * Build the {@link Contacts#CONTENT_LOOKUP_URI} for the given 131eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton * {@link ListView} position. 132eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton */ 133eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public Uri getContactUri(int position) { 134eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton if (position == ListView.INVALID_POSITION) { 135eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton throw new IllegalArgumentException("Position not in list bounds"); 136eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 137eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 138eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton final Cursor cursor = (Cursor) mAdapter.getItem(position); 139eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton if (cursor == null) { 140eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return null; 141eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 142eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 143eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton // Build and return soft, lookup reference 144eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton final long contactId = cursor.getLong(ContactsListLoader.COLUMN_ID); 145eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton final String lookupKey = cursor.getString(ContactsListLoader.COLUMN_LOOKUP_KEY); 146eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return Contacts.getLookupUri(contactId, lookupKey); 147eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 148eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 149eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 150eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton // The user clicked on an item in the left side pane, start loading the data for it 151eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton if (mController != null) { 152eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton mController.onContactSelected(getContactUri(position)); 153eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 154eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 155eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton 156eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton private int getListItemResId() { 157eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton // This should be done using the resource system, but for now we want to override 158eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton // the configuration for running xlarge UIs on normal screens and vice versa 159eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton Configuration config = getActivity().getResources().getConfiguration(); 160eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton int screenLayoutSize = config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; 161eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton if (screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_XLARGE) { 162eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return R.layout.xlarge_list_item; 163eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } else { 164eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton return R.layout.normal_list_item; 165eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 166eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton } 167eda61bd20eaf7b1f627bc44962709bf8f1b09628Jeff Hamilton} 168