summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Adrian Roos <roosa@google.com> 2017-02-21 21:38:12 +0100
committer Adrian Roos <roosa@google.com> 2017-02-22 11:15:14 +0100
commit28a0de9c5ee66a90e35f9e2d0e5ab0af8676546b (patch)
treeeb0cd3658e7baf964c0c232865813491fa2a5c82
parentc98c16ded8738054242b2576a74e145f834b6efa (diff)
Shade: Factor out DoubleTapHelper
Factors DoubleTapHelper out of ActivatableNotificationView, such that the same logic can be reused for the StatusBarWindowView. Bug: 30876804 Test: have a notification, lock phone, interact with notifications on the lockscreen Change-Id: I4f3a43859d81677d5168424874b106bbfdea0be5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java174
2 files changed, 185 insertions, 81 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 0bd649121321..98787f7c6ec0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -38,6 +38,7 @@ import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.phone.DoubleTapHelper;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -47,7 +48,6 @@ import com.android.systemui.statusbar.stack.StackStateAnimator;
*/
public abstract class ActivatableNotificationView extends ExpandableOutlineView {
- private static final long DOUBLETAP_TIMEOUT_MS = 1200;
private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220;
private static final int ACTIVATE_ANIMATION_LENGTH = 220;
private static final int DARK_ANIMATION_LENGTH = 170;
@@ -101,6 +101,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private final int mLowPriorityRippleColor;
protected final int mNormalRippleColor;
private final AccessibilityManager mAccessibilityManager;
+ private final DoubleTapHelper mDoubleTapHelper;
private boolean mDimmed;
private boolean mDark;
@@ -114,14 +115,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
*/
private boolean mActivated;
- private float mDownX;
- private float mDownY;
- private final float mTouchSlop;
-
- private float mActivationX;
- private float mActivationY;
- private final float mDoubleTapSlop;
-
private OnActivatedListener mOnActivatedListener;
private final Interpolator mSlowOutFastInInterpolator;
@@ -143,7 +136,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private final int mLowPriorityColor;
private boolean mIsBelowSpeedBump;
private FalsingManager mFalsingManager;
- private boolean mTrackTouch;
private float mNormalBackgroundVisibilityAmount;
private ValueAnimator mFadeInFromDarkAnimator;
@@ -183,8 +175,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
- mDoubleTapSlop = context.getResources().getDimension(R.dimen.double_tap_slop);
mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
setClipChildren(false);
@@ -200,6 +190,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
R.color.notification_ripple_untinted_color);
mFalsingManager = FalsingManager.getInstance(context);
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
+
+ mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
+ if (active) {
+ makeActive();
+ } else {
+ makeInactive(true /* animate */);
+ }
+ }, this::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
}
@Override
@@ -284,60 +282,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
private boolean handleTouchEventDimmed(MotionEvent event) {
- int action = event.getActionMasked();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mDownX = event.getX();
- mDownY = event.getY();
- mTrackTouch = true;
- if (mDownY > getActualHeight()) {
- mTrackTouch = false;
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (!isWithinTouchSlop(event)) {
- makeInactive(true /* animate */);
- mTrackTouch = false;
- }
- break;
- case MotionEvent.ACTION_UP:
- if (isWithinTouchSlop(event)) {
- if (handleSlideBack()) {
- return true;
- }
- if (!mActivated) {
- makeActive();
- postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
- mActivationX = event.getX();
- mActivationY = event.getY();
- } else {
- boolean withinDoubleTapSlop = isWithinDoubleTapSlop(event);
- mFalsingManager.onNotificationDoubleTap(
- withinDoubleTapSlop,
- event.getX() - mActivationX,
- event.getY() - mActivationY);
- if (withinDoubleTapSlop) {
- if (!performClick()) {
- return false;
- }
- } else {
- makeInactive(true /* animate */);
- mTrackTouch = false;
- }
- }
- } else {
- makeInactive(true /* animate */);
- mTrackTouch = false;
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- makeInactive(true /* animate */);
- mTrackTouch = false;
- break;
- default:
- break;
- }
- return mTrackTouch;
+ return mDoubleTapHelper.onTouchEvent(event, getActualHeight());
}
private void makeActive() {
@@ -425,21 +370,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
removeCallbacks(mTapTimeoutRunnable);
}
- private boolean isWithinTouchSlop(MotionEvent event) {
- return Math.abs(event.getX() - mDownX) < mTouchSlop
- && Math.abs(event.getY() - mDownY) < mTouchSlop;
- }
-
- private boolean isWithinDoubleTapSlop(MotionEvent event) {
- if (!mActivated) {
- // If we're not activated there's no double tap slop to satisfy.
- return true;
- }
-
- return Math.abs(event.getX() - mActivationX) < mDoubleTapSlop
- && Math.abs(event.getY() - mActivationY) < mDoubleTapSlop;
- }
-
public void setDimmed(boolean dimmed, boolean fade) {
if (mDimmed != dimmed) {
mDimmed = dimmed;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
new file mode 100644
index 000000000000..dcb6a3801844
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2017 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.systemui.statusbar.phone;
+
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import com.android.systemui.R;
+
+/**
+ * Detects a double tap.
+ */
+public class DoubleTapHelper {
+
+ private static final long DOUBLETAP_TIMEOUT_MS = 1200;
+
+ private final View mView;
+ private final ActivationListener mActivationListener;
+ private final DoubleTapListener mDoubleTapListener;
+ private final SlideBackListener mSlideBackListener;
+ private final DoubleTapLogListener mDoubleTapLogListener;
+
+ private float mTouchSlop;
+ private float mDoubleTapSlop;
+
+ private boolean mActivated;
+
+ private float mDownX;
+ private float mDownY;
+ private boolean mTrackTouch;
+
+ private float mActivationX;
+ private float mActivationY;
+ private Runnable mTapTimeoutRunnable = this::makeInactive;
+
+ public DoubleTapHelper(View view, ActivationListener activationListener,
+ DoubleTapListener doubleTapListener, SlideBackListener slideBackListener,
+ DoubleTapLogListener doubleTapLogListener) {
+ mTouchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
+ mDoubleTapSlop = view.getResources().getDimension(R.dimen.double_tap_slop);
+ mView = view;
+
+ mActivationListener = activationListener;
+ mDoubleTapListener = doubleTapListener;
+ mSlideBackListener = slideBackListener;
+ mDoubleTapLogListener = doubleTapLogListener;
+ }
+
+ public boolean onTouchEvent(MotionEvent event) {
+ return onTouchEvent(event, Integer.MAX_VALUE);
+ }
+
+ public boolean onTouchEvent(MotionEvent event, int maxTouchableHeight) {
+ int action = event.getActionMasked();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mDownX = event.getX();
+ mDownY = event.getY();
+ mTrackTouch = true;
+ if (mDownY > maxTouchableHeight) {
+ mTrackTouch = false;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (!isWithinTouchSlop(event)) {
+ makeInactive();
+ mTrackTouch = false;
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (isWithinTouchSlop(event)) {
+ if (mSlideBackListener != null && mSlideBackListener.onSlideBack()) {
+ return true;
+ }
+ if (!mActivated) {
+ makeActive();
+ mView.postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
+ mActivationX = event.getX();
+ mActivationY = event.getY();
+ } else {
+ boolean withinDoubleTapSlop = isWithinDoubleTapSlop(event);
+ if (mDoubleTapLogListener != null) {
+ mDoubleTapLogListener.onDoubleTapLog(withinDoubleTapSlop,
+ event.getX() - mActivationX,
+ event.getY() - mActivationY);
+ }
+ if (withinDoubleTapSlop) {
+ if (!mDoubleTapListener.onDoubleTap()) {
+ return false;
+ }
+ } else {
+ makeInactive();
+ mTrackTouch = false;
+ }
+ }
+ } else {
+ makeInactive();
+ mTrackTouch = false;
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ makeInactive();
+ mTrackTouch = false;
+ break;
+ default:
+ break;
+ }
+ return mTrackTouch;
+ }
+
+ private void makeActive() {
+ if (!mActivated) {
+ mActivated = true;
+ mActivationListener.onActiveChanged(true);
+ }
+ }
+
+ private void makeInactive() {
+ if (mActivated) {
+ mActivated = false;
+ mActivationListener.onActiveChanged(false);
+ }
+ }
+
+ private boolean isWithinTouchSlop(MotionEvent event) {
+ return Math.abs(event.getX() - mDownX) < mTouchSlop
+ && Math.abs(event.getY() - mDownY) < mTouchSlop;
+ }
+
+ private boolean isWithinDoubleTapSlop(MotionEvent event) {
+ if (!mActivated) {
+ // If we're not activated there's no double tap slop to satisfy.
+ return true;
+ }
+
+ return Math.abs(event.getX() - mActivationX) < mDoubleTapSlop
+ && Math.abs(event.getY() - mActivationY) < mDoubleTapSlop;
+ }
+
+ @FunctionalInterface
+ public interface ActivationListener {
+ void onActiveChanged(boolean active);
+ }
+
+ @FunctionalInterface
+ public interface DoubleTapListener {
+ boolean onDoubleTap();
+ }
+
+ @FunctionalInterface
+ public interface SlideBackListener {
+ boolean onSlideBack();
+ }
+
+ @FunctionalInterface
+ public interface DoubleTapLogListener {
+ void onDoubleTapLog(boolean accepted, float dx, float dy);
+ }
+}