summaryrefslogtreecommitdiff
path: root/src/com/android/dialer/list/SpeedDialFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/dialer/list/SpeedDialFragment.java')
-rw-r--r--src/com/android/dialer/list/SpeedDialFragment.java504
1 files changed, 0 insertions, 504 deletions
diff --git a/src/com/android/dialer/list/SpeedDialFragment.java b/src/com/android/dialer/list/SpeedDialFragment.java
deleted file mode 100644
index 7e10297d0..000000000
--- a/src/com/android/dialer/list/SpeedDialFragment.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright (C) 2013 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.dialer.list;
-
-import static android.Manifest.permission.READ_CONTACTS;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.LoaderManager;
-import android.content.CursorLoader;
-import android.content.Loader;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Trace;
-import android.support.v13.app.FragmentCompat;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.animation.AnimationUtils;
-import android.view.animation.LayoutAnimationController;
-import android.widget.AbsListView;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.FrameLayout;
-import android.widget.FrameLayout.LayoutParams;
-import android.widget.ImageView;
-import android.widget.ListView;
-
-import com.android.contacts.common.ContactPhotoManager;
-import com.android.contacts.common.ContactTileLoaderFactory;
-import com.android.contacts.common.list.ContactTileView;
-import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
-import com.android.contacts.common.util.PermissionsUtil;
-import com.android.dialer.R;
-import com.android.dialer.widget.EmptyContentView;
-import com.android.incallui.Call.LogState;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * This fragment displays the user's favorite/frequent contacts in a grid.
- */
-public class SpeedDialFragment extends Fragment implements OnItemClickListener,
- PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener,
- EmptyContentView.OnEmptyViewActionButtonClickedListener,
- FragmentCompat.OnRequestPermissionsResultCallback {
-
- private static final int READ_CONTACTS_PERMISSION_REQUEST_CODE = 1;
-
- /**
- * By default, the animation code assumes that all items in a list view are of the same height
- * when animating new list items into view (e.g. from the bottom of the screen into view).
- * This can cause incorrect translation offsets when a item that is larger or smaller than
- * other list item is removed from the list. This key is used to provide the actual height
- * of the removed object so that the actual translation appears correct to the user.
- */
- private static final long KEY_REMOVED_ITEM_HEIGHT = Long.MAX_VALUE;
-
- private static final String TAG = "SpeedDialFragment";
- private static final boolean DEBUG = false;
-
- private int mAnimationDuration;
-
- /**
- * Used with LoaderManager.
- */
- private static int LOADER_ID_CONTACT_TILE = 1;
-
- public interface HostInterface {
- public void setDragDropController(DragDropController controller);
- public void showAllContactsTab();
- }
-
- private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
- @Override
- public CursorLoader onCreateLoader(int id, Bundle args) {
- if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader.");
- return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity());
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished");
- mContactTileAdapter.setContactCursor(data);
- setEmptyViewVisibility(mContactTileAdapter.getCount() == 0);
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. ");
- }
- }
-
- private class ContactTileAdapterListener implements ContactTileView.Listener {
- @Override
- public void onContactSelected(Uri contactUri, Rect targetRect) {
- if (mPhoneNumberPickerActionListener != null) {
- mPhoneNumberPickerActionListener.onPickDataUri(contactUri,
- false /* isVideoCall */, LogState.INITIATION_SPEED_DIAL);
- }
- }
-
- @Override
- public void onCallNumberDirectly(String phoneNumber) {
- if (mPhoneNumberPickerActionListener != null) {
- mPhoneNumberPickerActionListener.onPickPhoneNumber(phoneNumber,
- false /* isVideoCall */, LogState.INITIATION_SPEED_DIAL);
- }
- }
-
- @Override
- public int getApproximateTileWidth() {
- return getView().getWidth();
- }
- }
-
- private class ScrollListener implements ListView.OnScrollListener {
- @Override
- public void onScroll(AbsListView view,
- int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- if (mActivityScrollListener != null) {
- mActivityScrollListener.onListFragmentScroll(firstVisibleItem, visibleItemCount,
- totalItemCount);
- }
- }
-
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- mActivityScrollListener.onListFragmentScrollStateChange(scrollState);
- }
- }
-
- private OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener;
-
- private OnListFragmentScrolledListener mActivityScrollListener;
- private PhoneFavoritesTileAdapter mContactTileAdapter;
-
- private View mParentView;
-
- private PhoneFavoriteListView mListView;
-
- private View mContactTileFrame;
-
- private final HashMap<Long, Integer> mItemIdTopMap = new HashMap<Long, Integer>();
- private final HashMap<Long, Integer> mItemIdLeftMap = new HashMap<Long, Integer>();
-
- /**
- * Layout used when there are no favorites.
- */
- private EmptyContentView mEmptyView;
-
- private final ContactTileView.Listener mContactTileAdapterListener =
- new ContactTileAdapterListener();
- private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener =
- new ContactTileLoaderListener();
- private final ScrollListener mScrollListener = new ScrollListener();
-
- @Override
- public void onAttach(Activity activity) {
- if (DEBUG) Log.d(TAG, "onAttach()");
- super.onAttach(activity);
-
- // Construct two base adapters which will become part of PhoneFavoriteMergedAdapter.
- // We don't construct the resultant adapter at this moment since it requires LayoutInflater
- // that will be available on onCreateView().
- mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener,
- this);
- mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity));
- }
-
- @Override
- public void onCreate(Bundle savedState) {
- if (DEBUG) Log.d(TAG, "onCreate()");
- Trace.beginSection(TAG + " onCreate");
- super.onCreate(savedState);
-
- mAnimationDuration = getResources().getInteger(R.integer.fade_duration);
- Trace.endSection();
- }
-
- @Override
- public void onResume() {
- Trace.beginSection(TAG + " onResume");
- super.onResume();
- if (mContactTileAdapter != null) {
- mContactTileAdapter.refreshContactsPreferences();
- }
- if (PermissionsUtil.hasContactsPermissions(getActivity())) {
- if (getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE) == null) {
- getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null,
- mContactTileLoaderListener);
-
- } else {
- getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad();
- }
-
- mEmptyView.setDescription(R.string.speed_dial_empty);
- mEmptyView.setActionLabel(R.string.speed_dial_empty_add_favorite_action);
- } else {
- mEmptyView.setDescription(R.string.permission_no_speeddial);
- mEmptyView.setActionLabel(R.string.permission_single_turn_on);
- }
- Trace.endSection();
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- Trace.beginSection(TAG + " onCreateView");
- mParentView = inflater.inflate(R.layout.speed_dial_fragment, container, false);
-
- mListView = (PhoneFavoriteListView) mParentView.findViewById(R.id.contact_tile_list);
- mListView.setOnItemClickListener(this);
- mListView.setVerticalScrollBarEnabled(false);
- mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT);
- mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
- mListView.getDragDropController().addOnDragDropListener(mContactTileAdapter);
-
- final ImageView dragShadowOverlay =
- (ImageView) getActivity().findViewById(R.id.contact_tile_drag_shadow_overlay);
- mListView.setDragShadowOverlay(dragShadowOverlay);
-
- mEmptyView = (EmptyContentView) mParentView.findViewById(R.id.empty_list_view);
- mEmptyView.setImage(R.drawable.empty_speed_dial);
- mEmptyView.setActionClickedListener(this);
-
- mContactTileFrame = mParentView.findViewById(R.id.contact_tile_frame);
-
- final LayoutAnimationController controller = new LayoutAnimationController(
- AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
- controller.setDelay(0);
- mListView.setLayoutAnimation(controller);
- mListView.setAdapter(mContactTileAdapter);
-
- mListView.setOnScrollListener(mScrollListener);
- mListView.setFastScrollEnabled(false);
- mListView.setFastScrollAlwaysVisible(false);
-
- //prevent content changes of the list from firing accessibility events.
- mListView.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_NONE);
- ContentChangedFilter.addToParent(mListView);
-
- Trace.endSection();
- return mParentView;
- }
-
- public boolean hasFrequents() {
- if (mContactTileAdapter == null) return false;
- return mContactTileAdapter.getNumFrequents() > 0;
- }
-
- /* package */ void setEmptyViewVisibility(final boolean visible) {
- final int previousVisibility = mEmptyView.getVisibility();
- final int emptyViewVisibility = visible ? View.VISIBLE : View.GONE;
- final int listViewVisibility = visible ? View.GONE : View.VISIBLE;
-
- if (previousVisibility != emptyViewVisibility) {
- final FrameLayout.LayoutParams params = (LayoutParams) mContactTileFrame
- .getLayoutParams();
- params.height = visible ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
- mContactTileFrame.setLayoutParams(params);
- mEmptyView.setVisibility(emptyViewVisibility);
- mListView.setVisibility(listViewVisibility);
- }
- }
-
- @Override
- public void onStart() {
- super.onStart();
-
- final Activity activity = getActivity();
-
- try {
- mActivityScrollListener = (OnListFragmentScrolledListener) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement OnListFragmentScrolledListener");
- }
-
- try {
- OnDragDropListener listener = (OnDragDropListener) activity;
- mListView.getDragDropController().addOnDragDropListener(listener);
- ((HostInterface) activity).setDragDropController(mListView.getDragDropController());
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement OnDragDropListener and HostInterface");
- }
-
- try {
- mPhoneNumberPickerActionListener = (OnPhoneNumberPickerActionListener) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement PhoneFavoritesFragment.listener");
- }
-
- // Use initLoader() instead of restartLoader() to refraining unnecessary reload.
- // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will
- // be called, on which we'll check if "all" contacts should be reloaded again or not.
- if (PermissionsUtil.hasContactsPermissions(activity)) {
- getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener);
- } else {
- setEmptyViewVisibility(true);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * This is only effective for elements provided by {@link #mContactTileAdapter}.
- * {@link #mContactTileAdapter} has its own logic for click events.
- */
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final int contactTileAdapterCount = mContactTileAdapter.getCount();
- if (position <= contactTileAdapterCount) {
- Log.e(TAG, "onItemClick() event for unexpected position. "
- + "The position " + position + " is before \"all\" section. Ignored.");
- }
- }
-
- /**
- * Cache the current view offsets into memory. Once a relayout of views in the ListView
- * has happened due to a dataset change, the cached offsets are used to create animations
- * that slide views from their previous positions to their new ones, to give the appearance
- * that the views are sliding into their new positions.
- */
- private void saveOffsets(int removedItemHeight) {
- final int firstVisiblePosition = mListView.getFirstVisiblePosition();
- if (DEBUG) {
- Log.d(TAG, "Child count : " + mListView.getChildCount());
- }
- for (int i = 0; i < mListView.getChildCount(); i++) {
- final View child = mListView.getChildAt(i);
- final int position = firstVisiblePosition + i;
- // Since we are getting the position from mListView and then querying
- // mContactTileAdapter, its very possible that things are out of sync
- // and we might index out of bounds. Let's make sure that this doesn't happen.
- if (!mContactTileAdapter.isIndexInBound(position)) {
- continue;
- }
- final long itemId = mContactTileAdapter.getItemId(position);
- if (DEBUG) {
- Log.d(TAG, "Saving itemId: " + itemId + " for listview child " + i + " Top: "
- + child.getTop());
- }
- mItemIdTopMap.put(itemId, child.getTop());
- mItemIdLeftMap.put(itemId, child.getLeft());
- }
- mItemIdTopMap.put(KEY_REMOVED_ITEM_HEIGHT, removedItemHeight);
- }
-
- /*
- * Performs animations for the gridView
- */
- private void animateGridView(final long... idsInPlace) {
- if (mItemIdTopMap.isEmpty()) {
- // Don't do animations if the database is being queried for the first time and
- // the previous item offsets have not been cached, or the user hasn't done anything
- // (dragging, swiping etc) that requires an animation.
- return;
- }
-
- final ViewTreeObserver observer = mListView.getViewTreeObserver();
- observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- @SuppressWarnings("unchecked")
- @Override
- public boolean onPreDraw() {
- observer.removeOnPreDrawListener(this);
- final int firstVisiblePosition = mListView.getFirstVisiblePosition();
- final AnimatorSet animSet = new AnimatorSet();
- final ArrayList<Animator> animators = new ArrayList<Animator>();
- for (int i = 0; i < mListView.getChildCount(); i++) {
- final View child = mListView.getChildAt(i);
- int position = firstVisiblePosition + i;
-
- // Since we are getting the position from mListView and then querying
- // mContactTileAdapter, its very possible that things are out of sync
- // and we might index out of bounds. Let's make sure that this doesn't happen.
- if (!mContactTileAdapter.isIndexInBound(position)) {
- continue;
- }
-
- final long itemId = mContactTileAdapter.getItemId(position);
-
- if (containsId(idsInPlace, itemId)) {
- animators.add(ObjectAnimator.ofFloat(
- child, "alpha", 0.0f, 1.0f));
- break;
- } else {
- Integer startTop = mItemIdTopMap.get(itemId);
- Integer startLeft = mItemIdLeftMap.get(itemId);
- final int top = child.getTop();
- final int left = child.getLeft();
- int deltaX = 0;
- int deltaY = 0;
-
- if (startLeft != null) {
- if (startLeft != left) {
- deltaX = startLeft - left;
- animators.add(ObjectAnimator.ofFloat(
- child, "translationX", deltaX, 0.0f));
- }
- }
-
- if (startTop != null) {
- if (startTop != top) {
- deltaY = startTop - top;
- animators.add(ObjectAnimator.ofFloat(
- child, "translationY", deltaY, 0.0f));
- }
- }
-
- if (DEBUG) {
- Log.d(TAG, "Found itemId: " + itemId + " for listview child " + i +
- " Top: " + top +
- " Delta: " + deltaY);
- }
- }
- }
-
- if (animators.size() > 0) {
- animSet.setDuration(mAnimationDuration).playTogether(animators);
- animSet.start();
- }
-
- mItemIdTopMap.clear();
- mItemIdLeftMap.clear();
- return true;
- }
- });
- }
-
- private boolean containsId(long[] ids, long target) {
- // Linear search on array is fine because this is typically only 0-1 elements long
- for (int i = 0; i < ids.length; i++) {
- if (ids[i] == target) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void onDataSetChangedForAnimation(long... idsInPlace) {
- animateGridView(idsInPlace);
- }
-
- @Override
- public void cacheOffsetsForDatasetChange() {
- saveOffsets(0);
- }
-
- public AbsListView getListView() {
- return mListView;
- }
-
- @Override
- public void onEmptyViewActionButtonClicked() {
- final Activity activity = getActivity();
- if (activity == null) {
- return;
- }
-
- if (!PermissionsUtil.hasPermission(activity, READ_CONTACTS)) {
- FragmentCompat.requestPermissions(this, new String[] {READ_CONTACTS},
- READ_CONTACTS_PERMISSION_REQUEST_CODE);
- } else {
- // Switch tabs
- ((HostInterface) activity).showAllContactsTab();
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions,
- int[] grantResults) {
- if (requestCode == READ_CONTACTS_PERMISSION_REQUEST_CODE) {
- if (grantResults.length == 1 && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
- PermissionsUtil.notifyPermissionGranted(getActivity(), READ_CONTACTS);
- }
- }
- }
-}