From 251957d76e57eb6e5f8068b37346144e10e586a4 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 9 Apr 2014 04:24:09 +0200 Subject: [PATCH] Double tap interaction for notifications on lockscreen. This change also uses a different background for notifications on the lockscreen and moves the background drawable from the templates to SystemUI. Bug: 13635952 Change-Id: Icf09178065aa7fc0472adef70342d637fbcca785 --- .../res/drawable/notification_quantum_bg.xml | 14 ++- ...nd.xml => notification_quantum_bg_dim.xml} | 15 ++- .../notification_template_quantum_base.xml | 1 - ...notification_template_quantum_big_base.xml | 1 - ...ification_template_quantum_big_picture.xml | 1 - ...notification_template_quantum_big_text.xml | 1 - .../notification_template_quantum_inbox.xml | 1 - core/res/res/values/symbols.xml | 2 + .../layout/status_bar_notification_row.xml | 1 + .../systemui/statusbar/BaseStatusBar.java | 15 ++- .../statusbar/ExpandableNotificationRow.java | 23 ++++ .../systemui/statusbar/LatestItemView.java | 118 ++++++++++++++++++ .../statusbar/phone/PhoneStatusBar.java | 8 +- 13 files changed, 178 insertions(+), 23 deletions(-) rename core/res/res/drawable/{notification_quantum_background.xml => notification_quantum_bg_dim.xml} (67%) diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml index 608115e631e9a..300a565ba68eb 100644 --- a/core/res/res/drawable/notification_quantum_bg.xml +++ b/core/res/res/drawable/notification_quantum_bg.xml @@ -16,6 +16,16 @@ --> - - + + + + + + + + + + + + \ No newline at end of file diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_bg_dim.xml similarity index 67% rename from core/res/res/drawable/notification_quantum_background.xml rename to core/res/res/drawable/notification_quantum_bg_dim.xml index 7b508a94dcb13..11b6e1b5d534d 100644 --- a/core/res/res/drawable/notification_quantum_background.xml +++ b/core/res/res/drawable/notification_quantum_bg_dim.xml @@ -15,7 +15,14 @@ ~ limitations under the License --> - - - - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml index 8863cfa9341d7..8f3019d829f0e 100644 --- a/core/res/res/layout/notification_template_quantum_base.xml +++ b/core/res/res/layout/notification_template_quantum_base.xml @@ -17,7 +17,6 @@ + + diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index e74e5684710d4..d61d8b9cb8919 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -32,6 +32,7 @@ android:layout_marginTop="@dimen/notification_divider_height" android:focusable="true" android:clickable="true" + android:background="@*android:drawable/notification_quantum_bg" > 0 && version < Build.VERSION_CODES.GINGERBREAD) { content.setBackgroundResource(R.drawable.notification_row_legacy_bg); - } else { - content.setBackgroundResource(com.android.internal.R.drawable.notification_bg); } } } @@ -1004,7 +1002,7 @@ public abstract class BaseStatusBar extends SystemUI implements // Remove the expanded view. ViewGroup rowParent = (ViewGroup)entry.row.getParent(); if (rowParent != null) rowParent.removeView(entry.row); - updateExpansionStates(); + updateRowStates(); updateNotificationIcons(); return entry.notification; @@ -1048,7 +1046,7 @@ public abstract class BaseStatusBar extends SystemUI implements Log.d(TAG, "addNotificationViews: added at " + pos); } updateInterceptedState(entry); - updateExpansionStates(); + updateRowStates(); updateNotificationIcons(); } @@ -1056,7 +1054,10 @@ public abstract class BaseStatusBar extends SystemUI implements addNotificationViews(createNotificationViews(key, notification)); } - protected void updateExpansionStates() { + /** + * Updates expanded, dimmed and locked states of notification rows. + */ + protected void updateRowStates() { int n = mNotificationData.size(); for (int i = 0; i < n; i++) { NotificationData.Entry entry = mNotificationData.get(i); @@ -1068,6 +1069,8 @@ public abstract class BaseStatusBar extends SystemUI implements entry.row.setExpanded(top || entry.row.isUserExpanded()); } } + entry.row.setDimmed(mOnKeyguard); + entry.row.setLocked(mOnKeyguard); } } @@ -1222,7 +1225,7 @@ public abstract class BaseStatusBar extends SystemUI implements handleNotificationError(key, notification, "Couldn't update icon: " + ic); return; } - updateExpansionStates(); + updateRowStates(); } catch (RuntimeException e) { // It failed to add cleanly. Log, and remove the view from the panel. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index b3d8688d4b42f..c9ca55b4ff668 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -36,10 +36,18 @@ public class ExpandableNotificationRow extends FrameLayout { /** are we showing the "public" version */ private boolean mShowingPublic; + private LatestItemView mLatestItemView; + public ExpandableNotificationRow(Context context, AttributeSet attrs) { super(context, attrs); } + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mLatestItemView = (LatestItemView) findViewById(R.id.container); + } + public int getRowHeight() { return mRowHeight; } @@ -93,4 +101,19 @@ public class ExpandableNotificationRow extends FrameLayout { publicLayout.setVisibility(show ? View.VISIBLE : View.GONE); findViewById(R.id.expanded).setVisibility(show ? View.GONE : View.VISIBLE); } + + /** + * Sets the notification as dimmed, meaning that it will appear in a more gray variant. + */ + public void setDimmed(boolean dimmed) { + mLatestItemView.setDimmed(dimmed); + } + + /** + * Sets the notification as locked. In the locked state, the first tap will produce a quantum + * ripple to make the notification brighter and only the second tap will cause a click. + */ + public void setLocked(boolean locked) { + mLatestItemView.setLocked(locked); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java index 6419777566472..ad9028dc860e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java @@ -17,16 +17,44 @@ package com.android.systemui.statusbar; import android.content.Context; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; public class LatestItemView extends FrameLayout { + + private static final long DOUBLETAP_TIMEOUT_MS = 1000; + + private boolean mDimmed; + private boolean mLocked; + + /** + * Flag to indicate that the notification has been touched once and the second touch will + * click it. + */ + private boolean mActivated; + + private float mDownX; + private float mDownY; + private final float mTouchSlop; + private boolean mHotspotActive; + public LatestItemView(Context context, AttributeSet attrs) { super(context, attrs); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } + private final Runnable mTapTimeoutRunnable = new Runnable() { + @Override + public void run() { + makeInactive(); + } + }; + @Override public void setOnClickListener(OnClickListener l) { super.setOnClickListener(l); @@ -45,4 +73,94 @@ public class LatestItemView extends FrameLayout { } return false; } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mLocked) { + return handleTouchEventLocked(event); + } else { + return super.onTouchEvent(event); + } + } + + private boolean handleTouchEventLocked(MotionEvent event) { + int action = event.getActionMasked(); + Drawable background = getBackground(); + switch (action) { + case MotionEvent.ACTION_DOWN: + mDownX = event.getX(); + mDownY = event.getY(); + if (!mActivated) { + background.setHotspot(0, event.getX(), event.getY()); + mHotspotActive = true; + } + break; + case MotionEvent.ACTION_MOVE: + if (!isWithinTouchSlop(event)) { + makeInactive(); + return false; + } + break; + case MotionEvent.ACTION_UP: + if (isWithinTouchSlop(event)) { + if (!mActivated) { + mActivated = true; + postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS); + } else { + performClick(); + makeInactive(); + } + } else { + makeInactive(); + } + break; + case MotionEvent.ACTION_CANCEL: + makeInactive(); + break; + default: + break; + } + return true; + } + + /** + * Cancels the hotspot and makes the notification inactive. + */ + private void makeInactive() { + if (mHotspotActive) { + // Make sure that we clear the hotspot from the center. + getBackground().setHotspot(0, getWidth()/2, getHeight()/2); + getBackground().removeHotspot(0); + mHotspotActive = false; + } + mActivated = false; + removeCallbacks(mTapTimeoutRunnable); + } + + private boolean isWithinTouchSlop(MotionEvent event) { + return Math.abs(event.getX() - mDownX) < mTouchSlop + && Math.abs(event.getY() - mDownY) < mTouchSlop; + } + + /** + * Sets the notification as dimmed, meaning that it will appear in a more gray variant. + */ + public void setDimmed(boolean dimmed) { + if (mDimmed != dimmed) { + mDimmed = dimmed; + if (dimmed) { + setBackgroundResource(com.android.internal.R.drawable.notification_quantum_bg_dim); + } else { + setBackgroundResource(com.android.internal.R.drawable.notification_quantum_bg); + } + } + } + + /** + * Sets the notification as locked. In the locked state, the first tap will produce a quantum + * ripple to make the notification brighter and only the second tap will cause a click. + */ + public void setLocked(boolean locked) { + mLocked = locked; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 9b025275ea57b..e34911dcbdeeb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -2804,9 +2804,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } mKeyguardSettingsFlipButton.setVisibility(View.VISIBLE); mKeyguardSettingsFlipButton.findViewById(R.id.settings_button).setVisibility(View.VISIBLE); - mStackScroller.setAlpha(0.8f); - mStackScroller.setLayerType(View.LAYER_TYPE_HARDWARE, null); - updateExpansionStates(); + updateRowStates(); } public void hideKeyguard() { @@ -2815,9 +2813,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mKeyguardStatusView.setVisibility(View.GONE); mNotificationPanelHeader.setVisibility(View.VISIBLE); mKeyguardSettingsFlipButton.setVisibility(View.GONE); - mStackScroller.setAlpha(1f); - mStackScroller.setLayerType(View.LAYER_TYPE_NONE, null); - updateExpansionStates(); + updateRowStates(); } public void userActivity() {