Remove FEATURE_SWIPE_TO_DISMISS functionality

Not used anymore by any product.

Bug: 143346248
Test: Boots
Change-Id: I21286e62f73ec34f7d5ca040cd614838c9cd4276
This commit is contained in:
Jorim Jaggi
2019-10-25 14:35:10 +02:00
parent 5a89f1a030
commit e06b1fd0f5
11 changed files with 11 additions and 666 deletions

View File

@@ -1609,7 +1609,7 @@ package android {
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
field public static final int windowSplashscreenContent = 16844132; // 0x1010564
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field @Deprecated public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
field public static final int windowTitleStyle = 16842843; // 0x101005b
@@ -51976,7 +51976,7 @@ package android.view {
field public static final int FEATURE_OPTIONS_PANEL = 0; // 0x0
field @Deprecated public static final int FEATURE_PROGRESS = 2; // 0x2
field public static final int FEATURE_RIGHT_ICON = 4; // 0x4
field public static final int FEATURE_SWIPE_TO_DISMISS = 11; // 0xb
field @Deprecated public static final int FEATURE_SWIPE_TO_DISMISS = 11; // 0xb
field public static final int ID_ANDROID_CONTENT = 16908290; // 0x1020002
field public static final String NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME = "android:navigation:background";
field @Deprecated public static final int PROGRESS_END = 10000; // 0x2710

View File

@@ -219,7 +219,6 @@ public class Dialog implements DialogInterface, Window.Callback,
@Nullable Message cancelCallback) {
this(context);
mCancelable = cancelable;
updateWindowForCancelable();
mCancelMessage = cancelCallback;
}
@@ -227,7 +226,6 @@ public class Dialog implements DialogInterface, Window.Callback,
@Nullable OnCancelListener cancelListener) {
this(context);
mCancelable = cancelable;
updateWindowForCancelable();
setOnCancelListener(cancelListener);
}
@@ -1249,7 +1247,6 @@ public class Dialog implements DialogInterface, Window.Callback,
*/
public void setCancelable(boolean flag) {
mCancelable = flag;
updateWindowForCancelable();
}
/**
@@ -1263,7 +1260,6 @@ public class Dialog implements DialogInterface, Window.Callback,
public void setCanceledOnTouchOutside(boolean cancel) {
if (cancel && !mCancelable) {
mCancelable = true;
updateWindowForCancelable();
}
mWindow.setCloseOnTouchOutside(cancel);
@@ -1415,8 +1411,4 @@ public class Dialog implements DialogInterface, Window.Callback,
}
}
}
private void updateWindowForCancelable() {
mWindow.setCloseOnSwipeEnabled(mCancelable);
}
}

View File

@@ -1242,15 +1242,11 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
final boolean isTranslucent =
attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent,
false);
final boolean isSwipeToDismiss = !attributes.hasValue(
com.android.internal.R.styleable.Window_windowIsTranslucent)
&& attributes.getBoolean(
com.android.internal.R.styleable.Window_windowSwipeToDismiss, false);
final boolean isFloating =
attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating,
false);
return isFloating || isTranslucent || isSwipeToDismiss;
return isFloating || isTranslucent;
}
/**

View File

@@ -127,7 +127,10 @@ public abstract class Window {
public static final int FEATURE_ACTION_MODE_OVERLAY = 10;
/**
* Flag for requesting a decoration-free window that is dismissed by swiping from the left.
*
* @deprecated Swipe-to-dismiss isn't functional anymore.
*/
@Deprecated
public static final int FEATURE_SWIPE_TO_DISMISS = 11;
/**
* Flag for requesting that window content changes should be animated using a
@@ -2511,23 +2514,6 @@ public abstract class Window {
*/
public abstract void reportActivityRelaunched();
/**
* Called to set flag to check if the close on swipe is enabled. This will only function if
* FEATURE_SWIPE_TO_DISMISS has been set.
* @hide
*/
public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
mCloseOnSwipeEnabled = closeOnSwipeEnabled;
}
/**
* @return {@code true} if the close on swipe is enabled.
* @hide
*/
public boolean isCloseOnSwipeEnabled() {
return mCloseOnSwipeEnabled;
}
/**
* @return The {@link WindowInsetsController} associated with this window
* @see View#getWindowInsetsController()

View File

@@ -24,7 +24,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
@@ -112,7 +111,6 @@ import com.android.internal.view.menu.MenuHelper;
import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.MenuView;
import com.android.internal.widget.DecorContentParent;
import com.android.internal.widget.SwipeDismissLayout;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -378,15 +376,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
removeFeature(FEATURE_ACTION_BAR);
}
if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_SWIPE_TO_DISMISS) {
throw new AndroidRuntimeException(
"You cannot combine swipe dismissal and the action bar.");
}
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0 && featureId == FEATURE_ACTION_BAR) {
throw new AndroidRuntimeException(
"You cannot combine swipe dismissal and the action bar.");
}
if (featureId == FEATURE_INDETERMINATE_PROGRESS &&
getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
throw new AndroidRuntimeException("You cannot use indeterminate progress on a watch.");
@@ -2373,10 +2362,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
requestFeature(FEATURE_ACTION_MODE_OVERLAY);
}
if (a.getBoolean(R.styleable.Window_windowSwipeToDismiss, false)) {
requestFeature(FEATURE_SWIPE_TO_DISMISS);
}
if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
}
@@ -2565,10 +2550,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
setCloseOnSwipeEnabled(true);
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
@@ -2638,10 +2620,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
registerSwipeCallbacks(contentParent);
}
// Remaining setup -- of background and title -- that only applies
// to top-level windows.
if (getContainer() == null) {
@@ -3047,63 +3025,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return (mRightIconView = (ImageView)findViewById(R.id.right_icon));
}
private void registerSwipeCallbacks(ViewGroup contentParent) {
if (!(contentParent instanceof SwipeDismissLayout)) {
Log.w(TAG, "contentParent is not a SwipeDismissLayout: " + contentParent);
return;
}
SwipeDismissLayout swipeDismiss = (SwipeDismissLayout) contentParent;
swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
@Override
public void onDismissed(SwipeDismissLayout layout) {
dispatchOnWindowSwipeDismissed();
dispatchOnWindowDismissed(false /*finishTask*/, true /*suppressWindowTransition*/);
}
});
swipeDismiss.setOnSwipeProgressChangedListener(
new SwipeDismissLayout.OnSwipeProgressChangedListener() {
@Override
public void onSwipeProgressChanged(
SwipeDismissLayout layout, float alpha, float translate) {
WindowManager.LayoutParams newParams = getAttributes();
newParams.x = (int) translate;
newParams.alpha = alpha;
setAttributes(newParams);
int flags = 0;
if (newParams.x == 0) {
flags = FLAG_FULLSCREEN;
} else {
flags = FLAG_LAYOUT_NO_LIMITS;
}
setFlags(flags, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
}
@Override
public void onSwipeCancelled(SwipeDismissLayout layout) {
WindowManager.LayoutParams newParams = getAttributes();
// Swipe changes only affect the x-translation and alpha, check to see if
// those values have changed first before resetting them.
if (newParams.x != 0 || newParams.alpha != 1) {
newParams.x = 0;
newParams.alpha = 1;
setAttributes(newParams);
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
}
}
});
}
/** @hide */
@Override
public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
if (hasFeature(Window.FEATURE_SWIPE_TO_DISMISS) // swipe-to-dismiss feature is requested
&& mContentParent instanceof SwipeDismissLayout) { // check casting mContentParent
((SwipeDismissLayout) mContentParent).setDismissable(closeOnSwipeEnabled);
}
super.setCloseOnSwipeEnabled(closeOnSwipeEnabled);
}
/**
* Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
* callback. This method will grab whatever extra state is needed for the

View File

@@ -1,516 +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.internal.widget;
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ReceiverCallNotAllowedException;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
/**
* Special layout that finishes its activity when swiped away.
*/
public class SwipeDismissLayout extends FrameLayout {
private static final String TAG = "SwipeDismissLayout";
private static final float MAX_DIST_THRESHOLD = .33f;
private static final float MIN_DIST_THRESHOLD = .1f;
public interface OnDismissedListener {
void onDismissed(SwipeDismissLayout layout);
}
public interface OnSwipeProgressChangedListener {
/**
* Called when the layout has been swiped and the position of the window should change.
*
* @param alpha A number in [0, 1] representing what the alpha transparency of the window
* should be.
* @param translate A number in [0, w], where w is the width of the
* layout. This is equivalent to progress * layout.getWidth().
*/
void onSwipeProgressChanged(SwipeDismissLayout layout, float alpha, float translate);
void onSwipeCancelled(SwipeDismissLayout layout);
}
private boolean mIsWindowNativelyTranslucent;
// Cached ViewConfiguration and system-wide constant values
private int mSlop;
private int mMinFlingVelocity;
// Transient properties
private int mActiveTouchId;
private float mDownX;
private float mDownY;
private float mLastX;
private boolean mSwiping;
private boolean mDismissed;
private boolean mDiscardIntercept;
private VelocityTracker mVelocityTracker;
private boolean mBlockGesture = false;
private boolean mActivityTranslucencyConverted = false;
private final DismissAnimator mDismissAnimator = new DismissAnimator();
private OnDismissedListener mDismissedListener;
private OnSwipeProgressChangedListener mProgressListener;
private BroadcastReceiver mScreenOffReceiver;
private IntentFilter mScreenOffFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
private boolean mDismissable = true;
public SwipeDismissLayout(Context context) {
super(context);
init(context);
}
public SwipeDismissLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SwipeDismissLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
ViewConfiguration vc = ViewConfiguration.get(context);
mSlop = vc.getScaledTouchSlop();
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
TypedArray a = context.getTheme().obtainStyledAttributes(
com.android.internal.R.styleable.Theme);
mIsWindowNativelyTranslucent = a.getBoolean(
com.android.internal.R.styleable.Window_windowIsTranslucent, false);
a.recycle();
}
public void setOnDismissedListener(OnDismissedListener listener) {
mDismissedListener = listener;
}
public void setOnSwipeProgressChangedListener(OnSwipeProgressChangedListener listener) {
mProgressListener = listener;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
try {
mScreenOffReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
post(() -> {
if (mDismissed) {
dismiss();
} else {
cancel();
}
resetMembers();
});
}
};
getContext().registerReceiver(mScreenOffReceiver, mScreenOffFilter);
} catch (ReceiverCallNotAllowedException e) {
/* Exception is thrown if the context is a ReceiverRestrictedContext object. As
* ReceiverRestrictedContext is not public, the context type cannot be checked before
* calling registerReceiver. The most likely scenario in which the exception would be
* thrown would be when a BroadcastReceiver creates a dialog to show the user. */
mScreenOffReceiver = null; // clear receiver since it was not used.
}
}
@Override
protected void onDetachedFromWindow() {
if (mScreenOffReceiver != null) {
getContext().unregisterReceiver(mScreenOffReceiver);
mScreenOffReceiver = null;
}
super.onDetachedFromWindow();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
checkGesture((ev));
if (mBlockGesture) {
return true;
}
if (!mDismissable) {
return super.onInterceptTouchEvent(ev);
}
// Offset because the view is translated during swipe, match X with raw X. Active touch
// coordinates are mostly used by the velocity tracker, so offset it to match the raw
// coordinates which is what is primarily used elsewhere.
ev.offsetLocation(ev.getRawX() - ev.getX(), 0);
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
resetMembers();
mDownX = ev.getRawX();
mDownY = ev.getRawY();
mActiveTouchId = ev.getPointerId(0);
mVelocityTracker = VelocityTracker.obtain("int1");
mVelocityTracker.addMovement(ev);
break;
case MotionEvent.ACTION_POINTER_DOWN:
int actionIndex = ev.getActionIndex();
mActiveTouchId = ev.getPointerId(actionIndex);
break;
case MotionEvent.ACTION_POINTER_UP:
actionIndex = ev.getActionIndex();
int pointerId = ev.getPointerId(actionIndex);
if (pointerId == mActiveTouchId) {
// This was our active pointer going up. Choose a new active pointer.
int newActionIndex = actionIndex == 0 ? 1 : 0;
mActiveTouchId = ev.getPointerId(newActionIndex);
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
resetMembers();
break;
case MotionEvent.ACTION_MOVE:
if (mVelocityTracker == null || mDiscardIntercept) {
break;
}
int pointerIndex = ev.findPointerIndex(mActiveTouchId);
if (pointerIndex == -1) {
Log.e(TAG, "Invalid pointer index: ignoring.");
mDiscardIntercept = true;
break;
}
float dx = ev.getRawX() - mDownX;
float x = ev.getX(pointerIndex);
float y = ev.getY(pointerIndex);
if (dx != 0 && canScroll(this, false, dx, x, y)) {
mDiscardIntercept = true;
break;
}
updateSwiping(ev);
break;
}
return !mDiscardIntercept && mSwiping;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
checkGesture((ev));
if (mBlockGesture) {
return true;
}
if (mVelocityTracker == null || !mDismissable) {
return super.onTouchEvent(ev);
}
// Offset because the view is translated during swipe, match X with raw X. Active touch
// coordinates are mostly used by the velocity tracker, so offset it to match the raw
// coordinates which is what is primarily used elsewhere.
ev.offsetLocation(ev.getRawX() - ev.getX(), 0);
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_UP:
updateDismiss(ev);
if (mDismissed) {
mDismissAnimator.animateDismissal(ev.getRawX() - mDownX);
} else if (mSwiping
// Only trigger animation if we had a MOVE event that would shift the
// underlying view, otherwise the animation would be janky.
&& mLastX != Integer.MIN_VALUE) {
mDismissAnimator.animateRecovery(ev.getRawX() - mDownX);
}
resetMembers();
break;
case MotionEvent.ACTION_CANCEL:
cancel();
resetMembers();
break;
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(ev);
mLastX = ev.getRawX();
updateSwiping(ev);
if (mSwiping) {
setProgress(ev.getRawX() - mDownX);
break;
}
}
return true;
}
private void setProgress(float deltaX) {
if (mProgressListener != null && deltaX >= 0) {
mProgressListener.onSwipeProgressChanged(
this, progressToAlpha(deltaX / getWidth()), deltaX);
}
}
private void dismiss() {
if (mDismissedListener != null) {
mDismissedListener.onDismissed(this);
}
}
protected void cancel() {
if (!mIsWindowNativelyTranslucent) {
Activity activity = findActivity();
if (activity != null && mActivityTranslucencyConverted) {
activity.convertFromTranslucent();
mActivityTranslucencyConverted = false;
}
}
if (mProgressListener != null) {
mProgressListener.onSwipeCancelled(this);
}
}
/**
* Resets internal members when canceling.
*/
private void resetMembers() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
}
mVelocityTracker = null;
mDownX = 0;
mLastX = Integer.MIN_VALUE;
mDownY = 0;
mSwiping = false;
mDismissed = false;
mDiscardIntercept = false;
}
private void updateSwiping(MotionEvent ev) {
boolean oldSwiping = mSwiping;
if (!mSwiping) {
float deltaX = ev.getRawX() - mDownX;
float deltaY = ev.getRawY() - mDownY;
if ((deltaX * deltaX) + (deltaY * deltaY) > mSlop * mSlop) {
mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < Math.abs(deltaX);
} else {
mSwiping = false;
}
}
if (mSwiping && !oldSwiping) {
// Swiping has started
if (!mIsWindowNativelyTranslucent) {
Activity activity = findActivity();
if (activity != null) {
mActivityTranslucencyConverted = activity.convertToTranslucent(null, null);
}
}
}
}
private void updateDismiss(MotionEvent ev) {
float deltaX = ev.getRawX() - mDownX;
// Don't add the motion event as an UP event would clear the velocity tracker
mVelocityTracker.computeCurrentVelocity(1000);
float xVelocity = mVelocityTracker.getXVelocity();
if (mLastX == Integer.MIN_VALUE) {
// If there's no changes to mLastX, we have only one point of data, and therefore no
// velocity. Estimate velocity from just the up and down event in that case.
xVelocity = deltaX / ((ev.getEventTime() - ev.getDownTime()) / 1000);
}
if (!mDismissed) {
// Adjust the distance threshold linearly between the min and max threshold based on the
// x-velocity scaled with the the fling threshold speed
float distanceThreshold = getWidth() * Math.max(
Math.min((MIN_DIST_THRESHOLD - MAX_DIST_THRESHOLD)
* xVelocity / mMinFlingVelocity // scale x-velocity with fling velocity
+ MAX_DIST_THRESHOLD, // offset to start at max threshold
MAX_DIST_THRESHOLD), // cap at max threshold
MIN_DIST_THRESHOLD); // bottom out at min threshold
if ((deltaX > distanceThreshold && ev.getRawX() >= mLastX)
|| xVelocity >= mMinFlingVelocity) {
mDismissed = true;
}
}
// Check if the user tried to undo this.
if (mDismissed && mSwiping) {
// Check if the user's finger is actually flinging back to left
if (xVelocity < -mMinFlingVelocity) {
mDismissed = false;
}
}
}
/**
* Tests scrollability within child views of v in the direction of dx.
*
* @param v View to test for horizontal scrollability
* @param checkV Whether the view v passed should itself be checked for scrollability (true),
* or just its children (false).
* @param dx Delta scrolled in pixels. Only the sign of this is used.
* @param x X coordinate of the active touch point
* @param y Y coordinate of the active touch point
* @return true if child views of v can be scrolled by delta of dx.
*/
protected boolean canScroll(View v, boolean checkV, float dx, float x, float y) {
if (v instanceof ViewGroup) {
final ViewGroup group = (ViewGroup) v;
final int scrollX = v.getScrollX();
final int scrollY = v.getScrollY();
final int count = group.getChildCount();
for (int i = count - 1; i >= 0; i--) {
final View child = group.getChildAt(i);
if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
canScroll(child, true, dx, x + scrollX - child.getLeft(),
y + scrollY - child.getTop())) {
return true;
}
}
}
return checkV && v.canScrollHorizontally((int) -dx);
}
public void setDismissable(boolean dismissable) {
if (!dismissable && mDismissable) {
cancel();
resetMembers();
}
mDismissable = dismissable;
}
private void checkGesture(MotionEvent ev) {
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
mBlockGesture = mDismissAnimator.isAnimating();
}
}
private float progressToAlpha(float progress) {
return 1 - progress * progress * progress;
}
private Activity findActivity() {
Context context = getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
return null;
}
private class DismissAnimator implements AnimatorUpdateListener, Animator.AnimatorListener {
private final TimeInterpolator DISMISS_INTERPOLATOR = new DecelerateInterpolator(1.5f);
private final long DISMISS_DURATION = 250;
private final ValueAnimator mDismissAnimator = new ValueAnimator();
private boolean mWasCanceled = false;
private boolean mDismissOnComplete = false;
/* package */ DismissAnimator() {
mDismissAnimator.addUpdateListener(this);
mDismissAnimator.addListener(this);
}
/* package */ void animateDismissal(float currentTranslation) {
animate(
currentTranslation / getWidth(),
1,
DISMISS_DURATION,
DISMISS_INTERPOLATOR,
true /* dismiss */);
}
/* package */ void animateRecovery(float currentTranslation) {
animate(
currentTranslation / getWidth(),
0,
DISMISS_DURATION,
DISMISS_INTERPOLATOR,
false /* don't dismiss */);
}
/* package */ boolean isAnimating() {
return mDismissAnimator.isStarted();
}
private void animate(float from, float to, long duration, TimeInterpolator interpolator,
boolean dismissOnComplete) {
mDismissAnimator.cancel();
mDismissOnComplete = dismissOnComplete;
mDismissAnimator.setFloatValues(from, to);
mDismissAnimator.setDuration(duration);
mDismissAnimator.setInterpolator(interpolator);
mDismissAnimator.start();
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
setProgress(value * getWidth());
}
@Override
public void onAnimationStart(Animator animation) {
mWasCanceled = false;
}
@Override
public void onAnimationCancel(Animator animation) {
mWasCanceled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
if (!mWasCanceled) {
if (mDismissOnComplete) {
dismiss();
} else {
cancel();
}
}
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}
}

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<!--
This is a layout for a window whose resident activity is finished when swiped away.
-->
<com.android.internal.widget.SwipeDismissLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/content"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

View File

@@ -363,9 +363,7 @@
<attr name="windowOverscan" format="boolean" />
<!-- Flag indicating whether this is a floating window. -->
<attr name="windowIsFloating" format="boolean" />
<!-- Flag indicating whether this is a translucent window. If this attribute is unset (but
not if set to false), the window might still be considered translucent, if
windowSwipeToDismiss is set to true. -->
<!-- Flag indicating whether this is a translucent window. -->
<attr name="windowIsTranslucent" format="boolean" />
<!-- Flag indicating that this window's background should be the
user's current wallpaper. Corresponds
@@ -492,7 +490,9 @@
<!-- Flag to indicate that a window can be swiped away to be dismissed.
Corresponds to {@link android.view.Window#FEATURE_SWIPE_TO_DISMISS}. It will also
dynamically change translucency of the window, if the windowIsTranslucent is not set.
If windowIsTranslucent is set (to either true or false) it will obey that setting. -->
If windowIsTranslucent is set (to either true or false) it will obey that setting.
@deprecated Swipe-to-dismiss isn't functional anymore.
-->
<attr name="windowSwipeToDismiss" format="boolean" />
<!-- Flag indicating whether this window requests that content changes be performed
@@ -1961,7 +1961,6 @@
<attr name="windowCloseOnTouchOutside" />
<attr name="windowTranslucentStatus" />
<attr name="windowTranslucentNavigation" />
<attr name="windowSwipeToDismiss" />
<attr name="windowContentTransitions" />
<attr name="windowActivityTransitions" />
<attr name="windowContentTransitionManager" />

View File

@@ -32,9 +32,6 @@
<!-- True if windowOverscan should be on by default. -->
<bool name="config_windowOverscanByDefault">false</bool>
<!-- True if windowSwipeToDismiss should be on by default. -->
<bool name="config_windowSwipeToDismiss">false</bool>
<!-- True if preference fragment should clip to padding. -->
<bool name="config_preferenceFragmentClipToPadding">true</bool>

View File

@@ -1841,7 +1841,6 @@
<java-symbol type="layout" name="screen_progress" />
<java-symbol type="layout" name="screen_simple" />
<java-symbol type="layout" name="screen_simple_overlay_action_mode" />
<java-symbol type="layout" name="screen_swipe_dismiss" />
<java-symbol type="layout" name="screen_title" />
<java-symbol type="layout" name="screen_title_icons" />
<java-symbol type="string" name="system_ui_date_pattern" />

View File

@@ -182,7 +182,6 @@ please see themes_device_defaults.xml.
<item name="windowSharedElementExitTransition">@transition/move</item>
<item name="windowContentTransitions">false</item>
<item name="windowActivityTransitions">true</item>
<item name="windowSwipeToDismiss">@bool/config_windowSwipeToDismiss</item>
<!-- Dialog attributes -->
<item name="dialogTheme">@style/ThemeOverlay.Material.Dialog</item>
@@ -557,7 +556,6 @@ please see themes_device_defaults.xml.
<item name="windowSharedElementExitTransition">@transition/move</item>
<item name="windowContentTransitions">false</item>
<item name="windowActivityTransitions">true</item>
<item name="windowSwipeToDismiss">@bool/config_windowSwipeToDismiss</item>
<!-- Dialog attributes -->
<item name="dialogTheme">@style/ThemeOverlay.Material.Dialog</item>