Merge "Shade: Factor out DoubleTapHelper"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a1d548024d
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user