Merge "Making transition out of recents look better" into jb-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
421dceb0a4
@ -98,6 +98,8 @@ public class ActivityOptions {
|
|||||||
public static final int ANIM_SCALE_UP = 2;
|
public static final int ANIM_SCALE_UP = 2;
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static final int ANIM_THUMBNAIL = 3;
|
public static final int ANIM_THUMBNAIL = 3;
|
||||||
|
/** @hide */
|
||||||
|
public static final int ANIM_THUMBNAIL_DELAYED = 4;
|
||||||
|
|
||||||
private String mPackageName;
|
private String mPackageName;
|
||||||
private int mAnimationType = ANIM_NONE;
|
private int mAnimationType = ANIM_NONE;
|
||||||
@ -219,9 +221,38 @@ public class ActivityOptions {
|
|||||||
*/
|
*/
|
||||||
public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
|
public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
|
||||||
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
|
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
|
||||||
|
return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an ActivityOptions specifying an animation where a thumbnail
|
||||||
|
* is scaled from a given position to the new activity window that is
|
||||||
|
* being started. Before the animation, there is a short delay.
|
||||||
|
*
|
||||||
|
* @param source The View that this thumbnail is animating from. This
|
||||||
|
* defines the coordinate space for <var>startX</var> and <var>startY</var>.
|
||||||
|
* @param thumbnail The bitmap that will be shown as the initial thumbnail
|
||||||
|
* of the animation.
|
||||||
|
* @param startX The x starting location of the bitmap, relative to <var>source</var>.
|
||||||
|
* @param startY The y starting location of the bitmap, relative to <var>source</var>.
|
||||||
|
* @param listener Optional OnAnimationStartedListener to find out when the
|
||||||
|
* requested animation has started running. If for some reason the animation
|
||||||
|
* is not executed, the callback will happen immediately.
|
||||||
|
* @return Returns a new ActivityOptions object that you can use to
|
||||||
|
* supply these options as the options Bundle when starting an activity.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static ActivityOptions makeDelayedThumbnailScaleUpAnimation(View source,
|
||||||
|
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
|
||||||
|
return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
|
||||||
|
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
|
||||||
|
boolean delayed) {
|
||||||
ActivityOptions opts = new ActivityOptions();
|
ActivityOptions opts = new ActivityOptions();
|
||||||
opts.mPackageName = source.getContext().getPackageName();
|
opts.mPackageName = source.getContext().getPackageName();
|
||||||
opts.mAnimationType = ANIM_THUMBNAIL;
|
opts.mAnimationType = delayed ? ANIM_THUMBNAIL_DELAYED : ANIM_THUMBNAIL;
|
||||||
opts.mThumbnail = thumbnail;
|
opts.mThumbnail = thumbnail;
|
||||||
int[] pts = new int[2];
|
int[] pts = new int[2];
|
||||||
source.getLocationOnScreen(pts);
|
source.getLocationOnScreen(pts);
|
||||||
@ -258,7 +289,8 @@ public class ActivityOptions {
|
|||||||
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
|
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
|
||||||
mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
|
mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
|
||||||
mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
|
mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
|
||||||
} else if (mAnimationType == ANIM_THUMBNAIL) {
|
} else if (mAnimationType == ANIM_THUMBNAIL ||
|
||||||
|
mAnimationType == ANIM_THUMBNAIL_DELAYED) {
|
||||||
mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
|
mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
|
||||||
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
|
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
|
||||||
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
|
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
|
||||||
@ -359,6 +391,7 @@ public class ActivityOptions {
|
|||||||
mStartHeight = otherOptions.mStartHeight;
|
mStartHeight = otherOptions.mStartHeight;
|
||||||
break;
|
break;
|
||||||
case ANIM_THUMBNAIL:
|
case ANIM_THUMBNAIL:
|
||||||
|
case ANIM_THUMBNAIL_DELAYED:
|
||||||
mAnimationType = otherOptions.mAnimationType;
|
mAnimationType = otherOptions.mAnimationType;
|
||||||
mThumbnail = otherOptions.mThumbnail;
|
mThumbnail = otherOptions.mThumbnail;
|
||||||
mStartX = otherOptions.mStartX;
|
mStartX = otherOptions.mStartX;
|
||||||
@ -401,6 +434,7 @@ public class ActivityOptions {
|
|||||||
b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
|
b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
|
||||||
break;
|
break;
|
||||||
case ANIM_THUMBNAIL:
|
case ANIM_THUMBNAIL:
|
||||||
|
case ANIM_THUMBNAIL_DELAYED:
|
||||||
b.putInt(KEY_ANIM_TYPE, mAnimationType);
|
b.putInt(KEY_ANIM_TYPE, mAnimationType);
|
||||||
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
|
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
|
||||||
b.putInt(KEY_ANIM_START_X, mStartX);
|
b.putInt(KEY_ANIM_START_X, mStartX);
|
||||||
|
@ -84,7 +84,7 @@ interface IWindowManager
|
|||||||
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
|
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
|
||||||
int startHeight);
|
int startHeight);
|
||||||
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
|
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
|
||||||
IRemoteCallback startedCallback);
|
IRemoteCallback startedCallback, boolean delayed);
|
||||||
void executeAppTransition();
|
void executeAppTransition();
|
||||||
void setAppStartingWindow(IBinder token, String pkg, int theme,
|
void setAppStartingWindow(IBinder token, String pkg, int theme,
|
||||||
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
|
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
|
||||||
|
@ -27,6 +27,12 @@
|
|||||||
systemui:recentItemLayout="@layout/status_bar_recent_item"
|
systemui:recentItemLayout="@layout/status_bar_recent_item"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/recents_transition_placeholder_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/recents_bg_protect"
|
android:id="@+id/recents_bg_protect"
|
||||||
android:background="@drawable/status_bar_recents_background"
|
android:background="@drawable/status_bar_recents_background"
|
||||||
|
@ -27,6 +27,12 @@
|
|||||||
systemui:recentItemLayout="@layout/status_bar_recent_item"
|
systemui:recentItemLayout="@layout/status_bar_recent_item"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/recents_transition_placeholder_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/recents_bg_protect"
|
android:id="@+id/recents_bg_protect"
|
||||||
android:background="@drawable/status_bar_recents_background"
|
android:background="@drawable/status_bar_recents_background"
|
||||||
|
@ -39,6 +39,12 @@
|
|||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:clipChildren="false">
|
android:clipChildren="false">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/recents_transition_placeholder_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
|
||||||
<com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
|
<com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -21,21 +21,21 @@ import android.animation.AnimatorSet;
|
|||||||
import android.animation.AnimatorSet.Builder;
|
import android.animation.AnimatorSet.Builder;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewRootImpl;
|
||||||
|
|
||||||
/* package */ class Choreographer implements Animator.AnimatorListener {
|
/* package */ class Choreographer implements Animator.AnimatorListener {
|
||||||
// should group this into a multi-property animation
|
// should group this into a multi-property animation
|
||||||
private static final int OPEN_DURATION = 136;
|
private static final int OPEN_DURATION = 136;
|
||||||
private static final int CLOSE_DURATION = 250;
|
private static final int CLOSE_DURATION = 130;
|
||||||
private static final int SCRIM_DURATION = 400;
|
private static final int SCRIM_DURATION = 400;
|
||||||
private static final String TAG = RecentsPanelView.TAG;
|
private static final String TAG = RecentsPanelView.TAG;
|
||||||
private static final boolean DEBUG = RecentsPanelView.DEBUG;
|
private static final boolean DEBUG = RecentsPanelView.DEBUG;
|
||||||
|
|
||||||
boolean mVisible;
|
boolean mVisible;
|
||||||
int mPanelHeight;
|
int mPanelHeight;
|
||||||
View mRootView;
|
RecentsPanelView mRootView;
|
||||||
View mScrimView;
|
View mScrimView;
|
||||||
View mContentView;
|
View mContentView;
|
||||||
View mNoRecentAppsView;
|
View mNoRecentAppsView;
|
||||||
@ -45,7 +45,7 @@ import android.view.View;
|
|||||||
// the panel will start to appear this many px from the end
|
// the panel will start to appear this many px from the end
|
||||||
final int HYPERSPACE_OFFRAMP = 200;
|
final int HYPERSPACE_OFFRAMP = 200;
|
||||||
|
|
||||||
public Choreographer(View root, View scrim, View content,
|
public Choreographer(RecentsPanelView root, View scrim, View content,
|
||||||
View noRecentApps, Animator.AnimatorListener listener) {
|
View noRecentApps, Animator.AnimatorListener listener) {
|
||||||
mRootView = root;
|
mRootView = root;
|
||||||
mScrimView = scrim;
|
mScrimView = scrim;
|
||||||
@ -67,7 +67,7 @@ import android.view.View;
|
|||||||
end = 0;
|
end = 0;
|
||||||
} else {
|
} else {
|
||||||
start = y;
|
start = y;
|
||||||
end = y + HYPERSPACE_OFFRAMP;
|
end = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
|
Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
|
||||||
@ -77,12 +77,12 @@ import android.view.View;
|
|||||||
: new android.view.animation.AccelerateInterpolator(2.5f));
|
: new android.view.animation.AccelerateInterpolator(2.5f));
|
||||||
posAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
|
posAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
|
||||||
|
|
||||||
Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
|
Animator fadeAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
|
||||||
mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
|
mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
|
||||||
glowAnim.setInterpolator(appearing
|
fadeAnim.setInterpolator(appearing
|
||||||
? new android.view.animation.AccelerateInterpolator(1.0f)
|
? new android.view.animation.AccelerateInterpolator(1.0f)
|
||||||
: new android.view.animation.DecelerateInterpolator(1.0f));
|
: new android.view.animation.DecelerateInterpolator(1.0f));
|
||||||
glowAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
|
fadeAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
|
||||||
|
|
||||||
Animator noRecentAppsFadeAnim = null;
|
Animator noRecentAppsFadeAnim = null;
|
||||||
if (mNoRecentAppsView != null && // doesn't exist on large devices
|
if (mNoRecentAppsView != null && // doesn't exist on large devices
|
||||||
@ -96,7 +96,7 @@ import android.view.View;
|
|||||||
}
|
}
|
||||||
|
|
||||||
mContentAnim = new AnimatorSet();
|
mContentAnim = new AnimatorSet();
|
||||||
final Builder builder = mContentAnim.play(glowAnim).with(posAnim);
|
final Builder builder = mContentAnim.play(fadeAnim).with(posAnim);
|
||||||
|
|
||||||
if (noRecentAppsFadeAnim != null) {
|
if (noRecentAppsFadeAnim != null) {
|
||||||
builder.with(noRecentAppsFadeAnim);
|
builder.with(noRecentAppsFadeAnim);
|
||||||
@ -153,9 +153,10 @@ import android.view.View;
|
|||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
if (DEBUG) Slog.d(TAG, "onAnimationEnd");
|
if (DEBUG) Slog.d(TAG, "onAnimationEnd");
|
||||||
if (!mVisible) {
|
if (!mVisible) {
|
||||||
mRootView.setVisibility(View.GONE);
|
mRootView.hideWindow();
|
||||||
}
|
}
|
||||||
mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
|
mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||||
|
mContentView.setAlpha(1f);
|
||||||
mContentAnim = null;
|
mContentAnim = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,9 @@ import android.content.res.Configuration;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.graphics.Shader.TileMode;
|
import android.graphics.Shader.TileMode;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@ -48,11 +50,9 @@ import android.widget.AdapterView;
|
|||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.HorizontalScrollView;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ImageView.ScaleType;
|
import android.widget.ImageView.ScaleType;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.ScrollView;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@ -83,6 +83,9 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
|
|||||||
private Choreographer mChoreo;
|
private Choreographer mChoreo;
|
||||||
OnRecentsPanelVisibilityChangedListener mVisibilityChangedListener;
|
OnRecentsPanelVisibilityChangedListener mVisibilityChangedListener;
|
||||||
|
|
||||||
|
ImageView mPlaceholderThumbnail;
|
||||||
|
boolean mHideWindowAfterPlaceholderThumbnailIsHidden;
|
||||||
|
|
||||||
private RecentTasksLoader mRecentTasksLoader;
|
private RecentTasksLoader mRecentTasksLoader;
|
||||||
private ArrayList<TaskDescription> mRecentTaskDescriptions;
|
private ArrayList<TaskDescription> mRecentTaskDescriptions;
|
||||||
private Runnable mPreloadTasksRunnable;
|
private Runnable mPreloadTasksRunnable;
|
||||||
@ -283,7 +286,9 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
|
|||||||
public void show(boolean show, boolean animate,
|
public void show(boolean show, boolean animate,
|
||||||
ArrayList<TaskDescription> recentTaskDescriptions, boolean firstScreenful) {
|
ArrayList<TaskDescription> recentTaskDescriptions, boolean firstScreenful) {
|
||||||
// For now, disable animations. We may want to re-enable in the future
|
// For now, disable animations. We may want to re-enable in the future
|
||||||
|
if (show) {
|
||||||
animate = false;
|
animate = false;
|
||||||
|
}
|
||||||
if (show) {
|
if (show) {
|
||||||
// Need to update list of recent apps before we set visibility so this view's
|
// Need to update list of recent apps before we set visibility so this view's
|
||||||
// content description is updated before it gets focus for TalkBack mode
|
// content description is updated before it gets focus for TalkBack mode
|
||||||
@ -687,11 +692,31 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
|
|||||||
context.getSystemService(Context.ACTIVITY_SERVICE);
|
context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
holder.thumbnailViewImage.setDrawingCacheEnabled(true);
|
holder.thumbnailViewImage.setDrawingCacheEnabled(true);
|
||||||
Bitmap bm = holder.thumbnailViewImage.getDrawingCache();
|
Bitmap bm = holder.thumbnailViewImage.getDrawingCache();
|
||||||
ActivityOptions opts = ActivityOptions.makeThumbnailScaleUpAnimation(
|
mPlaceholderThumbnail = (ImageView) findViewById(R.id.recents_transition_placeholder_icon);
|
||||||
|
|
||||||
|
final ImageView placeholderThumbnail = mPlaceholderThumbnail;
|
||||||
|
mHideWindowAfterPlaceholderThumbnailIsHidden = false;
|
||||||
|
placeholderThumbnail.setVisibility(VISIBLE);
|
||||||
|
Bitmap b2 = bm.copy(bm.getConfig(), true);
|
||||||
|
placeholderThumbnail.setImageBitmap(b2);
|
||||||
|
|
||||||
|
Rect r = new Rect();
|
||||||
|
holder.thumbnailViewImage.getGlobalVisibleRect(r);
|
||||||
|
|
||||||
|
placeholderThumbnail.setTranslationX(r.left);
|
||||||
|
placeholderThumbnail.setTranslationY(r.top);
|
||||||
|
|
||||||
|
show(false, true);
|
||||||
|
|
||||||
|
ActivityOptions opts = ActivityOptions.makeDelayedThumbnailScaleUpAnimation(
|
||||||
holder.thumbnailViewImage, bm, 0, 0,
|
holder.thumbnailViewImage, bm, 0, 0,
|
||||||
new ActivityOptions.OnAnimationStartedListener() {
|
new ActivityOptions.OnAnimationStartedListener() {
|
||||||
@Override public void onAnimationStarted() {
|
@Override public void onAnimationStarted() {
|
||||||
hide(true);
|
mPlaceholderThumbnail = null;
|
||||||
|
placeholderThumbnail.setVisibility(INVISIBLE);
|
||||||
|
if (mHideWindowAfterPlaceholderThumbnailIsHidden) {
|
||||||
|
hideWindow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (ad.taskId >= 0) {
|
if (ad.taskId >= 0) {
|
||||||
@ -709,6 +734,15 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
|
|||||||
holder.thumbnailViewImage.setDrawingCacheEnabled(false);
|
holder.thumbnailViewImage.setDrawingCacheEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void hideWindow() {
|
||||||
|
if (mPlaceholderThumbnail != null) {
|
||||||
|
mHideWindowAfterPlaceholderThumbnailIsHidden = true;
|
||||||
|
} else {
|
||||||
|
setVisibility(GONE);
|
||||||
|
mHideWindowAfterPlaceholderThumbnailIsHidden = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
handleOnClick(view);
|
handleOnClick(view);
|
||||||
}
|
}
|
||||||
|
@ -552,7 +552,8 @@ final class ActivityRecord {
|
|||||||
|
|
||||||
void applyOptionsLocked() {
|
void applyOptionsLocked() {
|
||||||
if (pendingOptions != null) {
|
if (pendingOptions != null) {
|
||||||
switch (pendingOptions.getAnimationType()) {
|
final int animationType = pendingOptions.getAnimationType();
|
||||||
|
switch (animationType) {
|
||||||
case ActivityOptions.ANIM_CUSTOM:
|
case ActivityOptions.ANIM_CUSTOM:
|
||||||
service.mWindowManager.overridePendingAppTransition(
|
service.mWindowManager.overridePendingAppTransition(
|
||||||
pendingOptions.getPackageName(),
|
pendingOptions.getPackageName(),
|
||||||
@ -571,10 +572,13 @@ final class ActivityRecord {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ActivityOptions.ANIM_THUMBNAIL:
|
case ActivityOptions.ANIM_THUMBNAIL:
|
||||||
|
case ActivityOptions.ANIM_THUMBNAIL_DELAYED:
|
||||||
|
boolean delayed = (animationType == ActivityOptions.ANIM_THUMBNAIL_DELAYED);
|
||||||
service.mWindowManager.overridePendingAppTransitionThumb(
|
service.mWindowManager.overridePendingAppTransitionThumb(
|
||||||
pendingOptions.getThumbnail(),
|
pendingOptions.getThumbnail(),
|
||||||
pendingOptions.getStartX(), pendingOptions.getStartY(),
|
pendingOptions.getStartX(), pendingOptions.getStartY(),
|
||||||
pendingOptions.getOnAnimationStartListener());
|
pendingOptions.getOnAnimationStartListener(),
|
||||||
|
delayed);
|
||||||
if (intent.getSourceBounds() == null) {
|
if (intent.getSourceBounds() == null) {
|
||||||
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
|
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
|
||||||
pendingOptions.getStartY(),
|
pendingOptions.getStartY(),
|
||||||
|
@ -512,6 +512,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
int mNextAppTransitionType = ActivityOptions.ANIM_NONE;
|
int mNextAppTransitionType = ActivityOptions.ANIM_NONE;
|
||||||
String mNextAppTransitionPackage;
|
String mNextAppTransitionPackage;
|
||||||
Bitmap mNextAppTransitionThumbnail;
|
Bitmap mNextAppTransitionThumbnail;
|
||||||
|
boolean mNextAppTransitionDelayed;
|
||||||
IRemoteCallback mNextAppTransitionCallback;
|
IRemoteCallback mNextAppTransitionCallback;
|
||||||
int mNextAppTransitionEnter;
|
int mNextAppTransitionEnter;
|
||||||
int mNextAppTransitionExit;
|
int mNextAppTransitionExit;
|
||||||
@ -3176,7 +3177,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Animation createThumbnailAnimationLocked(int transit,
|
private Animation createThumbnailAnimationLocked(int transit,
|
||||||
boolean enter, boolean thumb) {
|
boolean enter, boolean thumb, boolean delayed) {
|
||||||
Animation a;
|
Animation a;
|
||||||
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
|
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
|
||||||
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
|
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
|
||||||
@ -3186,6 +3187,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
// it is the standard duration for that. Otherwise we use the longer
|
// it is the standard duration for that. Otherwise we use the longer
|
||||||
// task transition duration.
|
// task transition duration.
|
||||||
int duration;
|
int duration;
|
||||||
|
int delayDuration = delayed ? 200 : 0;
|
||||||
switch (transit) {
|
switch (transit) {
|
||||||
case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
|
case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
|
||||||
case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
|
case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
|
||||||
@ -3193,7 +3195,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
com.android.internal.R.integer.config_shortAnimTime);
|
com.android.internal.R.integer.config_shortAnimTime);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
duration = 300;
|
duration = delayed ? 200 : 300;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (thumb) {
|
if (thumb) {
|
||||||
@ -3201,6 +3203,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
// filling the screen.
|
// filling the screen.
|
||||||
float scaleW = mAppDisplayWidth/thumbWidth;
|
float scaleW = mAppDisplayWidth/thumbWidth;
|
||||||
float scaleH = mAppDisplayHeight/thumbHeight;
|
float scaleH = mAppDisplayHeight/thumbHeight;
|
||||||
|
|
||||||
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
|
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
|
||||||
computePivot(mNextAppTransitionStartX, 1/scaleW),
|
computePivot(mNextAppTransitionStartX, 1/scaleW),
|
||||||
computePivot(mNextAppTransitionStartY, 1/scaleH));
|
computePivot(mNextAppTransitionStartY, 1/scaleH));
|
||||||
@ -3210,17 +3213,38 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
set.addAnimation(scale);
|
set.addAnimation(scale);
|
||||||
alpha.setDuration(duration);
|
alpha.setDuration(duration);
|
||||||
set.addAnimation(alpha);
|
set.addAnimation(alpha);
|
||||||
|
set.setFillBefore(true);
|
||||||
|
if (delayDuration > 0) {
|
||||||
|
set.setStartOffset(delayDuration);
|
||||||
|
}
|
||||||
a = set;
|
a = set;
|
||||||
} else if (enter) {
|
} else if (enter) {
|
||||||
// Entering app zooms out from the center of the thumbnail.
|
// Entering app zooms out from the center of the thumbnail.
|
||||||
float scaleW = thumbWidth / mAppDisplayWidth;
|
float scaleW = thumbWidth / mAppDisplayWidth;
|
||||||
float scaleH = thumbHeight / mAppDisplayHeight;
|
float scaleH = thumbHeight / mAppDisplayHeight;
|
||||||
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
|
AnimationSet set = new AnimationSet(true);
|
||||||
|
Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
|
||||||
computePivot(mNextAppTransitionStartX, scaleW),
|
computePivot(mNextAppTransitionStartX, scaleW),
|
||||||
computePivot(mNextAppTransitionStartY, scaleH));
|
computePivot(mNextAppTransitionStartY, scaleH));
|
||||||
a.setDuration(duration);
|
scale.setDuration(duration);
|
||||||
|
scale.setFillBefore(true);
|
||||||
|
set.addAnimation(scale);
|
||||||
|
// Need to set an alpha animation on the entering app window
|
||||||
|
// in case it appears one frame before the thumbnail window
|
||||||
|
// (this solves flicker)
|
||||||
|
Animation alpha = new AlphaAnimation(0, 1);
|
||||||
|
alpha.setDuration(1);
|
||||||
|
alpha.setFillAfter(true);
|
||||||
|
set.addAnimation(alpha);
|
||||||
|
a = set;
|
||||||
|
if (delayDuration > 0) {
|
||||||
|
a.setStartOffset(delayDuration);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
a = createExitAnimationLocked(transit, duration);
|
a = createExitAnimationLocked(transit, duration);
|
||||||
|
if (delayDuration > 0) {
|
||||||
|
a.setStartOffset(delayDuration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a.setFillAfter(true);
|
a.setFillAfter(true);
|
||||||
final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
|
final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
|
||||||
@ -3252,12 +3276,18 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
|
if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
|
||||||
+ " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
|
+ " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
|
||||||
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
|
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
|
||||||
} else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL) {
|
} else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL ||
|
||||||
a = createThumbnailAnimationLocked(transit, enter, false);
|
mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED) {
|
||||||
|
boolean delayed = (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED);
|
||||||
|
a = createThumbnailAnimationLocked(transit, enter, false, delayed);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
|
|
||||||
+ " anim=" + a + " nextAppTransition=ANIM_THUMBNAIL"
|
if (DEBUG_ANIM) {
|
||||||
|
String animName = delayed ? "ANIM_THUMBNAIL_DELAYED" : "ANIM_THUMBNAIL";
|
||||||
|
Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
|
||||||
|
+ " anim=" + a + " nextAppTransition=" + animName
|
||||||
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
|
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int animAttr = 0;
|
int animAttr = 0;
|
||||||
switch (transit) {
|
switch (transit) {
|
||||||
@ -3879,11 +3909,13 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
|
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
|
||||||
int startY, IRemoteCallback startedCallback) {
|
int startY, IRemoteCallback startedCallback, boolean delayed) {
|
||||||
if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
|
if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
|
||||||
mNextAppTransitionType = ActivityOptions.ANIM_THUMBNAIL;
|
mNextAppTransitionType =
|
||||||
|
delayed ? ActivityOptions.ANIM_THUMBNAIL_DELAYED : ActivityOptions.ANIM_THUMBNAIL;
|
||||||
mNextAppTransitionPackage = null;
|
mNextAppTransitionPackage = null;
|
||||||
mNextAppTransitionThumbnail = srcThumb;
|
mNextAppTransitionThumbnail = srcThumb;
|
||||||
|
mNextAppTransitionDelayed = delayed;
|
||||||
mNextAppTransitionStartX = startX;
|
mNextAppTransitionStartX = startX;
|
||||||
mNextAppTransitionStartY = startY;
|
mNextAppTransitionStartY = startY;
|
||||||
mNextAppTransitionCallback = startedCallback;
|
mNextAppTransitionCallback = startedCallback;
|
||||||
@ -8024,7 +8056,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
drawSurface.unlockCanvasAndPost(c);
|
drawSurface.unlockCanvasAndPost(c);
|
||||||
drawSurface.release();
|
drawSurface.release();
|
||||||
topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer;
|
topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer;
|
||||||
Animation anim = createThumbnailAnimationLocked(transit, true, true);
|
Animation anim = createThumbnailAnimationLocked(
|
||||||
|
transit, true, true, mNextAppTransitionDelayed);
|
||||||
topOpeningApp.mAppAnimator.thumbnailAnimation = anim;
|
topOpeningApp.mAppAnimator.thumbnailAnimation = anim;
|
||||||
anim.restrictDuration(MAX_ANIMATION_DURATION);
|
anim.restrictDuration(MAX_ANIMATION_DURATION);
|
||||||
anim.scaleCurrentDuration(mTransitionAnimationScale);
|
anim.scaleCurrentDuration(mTransitionAnimationScale);
|
||||||
@ -9602,10 +9635,12 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
pw.println(mNextAppTransitionStartHeight);
|
pw.println(mNextAppTransitionStartHeight);
|
||||||
break;
|
break;
|
||||||
case ActivityOptions.ANIM_THUMBNAIL:
|
case ActivityOptions.ANIM_THUMBNAIL:
|
||||||
|
case ActivityOptions.ANIM_THUMBNAIL_DELAYED:
|
||||||
pw.print(" mNextAppTransitionThumbnail=");
|
pw.print(" mNextAppTransitionThumbnail=");
|
||||||
pw.print(mNextAppTransitionThumbnail);
|
pw.print(mNextAppTransitionThumbnail);
|
||||||
pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
|
pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
|
||||||
pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY);
|
pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY);
|
||||||
|
pw.print(" mNextAppTransitionDelayed="); pw.println(mNextAppTransitionDelayed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
|
pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
|
||||||
|
@ -240,7 +240,7 @@ public class BridgeWindowManager implements IWindowManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
|
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
|
||||||
IRemoteCallback startedCallback) throws RemoteException {
|
IRemoteCallback startedCallback, boolean delayed) throws RemoteException {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user