blob: 189cfd375d02171971ed791b973e74c82094390e [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.contacts.list;
import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.android.contacts.R;
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactTileLoaderFactory;
import com.android.contacts.common.list.ContactTileAdapter;
import com.android.contacts.common.list.ContactTileAdapter.DisplayType;
import com.android.contacts.common.list.ContactTileView;
import com.android.contacts.common.util.ContactListViewUtils;
import com.android.contacts.common.util.SchedulingUtils;
/**
* Fragment containing a list of starred contacts followed by a list of frequently contacted.
*
* TODO: Make this an abstract class so that the favorites, frequent, and group list functionality
* can be separated out. This will make it easier to customize any of those lists if necessary
* (i.e. adding header views to the ListViews in the fragment). This work was started
* by creating {@link ContactTileFrequentFragment}.
*/
public class ContactTileListFragment extends Fragment {
private static final String TAG = ContactTileListFragment.class.getSimpleName();
public interface Listener {
void onContactSelected(Uri contactUri, Rect targetRect);
void onCallNumberDirectly(String phoneNumber);
}
private Listener mListener;
private ContactTileAdapter mAdapter;
private DisplayType mDisplayType;
private TextView mEmptyView;
private ListView mListView;
private boolean mOptionsMenuHasFrequents;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Resources res = getResources();
int columnCount = res.getInteger(R.integer.contact_tile_column_count_in_favorites);
mAdapter = new ContactTileAdapter(activity, mAdapterListener,
columnCount, mDisplayType);
mAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflateAndSetupView(inflater, container, savedInstanceState,
R.layout.contact_tile_list);
}
protected View inflateAndSetupView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState, int layoutResourceId) {
View listLayout = inflater.inflate(layoutResourceId, container, false);
mEmptyView = (TextView) listLayout.findViewById(R.id.contact_tile_list_empty);
mListView = (ListView) listLayout.findViewById(R.id.contact_tile_list);
mListView.setItemsCanFocus(true);
mListView.setAdapter(mAdapter);
ContactListViewUtils.applyCardPaddingToView(getResources(), mListView, listLayout);
return listLayout;
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (getActivity() != null && getView() != null && !hidden) {
// If the padding was last applied when in a hidden state, it may have been applied
// incorrectly. Therefore we need to reapply it.
ContactListViewUtils.applyCardPaddingToView(getResources(), mListView, getView());
}
}
@Override
public void onStart() {
super.onStart();
// initialize the loader for this display type and destroy all others
final DisplayType[] loaderTypes = mDisplayType.values();
for (int i = 0; i < loaderTypes.length; i++) {
if (loaderTypes[i] == mDisplayType) {
getLoaderManager().initLoader(mDisplayType.ordinal(), null,
mContactTileLoaderListener);
} else {
getLoaderManager().destroyLoader(loaderTypes[i].ordinal());
}
}
}
/**
* Returns whether there are any frequents with the side effect of setting the
* internal flag mOptionsMenuHasFrequents to the value. This should be called externally
* by the activity that is about to prepare the options menu with the clear frequents
* menu item.
*/
public boolean hasFrequents() {
mOptionsMenuHasFrequents = internalHasFrequents();
return mOptionsMenuHasFrequents;
}
/**
* Returns whether there are any frequents.
*/
private boolean internalHasFrequents() {
return mAdapter.getNumFrequents() > 0;
}
public void setColumnCount(int columnCount) {
mAdapter.setColumnCount(columnCount);
}
public void setDisplayType(DisplayType displayType) {
mDisplayType = displayType;
mAdapter.setDisplayType(mDisplayType);
}
public void enableQuickContact(boolean enableQuickContact) {
mAdapter.enableQuickContact(enableQuickContact);
}
private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener =
new LoaderCallbacks<Cursor>() {
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
switch (mDisplayType) {
case STARRED_ONLY:
return ContactTileLoaderFactory.createStarredLoader(getActivity());
case STREQUENT:
return ContactTileLoaderFactory.createStrequentLoader(getActivity());
case FREQUENT_ONLY:
return ContactTileLoaderFactory.createFrequentLoader(getActivity());
default:
throw new IllegalStateException(
"Unrecognized DisplayType " + mDisplayType);
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data == null || data.isClosed()) {
Log.e(TAG, "Failed to load contacts");
return;
}
mAdapter.setContactCursor(data);
mEmptyView.setText(getEmptyStateText());
mListView.setEmptyView(mEmptyView);
// invalidate the menu options if needed
invalidateOptionsMenuIfNeeded();
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {}
};
private boolean isOptionsMenuChanged() {
return mOptionsMenuHasFrequents != internalHasFrequents();
}
private void invalidateOptionsMenuIfNeeded() {
if (isOptionsMenuChanged()) {
getActivity().invalidateOptionsMenu();
}
}
private String getEmptyStateText() {
String emptyText;
switch (mDisplayType) {
case STREQUENT:
case STARRED_ONLY:
emptyText = getString(R.string.listTotalAllContactsZeroStarred);
break;
case FREQUENT_ONLY:
case GROUP_MEMBERS:
emptyText = getString(R.string.noContacts);
break;
default:
throw new IllegalArgumentException("Unrecognized DisplayType " + mDisplayType);
}
return emptyText;
}
public void setListener(Listener listener) {
mListener = listener;
}
private ContactTileView.Listener mAdapterListener =
new ContactTileView.Listener() {
@Override
public void onContactSelected(Uri contactUri, Rect targetRect) {
if (mListener != null) {
mListener.onContactSelected(contactUri, targetRect);
}
}
@Override
public void onCallNumberDirectly(String phoneNumber) {
if (mListener != null) {
mListener.onCallNumberDirectly(phoneNumber);
}
}
@Override
public int getApproximateTileWidth() {
return getView().getWidth() / mAdapter.getColumnCount();
}
};
}