Convert DragDownHelper to Kotlin am: 91579bde59
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14141534 Change-Id: I39041eaf8a96aac6c64d4c485c7d4b3a2fda22f0
This commit is contained in:
@@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 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;
|
|
||||||
|
|
||||||
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
|
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorListenerAdapter;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.animation.ValueAnimator;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewConfiguration;
|
|
||||||
|
|
||||||
import com.android.systemui.ExpandHelper;
|
|
||||||
import com.android.systemui.Gefingerpoken;
|
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
import com.android.systemui.classifier.FalsingCollector;
|
|
||||||
import com.android.systemui.plugins.FalsingManager;
|
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
|
|
||||||
* the notification where the drag started.
|
|
||||||
*/
|
|
||||||
public class DragDownHelper implements Gefingerpoken {
|
|
||||||
|
|
||||||
private static final float RUBBERBAND_FACTOR_EXPANDABLE = 0.5f;
|
|
||||||
private static final float RUBBERBAND_FACTOR_STATIC = 0.15f;
|
|
||||||
|
|
||||||
private static final int SPRING_BACK_ANIMATION_LENGTH_MS = 375;
|
|
||||||
|
|
||||||
private int mMinDragDistance;
|
|
||||||
private final FalsingManager mFalsingManager;
|
|
||||||
private ExpandHelper.Callback mCallback;
|
|
||||||
private float mInitialTouchX;
|
|
||||||
private float mInitialTouchY;
|
|
||||||
private boolean mDraggingDown;
|
|
||||||
private final float mTouchSlop;
|
|
||||||
private final float mSlopMultiplier;
|
|
||||||
private DragDownCallback mDragDownCallback;
|
|
||||||
private View mHost;
|
|
||||||
private final int[] mTemp2 = new int[2];
|
|
||||||
private boolean mDraggedFarEnough;
|
|
||||||
private ExpandableView mStartingChild;
|
|
||||||
private float mLastHeight;
|
|
||||||
private FalsingCollector mFalsingCollector;
|
|
||||||
|
|
||||||
public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
|
|
||||||
DragDownCallback dragDownCallback, FalsingManager falsingManager,
|
|
||||||
FalsingCollector falsingCollector) {
|
|
||||||
mMinDragDistance = context.getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.keyguard_drag_down_min_distance);
|
|
||||||
mFalsingManager = falsingManager;
|
|
||||||
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
|
||||||
mTouchSlop = configuration.getScaledTouchSlop();
|
|
||||||
mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
|
|
||||||
mCallback = callback;
|
|
||||||
mDragDownCallback = dragDownCallback;
|
|
||||||
mHost = host;
|
|
||||||
mFalsingCollector = falsingCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
|
||||||
final float x = event.getX();
|
|
||||||
final float y = event.getY();
|
|
||||||
|
|
||||||
switch (event.getActionMasked()) {
|
|
||||||
case MotionEvent.ACTION_DOWN:
|
|
||||||
mDraggedFarEnough = false;
|
|
||||||
mDraggingDown = false;
|
|
||||||
mStartingChild = null;
|
|
||||||
mInitialTouchY = y;
|
|
||||||
mInitialTouchX = x;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
final float h = y - mInitialTouchY;
|
|
||||||
// Adjust the touch slop if another gesture may be being performed.
|
|
||||||
final float touchSlop =
|
|
||||||
event.getClassification() == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE
|
|
||||||
? mTouchSlop * mSlopMultiplier
|
|
||||||
: mTouchSlop;
|
|
||||||
if (h > touchSlop && h > Math.abs(x - mInitialTouchX)) {
|
|
||||||
mFalsingCollector.onNotificationStartDraggingDown();
|
|
||||||
mDraggingDown = true;
|
|
||||||
captureStartingChild(mInitialTouchX, mInitialTouchY);
|
|
||||||
mInitialTouchY = y;
|
|
||||||
mInitialTouchX = x;
|
|
||||||
mDragDownCallback.onTouchSlopExceeded();
|
|
||||||
return mStartingChild != null || mDragDownCallback.isDragDownAnywhereEnabled();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
|
||||||
if (!mDraggingDown) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final float x = event.getX();
|
|
||||||
final float y = event.getY();
|
|
||||||
|
|
||||||
switch (event.getActionMasked()) {
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
mLastHeight = y - mInitialTouchY;
|
|
||||||
captureStartingChild(mInitialTouchX, mInitialTouchY);
|
|
||||||
if (mStartingChild != null) {
|
|
||||||
handleExpansion(mLastHeight, mStartingChild);
|
|
||||||
} else {
|
|
||||||
mDragDownCallback.setEmptyDragAmount(mLastHeight);
|
|
||||||
}
|
|
||||||
if (mLastHeight > mMinDragDistance) {
|
|
||||||
if (!mDraggedFarEnough) {
|
|
||||||
mDraggedFarEnough = true;
|
|
||||||
mDragDownCallback.onCrossedThreshold(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (mDraggedFarEnough) {
|
|
||||||
mDraggedFarEnough = false;
|
|
||||||
mDragDownCallback.onCrossedThreshold(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case MotionEvent.ACTION_UP:
|
|
||||||
if (!mFalsingManager.isUnlockingDisabled() && mDragDownCallback.canDragDown()
|
|
||||||
&& !isFalseTouch()) {
|
|
||||||
mDragDownCallback.onDraggedDown(mStartingChild, (int) (y - mInitialTouchY));
|
|
||||||
if (mStartingChild == null) {
|
|
||||||
cancelExpansion();
|
|
||||||
} else {
|
|
||||||
mCallback.setUserLockedChild(mStartingChild, false);
|
|
||||||
mStartingChild = null;
|
|
||||||
}
|
|
||||||
mDraggingDown = false;
|
|
||||||
} else {
|
|
||||||
stopDragging();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MotionEvent.ACTION_CANCEL:
|
|
||||||
stopDragging();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isFalseTouch() {
|
|
||||||
if (!mDragDownCallback.isFalsingCheckNeeded()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return mFalsingManager.isFalseTouch(NOTIFICATION_DRAG_DOWN) || !mDraggedFarEnough;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void captureStartingChild(float x, float y) {
|
|
||||||
if (mStartingChild == null) {
|
|
||||||
mStartingChild = findView(x, y);
|
|
||||||
if (mStartingChild != null) {
|
|
||||||
if (mDragDownCallback.isDragDownEnabledForView(mStartingChild)) {
|
|
||||||
mCallback.setUserLockedChild(mStartingChild, true);
|
|
||||||
} else {
|
|
||||||
mStartingChild = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleExpansion(float heightDelta, ExpandableView child) {
|
|
||||||
if (heightDelta < 0) {
|
|
||||||
heightDelta = 0;
|
|
||||||
}
|
|
||||||
boolean expandable = child.isContentExpandable();
|
|
||||||
float rubberbandFactor = expandable
|
|
||||||
? RUBBERBAND_FACTOR_EXPANDABLE
|
|
||||||
: RUBBERBAND_FACTOR_STATIC;
|
|
||||||
float rubberband = heightDelta * rubberbandFactor;
|
|
||||||
if (expandable
|
|
||||||
&& (rubberband + child.getCollapsedHeight()) > child.getMaxContentHeight()) {
|
|
||||||
float overshoot =
|
|
||||||
(rubberband + child.getCollapsedHeight()) - child.getMaxContentHeight();
|
|
||||||
overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
|
|
||||||
rubberband -= overshoot;
|
|
||||||
}
|
|
||||||
child.setActualHeight((int) (child.getCollapsedHeight() + rubberband));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelExpansion(final ExpandableView child) {
|
|
||||||
if (child.getActualHeight() == child.getCollapsedHeight()) {
|
|
||||||
mCallback.setUserLockedChild(child, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
|
|
||||||
child.getActualHeight(), child.getCollapsedHeight());
|
|
||||||
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
|
||||||
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
|
|
||||||
anim.addListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
mCallback.setUserLockedChild(child, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
anim.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelExpansion() {
|
|
||||||
ValueAnimator anim = ValueAnimator.ofFloat(mLastHeight, 0);
|
|
||||||
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
|
||||||
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
|
|
||||||
anim.addUpdateListener(animation -> {
|
|
||||||
mDragDownCallback.setEmptyDragAmount((Float) animation.getAnimatedValue());
|
|
||||||
});
|
|
||||||
anim.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopDragging() {
|
|
||||||
mFalsingCollector.onNotificationStopDraggingDown();
|
|
||||||
if (mStartingChild != null) {
|
|
||||||
cancelExpansion(mStartingChild);
|
|
||||||
mStartingChild = null;
|
|
||||||
} else {
|
|
||||||
cancelExpansion();
|
|
||||||
}
|
|
||||||
mDraggingDown = false;
|
|
||||||
mDragDownCallback.onDragDownReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExpandableView findView(float x, float y) {
|
|
||||||
mHost.getLocationOnScreen(mTemp2);
|
|
||||||
x += mTemp2[0];
|
|
||||||
y += mTemp2[1];
|
|
||||||
return mCallback.getChildAtRawPosition(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDraggingDown() {
|
|
||||||
return mDraggingDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDragDownEnabled() {
|
|
||||||
return mDragDownCallback.isDragDownEnabledForView(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface DragDownCallback {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the interaction is accepted, false if it should be cancelled
|
|
||||||
*/
|
|
||||||
boolean canDragDown();
|
|
||||||
|
|
||||||
/** Call when a view has been dragged. */
|
|
||||||
void onDraggedDown(View startingChild, int dragLengthY);
|
|
||||||
void onDragDownReset();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has dragged either above or below the threshold
|
|
||||||
* @param above whether he dragged above it
|
|
||||||
*/
|
|
||||||
void onCrossedThreshold(boolean above);
|
|
||||||
void onTouchSlopExceeded();
|
|
||||||
void setEmptyDragAmount(float amount);
|
|
||||||
boolean isFalsingCheckNeeded();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is dragging down enabled on a given view
|
|
||||||
* @param view The view to check or {@code null} to check if it's enabled at all
|
|
||||||
*/
|
|
||||||
boolean isDragDownEnabledForView(ExpandableView view);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return if drag down is enabled anywhere, not just on selected views.
|
|
||||||
*/
|
|
||||||
boolean isDragDownAnywhereEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
package com.android.systemui.statusbar
|
||||||
|
|
||||||
|
import android.animation.Animator
|
||||||
|
import android.animation.AnimatorListenerAdapter
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewConfiguration
|
||||||
|
import com.android.systemui.ExpandHelper
|
||||||
|
import com.android.systemui.Gefingerpoken
|
||||||
|
import com.android.systemui.animation.Interpolators
|
||||||
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.classifier.Classifier
|
||||||
|
import com.android.systemui.classifier.FalsingCollector
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.plugins.FalsingManager
|
||||||
|
import com.android.systemui.statusbar.notification.row.ExpandableView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
|
||||||
|
* the notification where the drag started.
|
||||||
|
*/
|
||||||
|
class DragDownHelper(private val falsingManager: FalsingManager,
|
||||||
|
private val expandCallback: ExpandHelper.Callback,
|
||||||
|
private val dragDownCallback: DragDownCallback,
|
||||||
|
private val falsingCollector: FalsingCollector,
|
||||||
|
private val host: View,
|
||||||
|
context: Context): Gefingerpoken {
|
||||||
|
|
||||||
|
private val minDragDistance: Int
|
||||||
|
private var initialTouchX = 0f
|
||||||
|
private var initialTouchY = 0f
|
||||||
|
private val touchSlop: Float
|
||||||
|
private val slopMultiplier: Float
|
||||||
|
private val temp2 = IntArray(2)
|
||||||
|
private var draggedFarEnough = false
|
||||||
|
private var startingChild: ExpandableView? = null
|
||||||
|
private var lastHeight = 0f
|
||||||
|
var isDraggingDown = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
init {
|
||||||
|
minDragDistance = context.resources.getDimensionPixelSize(
|
||||||
|
R.dimen.keyguard_drag_down_min_distance)
|
||||||
|
val configuration = ViewConfiguration.get(context)
|
||||||
|
touchSlop = configuration.scaledTouchSlop.toFloat()
|
||||||
|
slopMultiplier = configuration.scaledAmbiguousGestureMultiplier
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
val x = event.x
|
||||||
|
val y = event.y
|
||||||
|
when (event.actionMasked) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
draggedFarEnough = false
|
||||||
|
isDraggingDown = false
|
||||||
|
startingChild = null
|
||||||
|
initialTouchY = y
|
||||||
|
initialTouchX = x
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
val h = y - initialTouchY
|
||||||
|
// Adjust the touch slop if another gesture may be being performed.
|
||||||
|
val touchSlop = if (event.classification
|
||||||
|
== MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE)
|
||||||
|
touchSlop * slopMultiplier
|
||||||
|
else
|
||||||
|
touchSlop
|
||||||
|
if (h > touchSlop && h > Math.abs(x - initialTouchX)) {
|
||||||
|
falsingCollector.onNotificationStartDraggingDown()
|
||||||
|
isDraggingDown = true
|
||||||
|
captureStartingChild(initialTouchX, initialTouchY)
|
||||||
|
initialTouchY = y
|
||||||
|
initialTouchX = x
|
||||||
|
dragDownCallback.onTouchSlopExceeded()
|
||||||
|
return startingChild != null || dragDownCallback.isDragDownAnywhereEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
if (!isDraggingDown) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val x = event.x
|
||||||
|
val y = event.y
|
||||||
|
when (event.actionMasked) {
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
lastHeight = y - initialTouchY
|
||||||
|
captureStartingChild(initialTouchX, initialTouchY)
|
||||||
|
if (startingChild != null) {
|
||||||
|
handleExpansion(lastHeight, startingChild!!)
|
||||||
|
} else {
|
||||||
|
dragDownCallback.setEmptyDragAmount(lastHeight)
|
||||||
|
}
|
||||||
|
if (lastHeight > minDragDistance) {
|
||||||
|
if (!draggedFarEnough) {
|
||||||
|
draggedFarEnough = true
|
||||||
|
dragDownCallback.onCrossedThreshold(true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (draggedFarEnough) {
|
||||||
|
draggedFarEnough = false
|
||||||
|
dragDownCallback.onCrossedThreshold(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_UP -> if (!falsingManager.isUnlockingDisabled && !isFalseTouch
|
||||||
|
&& dragDownCallback.canDragDown()) {
|
||||||
|
dragDownCallback.onDraggedDown(startingChild, (y - initialTouchY).toInt())
|
||||||
|
if (startingChild == null) {
|
||||||
|
cancelExpansion()
|
||||||
|
} else {
|
||||||
|
expandCallback.setUserLockedChild(startingChild, false)
|
||||||
|
startingChild = null
|
||||||
|
}
|
||||||
|
isDraggingDown = false
|
||||||
|
} else {
|
||||||
|
stopDragging()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_CANCEL -> {
|
||||||
|
stopDragging()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private val isFalseTouch: Boolean
|
||||||
|
get() {
|
||||||
|
return if (!dragDownCallback.isFalsingCheckNeeded) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
falsingManager.isFalseTouch(Classifier.NOTIFICATION_DRAG_DOWN) || !draggedFarEnough
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun captureStartingChild(x: Float, y: Float) {
|
||||||
|
if (startingChild == null) {
|
||||||
|
startingChild = findView(x, y)
|
||||||
|
if (startingChild != null) {
|
||||||
|
if (dragDownCallback.isDragDownEnabledForView(startingChild)) {
|
||||||
|
expandCallback.setUserLockedChild(startingChild, true)
|
||||||
|
} else {
|
||||||
|
startingChild = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleExpansion(heightDelta: Float, child: ExpandableView) {
|
||||||
|
var hDelta = heightDelta
|
||||||
|
if (hDelta < 0) {
|
||||||
|
hDelta = 0f
|
||||||
|
}
|
||||||
|
val expandable = child.isContentExpandable
|
||||||
|
val rubberbandFactor = if (expandable) {
|
||||||
|
RUBBERBAND_FACTOR_EXPANDABLE
|
||||||
|
} else {
|
||||||
|
RUBBERBAND_FACTOR_STATIC
|
||||||
|
}
|
||||||
|
var rubberband = hDelta * rubberbandFactor
|
||||||
|
if (expandable && rubberband + child.collapsedHeight > child.maxContentHeight) {
|
||||||
|
var overshoot = rubberband + child.collapsedHeight - child.maxContentHeight
|
||||||
|
overshoot *= 1 - RUBBERBAND_FACTOR_STATIC
|
||||||
|
rubberband -= overshoot
|
||||||
|
}
|
||||||
|
child.actualHeight = (child.collapsedHeight + rubberband).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelExpansion(child: ExpandableView) {
|
||||||
|
if (child.actualHeight == child.collapsedHeight) {
|
||||||
|
expandCallback.setUserLockedChild(child, false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val anim = ObjectAnimator.ofInt(child, "actualHeight",
|
||||||
|
child.actualHeight, child.collapsedHeight)
|
||||||
|
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||||
|
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
|
||||||
|
anim.addListener(object : AnimatorListenerAdapter() {
|
||||||
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
|
expandCallback.setUserLockedChild(child, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
anim.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelExpansion() {
|
||||||
|
val anim = ValueAnimator.ofFloat(lastHeight, 0f)
|
||||||
|
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||||
|
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
|
||||||
|
anim.addUpdateListener { animation: ValueAnimator ->
|
||||||
|
dragDownCallback.setEmptyDragAmount(animation.animatedValue as Float)
|
||||||
|
}
|
||||||
|
anim.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopDragging() {
|
||||||
|
falsingCollector.onNotificationStopDraggingDown()
|
||||||
|
if (startingChild != null) {
|
||||||
|
cancelExpansion(startingChild!!)
|
||||||
|
startingChild = null
|
||||||
|
} else {
|
||||||
|
cancelExpansion()
|
||||||
|
}
|
||||||
|
isDraggingDown = false
|
||||||
|
dragDownCallback.onDragDownReset()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findView(x: Float, y: Float): ExpandableView {
|
||||||
|
host.getLocationOnScreen(temp2)
|
||||||
|
return expandCallback.getChildAtRawPosition(x + temp2[0] , y + temp2[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
val isDragDownEnabled: Boolean
|
||||||
|
get() = dragDownCallback.isDragDownEnabledForView(null)
|
||||||
|
|
||||||
|
interface DragDownCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the interaction is accepted, false if it should be cancelled
|
||||||
|
*/
|
||||||
|
fun canDragDown(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call when a view has been dragged.
|
||||||
|
**/
|
||||||
|
fun onDraggedDown(startingChild: View?, dragLengthY: Int)
|
||||||
|
fun onDragDownReset()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has dragged either above or below the threshold
|
||||||
|
* @param above whether they dragged above it
|
||||||
|
*/
|
||||||
|
fun onCrossedThreshold(above: Boolean)
|
||||||
|
fun onTouchSlopExceeded()
|
||||||
|
fun setEmptyDragAmount(amount: Float)
|
||||||
|
val isFalsingCheckNeeded: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is dragging down enabled on a given view
|
||||||
|
* @param view The view to check or `null` to check if it's enabled at all
|
||||||
|
*/
|
||||||
|
fun isDragDownEnabledForView(view: ExpandableView?): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if drag down is enabled anywhere, not just on selected views.
|
||||||
|
*/
|
||||||
|
val isDragDownAnywhereEnabled: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val RUBBERBAND_FACTOR_EXPANDABLE = 0.5f
|
||||||
|
private const val RUBBERBAND_FACTOR_STATIC = 0.15f
|
||||||
|
private const val SPRING_BACK_ANIMATION_LENGTH_MS = 375
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -409,9 +409,8 @@ public class NotificationShadeWindowViewController {
|
|||||||
ExpandHelper.Callback expandHelperCallback = mStackScrollLayout.getExpandHelperCallback();
|
ExpandHelper.Callback expandHelperCallback = mStackScrollLayout.getExpandHelperCallback();
|
||||||
DragDownHelper.DragDownCallback dragDownCallback = mStackScrollLayout.getDragDownCallback();
|
DragDownHelper.DragDownCallback dragDownCallback = mStackScrollLayout.getDragDownCallback();
|
||||||
setDragDownHelper(
|
setDragDownHelper(
|
||||||
new DragDownHelper(
|
new DragDownHelper(mFalsingManager, expandHelperCallback, dragDownCallback,
|
||||||
mView.getContext(), mView, expandHelperCallback,
|
mFalsingCollector, mView, mView.getContext()));
|
||||||
dragDownCallback, mFalsingManager, mFalsingCollector));
|
|
||||||
|
|
||||||
mDepthController.setRoot(mView);
|
mDepthController.setRoot(mView);
|
||||||
mNotificationPanelViewController.addExpansionListener(mDepthController);
|
mNotificationPanelViewController.addExpansionListener(mDepthController);
|
||||||
|
|||||||
Reference in New Issue
Block a user