DO NOT MERGE Fix android:noHistory for Wear
Modifies swipe-to-close activities to be opaque by default (instead of translucent by default). Previously, android:noHistory properties on most activities in Wear were being ignored because they were usually transitioning to a swipe-to-close activity that was marked as translucent. This meant that the noHistory activity was still technically visible, and so would never be culled from the task history. Now, we convert a swiped activity to translucent as soon as a swipe begins, and convert it back after the swipe finishes. The previous version of SDL tries to do this, but fails in the case where the context is a ContextWrapper. This approach is hacky and isn't merge-able into master. We leave it DO NOT MERGE and will do a long-term fix after the holidays. Test: Built a test app to verify that noHistory is now being correctly respected. Manually verified that new activities start out opaque and not translucent. Manually verified that Home correctly starts/stops when it's revealed from underneath a partially swiped activity. Tested general swipe behavior on Settings, Contacts, Flashlight, Fit. Bug: 33252029 Change-Id: Ib2e7f21ea1e0d52db03e78d25676501e5f73b31f
This commit is contained in:
@@ -23,6 +23,7 @@ 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.res.TypedArray;
|
||||
@@ -33,7 +34,6 @@ import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
@@ -44,7 +44,6 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
private static final String TAG = "SwipeDismissLayout";
|
||||
|
||||
private static final float DISMISS_MIN_DRAG_WIDTH_RATIO = .33f;
|
||||
private boolean mUseDynamicTranslucency = true;
|
||||
|
||||
public interface OnDismissedListener {
|
||||
void onDismissed(SwipeDismissLayout layout);
|
||||
@@ -64,6 +63,8 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
void onSwipeCancelled(SwipeDismissLayout layout);
|
||||
}
|
||||
|
||||
private boolean mIsWindowNativelyTranslucent;
|
||||
|
||||
// Cached ViewConfiguration and system-wide constant values
|
||||
private int mSlop;
|
||||
private int mMinFlingVelocity;
|
||||
@@ -83,19 +84,6 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
|
||||
private OnDismissedListener mDismissedListener;
|
||||
private OnSwipeProgressChangedListener mProgressListener;
|
||||
private ViewTreeObserver.OnEnterAnimationCompleteListener mOnEnterAnimationCompleteListener =
|
||||
new ViewTreeObserver.OnEnterAnimationCompleteListener() {
|
||||
@Override
|
||||
public void onEnterAnimationComplete() {
|
||||
// SwipeDismissLayout assumes that the host Activity is translucent
|
||||
// and temporarily disables translucency when it is fully visible.
|
||||
// As soon as the user starts swiping, we will re-enable
|
||||
// translucency.
|
||||
if (mUseDynamicTranslucency && getContext() instanceof Activity) {
|
||||
((Activity) getContext()).convertFromTranslucent();
|
||||
}
|
||||
}
|
||||
};
|
||||
private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
|
||||
private Runnable mRunnable = new Runnable() {
|
||||
@Override
|
||||
@@ -141,8 +129,8 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
|
||||
TypedArray a = context.getTheme().obtainStyledAttributes(
|
||||
com.android.internal.R.styleable.Theme);
|
||||
mUseDynamicTranslucency = !a.hasValue(
|
||||
com.android.internal.R.styleable.Window_windowIsTranslucent);
|
||||
mIsWindowNativelyTranslucent = a.getBoolean(
|
||||
com.android.internal.R.styleable.Window_windowIsTranslucent, false);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@@ -157,20 +145,12 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (getContext() instanceof Activity) {
|
||||
getViewTreeObserver().addOnEnterAnimationCompleteListener(
|
||||
mOnEnterAnimationCompleteListener);
|
||||
}
|
||||
getContext().registerReceiver(mScreenOffReceiver, mScreenOffFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
getContext().unregisterReceiver(mScreenOffReceiver);
|
||||
if (getContext() instanceof Activity) {
|
||||
getViewTreeObserver().removeOnEnterAnimationCompleteListener(
|
||||
mOnEnterAnimationCompleteListener);
|
||||
}
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@@ -273,9 +253,6 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
mLastX = ev.getRawX();
|
||||
updateSwiping(ev);
|
||||
if (mSwiping) {
|
||||
if (mUseDynamicTranslucency && getContext() instanceof Activity) {
|
||||
((Activity) getContext()).convertToTranslucent(null, null);
|
||||
}
|
||||
setProgress(ev.getRawX() - mDownX);
|
||||
break;
|
||||
}
|
||||
@@ -298,8 +275,11 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
}
|
||||
|
||||
protected void cancel() {
|
||||
if (mUseDynamicTranslucency && getContext() instanceof Activity) {
|
||||
((Activity) getContext()).convertFromTranslucent();
|
||||
if (!mIsWindowNativelyTranslucent) {
|
||||
Activity activity = findActivity();
|
||||
if (activity != null) {
|
||||
activity.convertFromTranslucent();
|
||||
}
|
||||
}
|
||||
if (mProgressListener != null) {
|
||||
mProgressListener.onSwipeCancelled(this);
|
||||
@@ -323,6 +303,7 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
}
|
||||
|
||||
private void updateSwiping(MotionEvent ev) {
|
||||
boolean oldSwiping = mSwiping;
|
||||
if (!mSwiping) {
|
||||
float deltaX = ev.getRawX() - mDownX;
|
||||
float deltaY = ev.getRawY() - mDownY;
|
||||
@@ -332,6 +313,16 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
mSwiping = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSwiping && !oldSwiping) {
|
||||
// Swiping has started
|
||||
if (!mIsWindowNativelyTranslucent) {
|
||||
Activity activity = findActivity();
|
||||
if (activity != null) {
|
||||
activity.convertToTranslucent(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDismiss(MotionEvent ev) {
|
||||
@@ -406,6 +397,17 @@ public class SwipeDismissLayout extends FrameLayout {
|
||||
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;
|
||||
|
||||
@@ -710,12 +710,7 @@ final class ActivityRecord {
|
||||
AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
|
||||
realTheme, com.android.internal.R.styleable.Window, userId);
|
||||
final boolean translucent = ent != null && (ent.array.getBoolean(
|
||||
com.android.internal.R.styleable.Window_windowIsTranslucent, false)
|
||||
|| (!ent.array.hasValue(
|
||||
com.android.internal.R.styleable.Window_windowIsTranslucent)
|
||||
&& ent.array.getBoolean(
|
||||
com.android.internal.R.styleable.Window_windowSwipeToDismiss,
|
||||
false)));
|
||||
com.android.internal.R.styleable.Window_windowIsTranslucent, false));
|
||||
fullscreen = ent != null && !ent.array.getBoolean(
|
||||
com.android.internal.R.styleable.Window_windowIsFloating, false)
|
||||
&& !translucent;
|
||||
|
||||
Reference in New Issue
Block a user