From d9d409a86330c5fde0cc465562c6d3eb96ec10eb Mon Sep 17 00:00:00 2001 From: Yorke Lee Date: Wed, 4 Feb 2015 17:32:28 -0800 Subject: Extract SwipeableShortcutCard into its own class Intial work to separate shortcut card view logic and the actual adapter to prepare for removal of the shortcut cards list view. Change-Id: Ie102fcd1d0d7be13c326cdf4c47502194a2f5ad6 --- src/com/android/dialer/list/ListsFragment.java | 1 - .../android/dialer/list/ShortcutCardsAdapter.java | 213 ------------------- .../android/dialer/list/SwipeableShortcutCard.java | 231 +++++++++++++++++++++ 3 files changed, 231 insertions(+), 214 deletions(-) create mode 100644 src/com/android/dialer/list/SwipeableShortcutCard.java (limited to 'src') diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java index 7a5376c01..e9ce57b85 100644 --- a/src/com/android/dialer/list/ListsFragment.java +++ b/src/com/android/dialer/list/ListsFragment.java @@ -29,7 +29,6 @@ import com.android.dialer.calllog.CallLogFragment; import com.android.dialer.calllog.CallLogQuery; import com.android.dialer.calllog.CallLogQueryHandler; import com.android.dialer.calllog.ContactInfoHelper; -import com.android.dialer.list.ShortcutCardsAdapter.SwipeableShortcutCard; import com.android.dialer.util.DialerUtils; import com.android.dialer.widget.ActionBarController; import com.android.dialer.widget.OverlappingPaneLayout; diff --git a/src/com/android/dialer/list/ShortcutCardsAdapter.java b/src/com/android/dialer/list/ShortcutCardsAdapter.java index 6410eabf6..ad6a61c79 100644 --- a/src/com/android/dialer/list/ShortcutCardsAdapter.java +++ b/src/com/android/dialer/list/ShortcutCardsAdapter.java @@ -20,23 +20,14 @@ import android.content.Context; import android.content.res.Resources; import android.database.Cursor; import android.database.DataSetObserver; -import android.graphics.Rect; -import android.text.TextUtils; -import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.BaseAdapter; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.TextView; -import com.android.dialer.R; import com.android.dialer.calllog.CallLogAdapter; import com.android.dialer.calllog.CallLogNotificationsHelper; import com.android.dialer.calllog.CallLogQueryHandler; import com.android.dialer.list.SwipeHelper.OnItemGestureListener; -import com.android.dialer.list.SwipeHelper.SwipeHelperCallback; /** * An adapter that displays call shortcuts from {@link com.android.dialer.calllog.CallLogAdapter} @@ -52,24 +43,11 @@ public class ShortcutCardsAdapter extends BaseAdapter { } private static final String TAG = ShortcutCardsAdapter.class.getSimpleName(); - private static final float CLIP_CARD_BARELY_HIDDEN_RATIO = 0.001f; - private static final float CLIP_CARD_MOSTLY_HIDDEN_RATIO = 0.9f; - // Fade out 5x faster than the hidden ratio. - private static final float CLIP_CARD_OPACITY_RATIO = 5f; private final CallLogAdapter mCallLogAdapter; private final ListsFragment mFragment; - private final int mCallLogMarginHorizontal; - private final int mCallLogMarginTop; - private final int mCallLogMarginBottom; - private final int mCallLogPaddingStart; - private final int mCallLogPaddingTop; - private final int mCallLogPaddingBottom; - private final int mCardMaxHorizontalClip; - private final int mShortCardBackgroundColor; - private final Context mContext; private final DataSetObserver mObserver; @@ -117,22 +95,6 @@ public class ShortcutCardsAdapter extends BaseAdapter { final Resources resources = context.getResources(); mContext = context; mFragment = fragment; - mCardMaxHorizontalClip = - resources.getDimensionPixelSize(R.dimen.recent_call_log_item_horizontal_clip_limit); - mCallLogMarginHorizontal = - resources.getDimensionPixelSize(R.dimen.recent_call_log_item_margin_horizontal); - mCallLogMarginTop = - resources.getDimensionPixelSize(R.dimen.recent_call_log_item_margin_top); - mCallLogMarginBottom = - resources.getDimensionPixelSize(R.dimen.recent_call_log_item_margin_bottom); - mCallLogPaddingStart = - resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding_start); - mCallLogPaddingTop = - resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding_top); - mCallLogPaddingBottom = - resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding_bottom); - mShortCardBackgroundColor = resources.getColor(R.color.call_log_expanded_background_color); - mCallLogAdapter = callLogAdapter; mObserver = new CustomDataSetObserver(); @@ -215,179 +177,4 @@ public class ShortcutCardsAdapter extends BaseAdapter { public boolean isEnabled(int position) { return mCallLogAdapter.isEnabled(position); } - - /** - * The swipeable call log row. - */ - class SwipeableShortcutCard extends FrameLayout implements SwipeHelperCallback { - private SwipeHelper mSwipeHelper; - private OnItemGestureListener mOnItemSwipeListener; - - private float mPreviousTranslationZ = 0; - private Rect mClipRect = new Rect(); - - public SwipeableShortcutCard(Context context) { - super(context); - final float densityScale = getResources().getDisplayMetrics().density; - final float pagingTouchSlop = ViewConfiguration.get(context) - .getScaledPagingTouchSlop(); - mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, - densityScale, pagingTouchSlop); - } - - private void prepareChildView(View view) { - // Override CallLogAdapter's accessibility behavior; don't expand the shortcut card. - view.setAccessibilityDelegate(null); - view.setBackgroundResource(R.drawable.rounded_corner_bg); - - final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.WRAP_CONTENT); - params.setMargins( - mCallLogMarginHorizontal, - mCallLogMarginTop, - mCallLogMarginHorizontal, - mCallLogMarginBottom); - view.setLayoutParams(params); - - LinearLayout actionView = - (LinearLayout) view.findViewById(R.id.primary_action_view); - actionView.setPaddingRelative( - mCallLogPaddingStart, - mCallLogPaddingTop, - actionView.getPaddingEnd(), - mCallLogPaddingBottom); - - // TODO: Set content description including type/location and time information. - TextView nameView = (TextView) actionView.findViewById(R.id.name); - - actionView.setContentDescription( - TextUtils.expandTemplate( - getResources().getString(R.string.description_call_back_action), - nameView.getText())); - - mPreviousTranslationZ = getResources().getDimensionPixelSize( - R.dimen.recent_call_log_item_translation_z); - view.setTranslationZ(mPreviousTranslationZ); - - final ViewGroup callLogItem = (ViewGroup) view.findViewById(R.id.call_log_list_item); - // Reset the internal call log item view if it is being recycled - callLogItem.setTranslationX(0); - callLogItem.setTranslationY(0); - callLogItem.setAlpha(1); - callLogItem.setClipBounds(null); - setChildrenOpacity(callLogItem, 1.0f); - - callLogItem.findViewById(R.id.call_log_row) - .setBackgroundColor(mShortCardBackgroundColor); - - callLogItem.findViewById(R.id.call_indicator_icon).setVisibility(View.VISIBLE); - } - - @Override - public View getChildAtPosition(MotionEvent ev) { - return getChildCount() > 0 ? getChildAt(0) : null; - } - - @Override - public View getChildContentView(View v) { - return v.findViewById(R.id.call_log_list_item); - } - - @Override - public void onScroll() {} - - @Override - public boolean canChildBeDismissed(View v) { - return true; - } - - @Override - public void onBeginDrag(View v) { - // We do this so the underlying ScrollView knows that it won't get - // the chance to intercept events anymore - requestDisallowInterceptTouchEvent(true); - } - - @Override - public void onChildDismissed(View v) { - if (v != null && mOnItemSwipeListener != null) { - mOnItemSwipeListener.onSwipe(v); - } - } - - @Override - public void onDragCancelled(View v) {} - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (mSwipeHelper != null) { - return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev); - } else { - return super.onInterceptTouchEvent(ev); - } - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - if (mSwipeHelper != null) { - return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev); - } else { - return super.onTouchEvent(ev); - } - } - - public void setOnItemSwipeListener(OnItemGestureListener listener) { - mOnItemSwipeListener = listener; - } - - /** - * Clips the card by a specified amount. - * - * @param ratioHidden A float indicating how much of each edge of the card should be - * clipped. If 0, the entire card is displayed. If 0.5f, each edge is hidden - * entirely, thus obscuring the entire card. - */ - public void clipCard(float ratioHidden) { - final View viewToClip = getChildAt(0); - if (viewToClip == null) { - return; - } - int width = viewToClip.getWidth(); - int height = viewToClip.getHeight(); - - if (ratioHidden <= CLIP_CARD_BARELY_HIDDEN_RATIO) { - viewToClip.setTranslationZ(mPreviousTranslationZ); - } else if (viewToClip.getTranslationZ() != 0){ - mPreviousTranslationZ = viewToClip.getTranslationZ(); - viewToClip.setTranslationZ(0); - } - - if (ratioHidden > CLIP_CARD_MOSTLY_HIDDEN_RATIO) { - mClipRect.set(0, 0 , 0, 0); - setVisibility(View.INVISIBLE); - } else { - setVisibility(View.VISIBLE); - int newTop = (int) (ratioHidden * height); - mClipRect.set(0, newTop, width, height); - - // Since the pane will be overlapping with the action bar, apply a vertical offset - // to top align the clipped card in the viewable area; - viewToClip.setTranslationY(-newTop); - } - viewToClip.setClipBounds(mClipRect); - - // If the view has any children, fade them out of view. - final ViewGroup viewGroup = (ViewGroup) viewToClip; - setChildrenOpacity( - viewGroup, Math.max(0, 1 - (CLIP_CARD_OPACITY_RATIO * ratioHidden))); - } - - private void setChildrenOpacity(ViewGroup viewGroup, float alpha) { - final int count = viewGroup.getChildCount(); - for (int i = 0; i < count; i++) { - viewGroup.getChildAt(i).setAlpha(alpha); - } - } - } } diff --git a/src/com/android/dialer/list/SwipeableShortcutCard.java b/src/com/android/dialer/list/SwipeableShortcutCard.java new file mode 100644 index 000000000..93e9fff10 --- /dev/null +++ b/src/com/android/dialer/list/SwipeableShortcutCard.java @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2015 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 android.content.Context; +import android.content.res.Resources; +import android.graphics.Rect; +import android.text.TextUtils; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.dialer.R; +import com.android.dialer.list.SwipeHelper.OnItemGestureListener; +import com.android.dialer.list.SwipeHelper.SwipeHelperCallback; + +/** + * The swipeable call log row. + */ +public class SwipeableShortcutCard extends FrameLayout implements SwipeHelperCallback { + + private static final float CLIP_CARD_BARELY_HIDDEN_RATIO = 0.001f; + private static final float CLIP_CARD_MOSTLY_HIDDEN_RATIO = 0.9f; + // Fade out 5x faster than the hidden ratio. + private static final float CLIP_CARD_OPACITY_RATIO = 5f; + + final int mCallLogMarginHorizontal; + final int mCallLogMarginTop; + final int mCallLogMarginBottom; + final int mCallLogPaddingStart; + final int mCallLogPaddingTop; + final int mCallLogPaddingBottom; + final int mShortCardBackgroundColor; + + private SwipeHelper mSwipeHelper; + private OnItemGestureListener mOnItemSwipeListener; + + private float mPreviousTranslationZ = 0; + private Rect mClipRect = new Rect(); + + public SwipeableShortcutCard(Context context) { + super(context); + final Resources resources = getResources(); + final float densityScale =resources.getDisplayMetrics().density; + final float pagingTouchSlop = ViewConfiguration.get(context) + .getScaledPagingTouchSlop(); + mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, + densityScale, pagingTouchSlop); + + mCallLogMarginHorizontal = + resources.getDimensionPixelSize(R.dimen.recent_call_log_item_margin_horizontal); + mCallLogMarginTop = + resources.getDimensionPixelSize(R.dimen.recent_call_log_item_margin_top); + mCallLogMarginBottom = + resources.getDimensionPixelSize(R.dimen.recent_call_log_item_margin_bottom); + mCallLogPaddingStart = + resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding_start); + mCallLogPaddingTop = + resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding_top); + mCallLogPaddingBottom = + resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding_bottom); + mShortCardBackgroundColor = + resources.getColor(R.color.call_log_expanded_background_color, null); + } + + void prepareChildView(View view) { + // Override CallLogAdapter's accessibility behavior; don't expand the shortcut card. + view.setAccessibilityDelegate(null); + view.setBackgroundResource(R.drawable.rounded_corner_bg); + + final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.WRAP_CONTENT); + params.setMargins(mCallLogMarginHorizontal, mCallLogMarginTop, mCallLogMarginHorizontal, + mCallLogMarginBottom); + view.setLayoutParams(params); + + LinearLayout actionView = + (LinearLayout) view.findViewById(R.id.primary_action_view); + actionView.setPaddingRelative(mCallLogPaddingStart, mCallLogPaddingTop, + actionView.getPaddingEnd(), mCallLogPaddingBottom); + + // TODO: Set content description including type/location and time information. + TextView nameView = (TextView) actionView.findViewById(R.id.name); + + actionView.setContentDescription( + TextUtils.expandTemplate( + getResources().getString(R.string.description_call_back_action), + nameView.getText())); + + mPreviousTranslationZ = getResources().getDimensionPixelSize( + R.dimen.recent_call_log_item_translation_z); + view.setTranslationZ(mPreviousTranslationZ); + + final ViewGroup callLogItem = (ViewGroup) view.findViewById(R.id.call_log_list_item); + // Reset the internal call log item view if it is being recycled + callLogItem.setTranslationX(0); + callLogItem.setTranslationY(0); + callLogItem.setAlpha(1); + callLogItem.setClipBounds(null); + setChildrenOpacity(callLogItem, 1.0f); + + callLogItem.findViewById(R.id.call_log_row) + .setBackgroundColor(mShortCardBackgroundColor); + + callLogItem.findViewById(R.id.call_indicator_icon).setVisibility(View.VISIBLE); + } + + @Override + public View getChildAtPosition(MotionEvent ev) { + return getChildCount() > 0 ? getChildAt(0) : null; + } + + @Override + public View getChildContentView(View v) { + return v.findViewById(R.id.call_log_list_item); + } + + @Override + public void onScroll() {} + + @Override + public boolean canChildBeDismissed(View v) { + return true; + } + + @Override + public void onBeginDrag(View v) { + // We do this so the underlying ScrollView knows that it won't get + // the chance to intercept events anymore + requestDisallowInterceptTouchEvent(true); + } + + @Override + public void onChildDismissed(View v) { + if (v != null && mOnItemSwipeListener != null) { + mOnItemSwipeListener.onSwipe(v); + } + } + + @Override + public void onDragCancelled(View v) {} + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (mSwipeHelper != null) { + return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev); + } else { + return super.onInterceptTouchEvent(ev); + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (mSwipeHelper != null) { + return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev); + } else { + return super.onTouchEvent(ev); + } + } + + public void setOnItemSwipeListener(OnItemGestureListener listener) { + mOnItemSwipeListener = listener; + } + + /** + * Clips the card by a specified amount. + * + * @param ratioHidden A float indicating how much of each edge of the card should be + * clipped. If 0, the entire card is displayed. If 0.5f, each edge is hidden + * entirely, thus obscuring the entire card. + */ + public void clipCard(float ratioHidden) { + final View viewToClip = getChildAt(0); + if (viewToClip == null) { + return; + } + int width = viewToClip.getWidth(); + int height = viewToClip.getHeight(); + + if (ratioHidden <= CLIP_CARD_BARELY_HIDDEN_RATIO) { + viewToClip.setTranslationZ(mPreviousTranslationZ); + } else if (viewToClip.getTranslationZ() != 0){ + mPreviousTranslationZ = viewToClip.getTranslationZ(); + viewToClip.setTranslationZ(0); + } + + if (ratioHidden > CLIP_CARD_MOSTLY_HIDDEN_RATIO) { + mClipRect.set(0, 0 , 0, 0); + setVisibility(View.INVISIBLE); + } else { + setVisibility(View.VISIBLE); + int newTop = (int) (ratioHidden * height); + mClipRect.set(0, newTop, width, height); + + // Since the pane will be overlapping with the action bar, apply a vertical offset + // to top align the clipped card in the viewable area; + viewToClip.setTranslationY(-newTop); + } + viewToClip.setClipBounds(mClipRect); + + // If the view has any children, fade them out of view. + final ViewGroup viewGroup = (ViewGroup) viewToClip; + setChildrenOpacity( + viewGroup, Math.max(0, 1 - (CLIP_CARD_OPACITY_RATIO * ratioHidden))); + } + + private void setChildrenOpacity(ViewGroup viewGroup, float alpha) { + final int count = viewGroup.getChildCount(); + for (int i = 0; i < count; i++) { + viewGroup.getChildAt(i).setAlpha(alpha); + } + } +} \ No newline at end of file -- cgit v1.2.3