Android 12系统源码_窗口动画(一) ActivityOptions实现窗口打开动画的流程

一、通过ActivityOptions获取Activity对应的打开动画

1、我们可以通过ActivityOptions类,实现打开Activity的时候有对应的缩放动画。

    private void startActivity(View view) {int width = view.getMeasuredWidth();int height = view.getMeasuredHeight();Log.d(TAG, "startActivity: witch = " + width + " height = " + height);//打开Activity的时候添加从View逐渐缩放到全屏的Activity打开动画ActivityOptions activityOptions = ActivityOptions.makeScaleUpAnimation(view, 0, 0, width, height);Intent intent = new Intent();startActivity(intent, activityOptions.toBundle());}

以上代码主要是调用ActivityOptions的makeScaleUpAnimation方法,为Activity添加打开动画的。

2、通过ActivityOptions我们可以获取到很多种Activity的打开动画。

base/core/java/android/app/ActivityOptions.java

public class ActivityOptions {//缩放动画public static ActivityOptions makeScaleUpAnimation(View source,int startX, int startY, int width, int height) {ActivityOptions opts = new ActivityOptions();opts.mPackageName = source.getContext().getPackageName();opts.mAnimationType = ANIM_SCALE_UP;int[] pts = new int[2];source.getLocationOnScreen(pts);opts.mStartX = pts[0] + startX;opts.mStartY = pts[1] + startY;opts.mWidth = width;opts.mHeight = height;return opts;}//裁剪动画public static ActivityOptions makeClipRevealAnimation(View source,int startX, int startY, int width, int height) {ActivityOptions opts = new ActivityOptions();opts.mAnimationType = ANIM_CLIP_REVEAL;int[] pts = new int[2];source.getLocationOnScreen(pts);opts.mStartX = pts[0] + startX;opts.mStartY = pts[1] + startY;opts.mWidth = width;opts.mHeight = height;return opts;}//自定义动画public static ActivityOptions makeCustomAnimation(Context context,int enterResId, int exitResId) {return makeCustomAnimation(context, enterResId, exitResId, null, null, null);}//自定义动画    public static ActivityOptions makeCustomAnimation(Context context,int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {ActivityOptions opts = new ActivityOptions();opts.mPackageName = context.getPackageName();opts.mAnimationType = ANIM_CUSTOM;opts.mCustomEnterResId = enterResId;opts.mCustomExitResId = exitResId;opts.setOnAnimationStartedListener(handler, listener);return opts;}//场景过渡动画public static ActivityOptions makeSceneTransitionAnimation(Activity activity,Pair<View, String>... sharedElements) {ActivityOptions opts = new ActivityOptions();ExitTransitionCoordinator exit = makeSceneTransitionAnimation(new ActivityExitTransitionCallbacks(activity), activity.mExitTransitionListener,activity.getWindow(), opts, sharedElements);opts.mExitCoordinatorIndex =activity.mActivityTransitionState.addExitTransitionCoordinator(exit);return opts;}//缩略图缩放动画public static ActivityOptions makeThumbnailScaleUpAnimation(View source,Bitmap thumbnail, int startX, int startY) {return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);}//缩略图缩放动画private static ActivityOptions makeThumbnailScaleUpAnimation(View source,Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);}//缩略图缩放动画private static ActivityOptions makeThumbnailAnimation(View source,Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,boolean scaleUp) {ActivityOptions opts = new ActivityOptions();opts.mPackageName = source.getContext().getPackageName();opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;opts.mThumbnail = thumbnail;int[] pts = new int[2];source.getLocationOnScreen(pts);opts.mStartX = pts[0] + startX;opts.mStartY = pts[1] + startY;opts.setOnAnimationStartedListener(source.getHandler(), listener);return opts;}}
  • makeScaleUpAnimation(View source, int startX, int startY, int startWidth, int startHeight): 创建缩放动画,使目标 Activity 从指定的起始位置和大小缩放到其正常大小。可以指定动画起始位置和大小。

  • makeClipRevealAnimation(View source, int startX, int startY, int startWidth, int startHeight): 创建裁剪揭示动画,使目标 Activity 从指定的起始位置开始逐渐揭示出来。可以指定动画起始位置和大小。

  • makeCustomAnimation(int enterResId, int exitResId): 创建自定义的 Activity 进入和退出动画。通过传入进入动画资源 ID 和退出动画资源 ID 来定义自定义的动画效果。

  • makeSceneTransitionAnimation(Activity activity, Pair<View, String>… sharedElements): 创建场景过渡动画,用于在两个 Activity 之间共享元素的平滑过渡。可以传入一个或多个共享元素及其对应的名称。

  • makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY): 创建缩略图缩放动画,使目标 Activity 从指定的缩略图位置开始放大。可以指定缩略图和动画起始位置。

3、由于startActivity方法使用的是Bundle参数,ActivityOptions提供了toBundle方法,可以将自己转化成对应的参数类型。

public class ActivityOptions {public static final String KEY_ANIM_TYPE = "android:activity.animType";public static final String KEY_ANIM_ENTER_RES_ID = "android:activity.animEnterRes";public static final String KEY_ANIM_EXIT_RES_ID = "android:activity.animExitRes";public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:activity.animInPlaceRes";public static final String KEY_ANIM_THUMBNAIL = "android:activity.animThumbnail";public static final String KEY_ANIM_START_X = "android:activity.animStartX";public static final String KEY_ANIM_START_Y = "android:activity.animStartY";public static final String KEY_ANIM_WIDTH = "android:activity.animWidth";public static final String KEY_ANIM_HEIGHT = "android:activity.animHeight";public static final String KEY_ANIM_START_LISTENER = "android:activity.animStartListener";public static final String KEY_SPLASH_SCREEN_THEME = "android.activity.splashScreenTheme";private static final String KEY_ANIMATION_FINISHED_LISTENER ="android:activity.animationFinishedListener";private static final String KEY_ANIM_SPECS = "android:activity.animSpecs";private int mAnimationType = ANIM_UNDEFINED;//动画类型,默认为未定义public Bundle toBundle() {Bundle b = new Bundle();if (mPackageName != null) {b.putString(KEY_PACKAGE_NAME, mPackageName);}if (mLaunchBounds != null) {b.putParcelable(KEY_LAUNCH_BOUNDS, mLaunchBounds);}//动画类型if (mAnimationType != ANIM_UNDEFINED) {b.putInt(KEY_ANIM_TYPE, mAnimationType);}if (mUsageTimeReport != null) {b.putParcelable(KEY_USAGE_TIME_REPORT, mUsageTimeReport);}//根据动画类型,进一步传递不同的参数switch (mAnimationType) {case ANIM_CUSTOM://自定义动画,允许启动和结束的Activity定义不同的动画b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener!= null ? mAnimationStartedListener.asBinder() : null);break;case ANIM_CUSTOM_IN_PLACE://自定义动画b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);break;case ANIM_SCALE_UP://缩放case ANIM_CLIP_REVEAL://裁剪b.putInt(KEY_ANIM_START_X, mStartX);b.putInt(KEY_ANIM_START_Y, mStartY);b.putInt(KEY_ANIM_WIDTH, mWidth);b.putInt(KEY_ANIM_HEIGHT, mHeight);break;case ANIM_THUMBNAIL_SCALE_UP://使用一个缩略图,并将其放大为全屏界面。用户会看到原始界面逐渐放大到全屏,这种效果通常用于突出新界面的出现,使界面过渡更加平滑和引人注目。case ANIM_THUMBNAIL_SCALE_DOWN://这种动画效果会在启动新的 Activity 时,使用一个全屏的界面缩略图,并将其缩小为新界面。用户会看到全屏界面逐渐缩小到新界面的大小,这种效果通常用于突出原始界面的退出,使界面过渡更加平滑和自然case ANIM_THUMBNAIL_ASPECT_SCALE_UP://在放大过程中,缩略图的宽高比不会发生变化,保持原始界面的比例。这种效果通常用于要求保持界面比例的场景,使界面过渡更加统一和美观。case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN://在缩小过程中,缩略图的宽高比不会发生变化,保持原始界面的比例。这种效果通常用于要求保持界面比例的场景,使界面过渡更加统一和美观。// Once we parcel the thumbnail for transfering over to the system, create a copy of// the bitmap to a hardware bitmap and pass through the HardwareBufferif (mThumbnail != null) {final Bitmap hwBitmap = mThumbnail.copy(Config.HARDWARE, false /* isMutable */);if (hwBitmap != null) {b.putParcelable(KEY_ANIM_THUMBNAIL, hwBitmap.getHardwareBuffer());} else {Slog.w(TAG, "Failed to copy thumbnail");}}b.putInt(KEY_ANIM_START_X, mStartX);b.putInt(KEY_ANIM_START_Y, mStartY);b.putInt(KEY_ANIM_WIDTH, mWidth);b.putInt(KEY_ANIM_HEIGHT, mHeight);b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener!= null ? mAnimationStartedListener.asBinder() : null);break;case ANIM_SCENE_TRANSITION://场景动画if (mTransitionReceiver != null) {b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);}b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning);b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames);b.putParcelable(KEY_RESULT_DATA, mResultData);b.putInt(KEY_RESULT_CODE, mResultCode);b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);break;}if (mLockTaskMode) {b.putBoolean(KEY_LOCK_TASK_MODE, mLockTaskMode);}if (mLaunchDisplayId != INVALID_DISPLAY) {b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);}if (mCallerDisplayId != INVALID_DISPLAY) {b.putInt(KEY_CALLER_DISPLAY_ID, mCallerDisplayId);}if (mLaunchTaskDisplayArea != null) {b.putParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN, mLaunchTaskDisplayArea);}if (mLaunchRootTask != null) {b.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, mLaunchRootTask);}if (mLaunchTaskFragmentToken != null) {b.putBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN, mLaunchTaskFragmentToken);}if (mLaunchWindowingMode != WINDOWING_MODE_UNDEFINED) {b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);}if (mLaunchActivityType != ACTIVITY_TYPE_UNDEFINED) {b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);}if (mLaunchTaskId != -1) {b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);}if (mPendingIntentLaunchFlags != 0) {b.putInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, mPendingIntentLaunchFlags);}if (mTaskAlwaysOnTop) {b.putBoolean(KEY_TASK_ALWAYS_ON_TOP, mTaskAlwaysOnTop);}if (mTaskOverlay) {b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);}if (mTaskOverlayCanResume) {b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume);}if (mAvoidMoveToFront) {b.putBoolean(KEY_AVOID_MOVE_TO_FRONT, mAvoidMoveToFront);}if (mFreezeRecentTasksReordering) {b.putBoolean(KEY_FREEZE_RECENT_TASKS_REORDERING, mFreezeRecentTasksReordering);}if (mDisallowEnterPictureInPictureWhileLaunching) {b.putBoolean(KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING,mDisallowEnterPictureInPictureWhileLaunching);}if (mApplyActivityFlagsForBubbles) {b.putBoolean(KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, mApplyActivityFlagsForBubbles);}if (mAnimSpecs != null) {b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs);}if (mAnimationFinishedListener != null) {b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder());}if (mSpecsFuture != null) {b.putBinder(KEY_SPECS_FUTURE, mSpecsFuture.asBinder());}if (mSourceInfo != null) {b.putParcelable(KEY_SOURCE_INFO, mSourceInfo);}if (mRotationAnimationHint != -1) {b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint);}if (mAppVerificationBundle != null) {b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle);}if (mRemoteAnimationAdapter != null) {b.putParcelable(KEY_REMOTE_ANIMATION_ADAPTER, mRemoteAnimationAdapter);}if (mLaunchCookie != null) {b.putBinder(KEY_LAUNCH_COOKIE, mLaunchCookie);}if (mRemoteTransition != null) {b.putParcelable(KEY_REMOTE_TRANSITION, mRemoteTransition);}if (mOverrideTaskTransition) {b.putBoolean(KEY_OVERRIDE_TASK_TRANSITION, mOverrideTaskTransition);}if (mSplashScreenThemeResName != null && !mSplashScreenThemeResName.isEmpty()) {b.putString(KEY_SPLASH_SCREEN_THEME, mSplashScreenThemeResName);}if (mRemoveWithTaskOrganizer) {b.putBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER, mRemoveWithTaskOrganizer);}if (mLaunchedFromBubble) {b.putBoolean(KEY_LAUNCHED_FROM_BUBBLE, mLaunchedFromBubble);}if (mTransientLaunch) {b.putBoolean(KEY_TRANSIENT_LAUNCH, mTransientLaunch);}if (mSplashScreenStyle != 0) {b.putInt(KEY_SPLASH_SCREEN_STYLE, mSplashScreenStyle);}return b;}
}

二、ActivityThread和Activity生命周期相关的源码调用

1、ActivityThread主要是在Handler的handleMessage方法中,触发Activity的生命回调的。

public final class ActivityThread extends ClientTransactionHandlerimplements ActivityThreadInternal {final H mH = new H();//消息Handlerprivate final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);//管理Activity生命周期的回调class H extends Handler {public static final int EXECUTE_TRANSACTION = 159;public void handleMessage(Message msg) {switch (msg.what) {...代码省略...case EXECUTE_TRANSACTION://触发Activity生命周期回调的关键消息事件final ClientTransaction transaction = (ClientTransaction) msg.obj;mTransactionExecutor.execute(transaction);break;...代码省略...}}}
}

handleMessage方法主要是通过TransactionExecutor的execute方法触发Activity生命周期回调的。

2、TransactionExecutor的execute方法如下所示。

base/core/java/android/app/servertransaction/TransactionExecutor.java

public class TransactionExecutor {private ClientTransactionHandler mTransactionHandler;public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {mTransactionHandler = clientTransactionHandler;//这里的clientTransactionHandler就是ActivityThread对象}public void execute(ClientTransaction transaction) {...代码省略...executeCallbacks(transaction);executeLifecycleState(transaction);...代码省略...}private void executeLifecycleState(ClientTransaction transaction) {...代码省略...cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);...代码省略...}private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,ClientTransaction transaction) {final int start = r.getLifecycleState();final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);performLifecycleSequence(r, path, transaction);}private void performLifecycleSequence(ActivityClientRecord r, IntArray path,ClientTransaction transaction) {final int size = path.size();for (int i = 0, state; i < size; i++) {state = path.get(i);switch (state) {case ON_CREATE: //触发ActivityThread的handleLaunchActivity方法mTransactionHandler.handleLaunchActivity(r, mPendingActions,null /* customIntent */);break;case ON_START: //触发ActivityThread的handleLaunchActivity方法mTransactionHandler.handleStartActivity(r, mPendingActions,null /* activityOptions */);break;case ON_RESUME: //触发ActivityThread的handleResumeActivity方法mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */,r.isForward, "LIFECYCLER_RESUME_ACTIVITY");break;case ON_PAUSE: //触发ActivityThread的handlePauseActivity方法mTransactionHandler.handlePauseActivity(r, false /* finished */,false /* userLeaving */, 0 /* configChanges */, mPendingActions,"LIFECYCLER_PAUSE_ACTIVITY");break;case ON_STOP: //触发ActivityThread的handleStopActivity方法mTransactionHandler.handleStopActivity(r, 0 /* configChanges */,mPendingActions, false /* finalStateRequest */,"LIFECYCLER_STOP_ACTIVITY");break;case ON_DESTROY: //触发ActivityThread的handleDestroyActivity方法mTransactionHandler.handleDestroyActivity(r, false /* finishing */,0 /* configChanges */, false /* getNonConfigInstance */,"performLifecycleSequence. cycling to:" + path.get(size - 1));break;case ON_RESTART: //触发ActivityThread的performRestartActivity方法mTransactionHandler.performRestartActivity(r, false /* start */);break;default:throw new IllegalArgumentException("Unexpected lifecycle state: " + state);}}}
}

TransactionExecutor的execute方法最终会触发ActivityThread和Activity生命周期回调相关的方法。

3、来看下ActivityThread和Activity生命周期回调相关的方法。

public final class ActivityThread extends ClientTransactionHandlerimplements ActivityThreadInternal {Instrumentation mInstrumentation;@Overridepublic Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {...代码省略...//继续调用performLaunchActivity方法final Activity a = performLaunchActivity(r, customIntent);...代码省略...}private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {...代码省略...//通过反射创建Activity实例对象Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);...代码省略...//触发Activity的attach方法,此方法是Activity对象最早被调用的方法activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken, r.shareableActivityToken);...代码省略...//调用Instrumentation的callActivityOnCreate方法,该方法最终会触发Activity的onCreate方法                        if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}...代码省略...}@Overridepublic void handleStartActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, ActivityOptions activityOptions) {final Activity activity = r.activity;...代码省略...//调用Activity的performStart方法activity.performStart("handleStartActivity");...代码省略...}@Overridepublic void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {...代码省略...//调用performResumeActivity方法if (!performResumeActivity(r, finalStateRequest, reason)) {return;}...代码省略...r.window = r.activity.getWindow();View decor = r.window.getDecorView();//添加窗口,在这之后,Actiivty对应的视图才开始可见wm.addView(decor, l);...代码省略...}public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,String reason) {...代码省略...//调用Activity的performResume方法r.activity.performResume(r.startsNotResumed, reason);...代码省略...}@Overridepublic void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving,int configChanges, PendingTransactionActions pendingActions, String reason) {...代码省略...//继续调用performPauseActivity方法performPauseActivity(r, finished, reason, pendingActions);...代码省略...}private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,PendingTransactionActions pendingActions) {...代码省略...//继续调用performPauseActivityIfNeeded方法performPauseActivityIfNeeded(r, reason);...代码省略...        }    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {...代码省略...//调用Instrumentation的callActivityOnPause方法,该方法最终会触发Activity的onPause方法   mInstrumentation.callActivityOnPause(r.activity);...代码省略...}@Overridepublic void handleStopActivity(ActivityClientRecord r, int configChanges,PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {...代码省略...       //继续调用performStopActivityInner方法     performStopActivityInner(r, stopInfo, true /* saveState */, finalStateRequest, reason);...代码省略...                }private void performStopActivityInner(ActivityClientRecord r, StopInfo info,boolean saveState, boolean finalStateRequest, String reason) {...代码省略...        //调用callActivityOnStopcallActivityOnStop(r, saveState, reason);...代码省略...}private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {...代码省略...//调用Activity的performStop方法r.activity.performStop(r.mPreserveWindow, reason);...代码省略...       }@Overridepublic void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,boolean getNonConfigInstance, String reason) {performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);...代码省略...       }void performDestroyActivity(ActivityClientRecord r, boolean finishing,int configChanges, boolean getNonConfigInstance, String reason) {...代码省略...          if (!r.stopped) {callActivityOnStop(r, false /* saveState */, "destroy");}...代码省略...      //调用Instrumentation的callActivityOnDestroy方法,该方法最终会触发Activity的OnDestroy方法   mInstrumentation.callActivityOnDestroy(r.activity);...代码省略...      }@Overridepublic void performRestartActivity(ActivityClientRecord r, boolean start) {if (r.stopped) {//调用Activity的performRestart方法r.activity.performRestart(start, "performRestartActivity");if (start) {r.setState(ON_START);}}}
}

结合以上代码可以发现ActivityThread很多时候会进一步通过Instrumentation来触发Activity的生命周期回调。

4、简单来看下Instrumentation的相关源码。

base/core/java/android/app/Instrumentation.java

public class Instrumentation {public void callActivityOnCreate(Activity activity, Bundle icicle) {prePerformCreate(activity);activity.performCreate(icicle);//调用Activity的performCreate方法postPerformCreate(activity);}public void callActivityOnStart(Activity activity) {activity.onStart();//调用Activity的onStart方法}public void callActivityOnResume(Activity activity) {activity.mResumed = true;activity.onResume();//调用Activity的onResume方法...代码省略...}public void callActivityOnStop(Activity activity) {activity.onStop();//调用Activity的onResume方法}public void callActivityOnDestroy(Activity activity) {      activity.performDestroy();//调用Activity的performDestroy方法}
}    

5、最后来看下Activity和生命周期回调相关的方法

base/core/java/android/app/Activity.java

public class Activity extends ContextThemeWrapperimplements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,Window.OnWindowDismissedCallback,AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,IBinder shareableActivityToken) {...代码省略...mInstrumentation = instr;...代码省略...}final void performCreate(Bundle icicle, PersistableBundle persistentState) {...代码省略...if (persistentState != null) {onCreate(icicle, persistentState);} else {onCreate(icicle);}...代码省略...        }protected void onCreate(@Nullable Bundle savedInstanceState) {...代码省略...        }final void performStart(String reason) {...代码省略...       //调用Instrumentation的callActivityOnPause方法,该方法最终会触发Activity的onStart方法        mInstrumentation.callActivityOnStart(this);...代码省略...        }protected void onStart() {...代码省略...      }final void performResume(String reason) {    ...代码省略...       //调用Instrumentation的callActivityOnResume方法,该方法最终会触发Activity的onResume方法           mInstrumentation.callActivityOnResume(this);...代码省略...       }protected void onResume() {...代码省略...      }protected void onPause() {...代码省略...      }final void performStop(boolean preserveWindow, String reason) {...代码省略...    //调用Instrumentation的callActivityOnStop方法,该方法最终会触发Activity的OnStop方法               mInstrumentation.callActivityOnStop(this);...代码省略...    }protected void onStop() {...代码省略...    }final void performDestroy() {...代码省略...    onDestroy();...代码省略...    }protected void onDestroy() {...代码省略...    }
}

三、Activity和窗口动画相关的源码

1、在分析窗口动画和Window相关的源码之前,我们需要简单了解一下Activity是如何将窗口动画相关的参数传递给窗口的。

public class Activity extends ContextThemeWrapperimplements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,Window.OnWindowDismissedCallback,AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {private Window mWindow;final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,IBinder shareableActivityToken) {...代码省略...mWindow = new PhoneWindow(this, window, activityConfigCallback);...代码省略...}public Window getWindow() {return mWindow;//这里获取的是PhoneWindow}public void setContentView(@LayoutRes int layoutResID) {getWindow().setContentView(layoutResID);//调用PhoneWindow的setContentView方法initWindowDecorActionBar();}}

系统最早是在Activity的attach方法中创建其对应的PhoneWindow的,然后会在setContentView方法中调用PhoneWindow的setContentView方法。

2、PhoneWindow的setContentView方法如下所示。

base/core/java/com/android/internal/policy/PhoneWindow.java

public class PhoneWindow extends Window implements MenuBuilder.Callback {private final static int DEFAULT_BACKGROUND_FADE_DURATION_MS = 300;//默认的动效时间private static final Transition USE_DEFAULT_TRANSITION = new TransitionSet();//默认的窗口切换动效private Transition mEnterTransition = null;//进入动效private Transition mReturnTransition = USE_DEFAULT_TRANSITION;//返回动效private Transition mExitTransition = null;//退出动效private Transition mReenterTransition = USE_DEFAULT_TRANSITION;//从另一个Window返回当前Window的动效private Transition mSharedElementEnterTransition = null;//共享元素的进入动效private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION;//共享元素的返回动效private Transition mSharedElementExitTransition = null;//共享元素的退出动效private Transition mSharedElementReenterTransition = USE_DEFAULT_TRANSITION;//从另一个Window返回当前Window的共享元素动效private Boolean mAllowReturnTransitionOverlap;//是否允许返回动效private Boolean mAllowEnterTransitionOverlap;//是否允许进入动效private long mBackgroundFadeDurationMillis = -1;//转换动效的时间private Boolean mSharedElementsUseOverlay;  //是否允许共享元素动效@Overridepublic void setContentView(int layoutResID) {if (mContentParent == null) {installDecor();//调用installDecor} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {mContentParent.removeAllViews();}...代码省略...}private void installDecor() {...代码省略...//检查设备是否支持活动(Activity)之间的转换过渡效果,旨在提供更为流畅和吸引人的界面转场动画。if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {if (mTransitionManager == null) {final int transitionRes = getWindowStyle().getResourceId(R.styleable.Window_windowContentTransitionManager,0);if (transitionRes != 0) {final TransitionInflater inflater = TransitionInflater.from(getContext());mTransitionManager = inflater.inflateTransitionManager(transitionRes,mContentParent);} else {mTransitionManager = new TransitionManager();}}//和窗口相关的转换动效mEnterTransition = getTransition(mEnterTransition, null,R.styleable.Window_windowEnterTransition);mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,R.styleable.Window_windowReturnTransition);mExitTransition = getTransition(mExitTransition, null,R.styleable.Window_windowExitTransition);mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,R.styleable.Window_windowReenterTransition);mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,R.styleable.Window_windowSharedElementEnterTransition);mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,USE_DEFAULT_TRANSITION,R.styleable.Window_windowSharedElementReturnTransition);mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,R.styleable.Window_windowSharedElementExitTransition);mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,USE_DEFAULT_TRANSITION,R.styleable.Window_windowSharedElementReenterTransition);if (mAllowEnterTransitionOverlap == null) {mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(R.styleable.Window_windowAllowEnterTransitionOverlap, true);}if (mAllowReturnTransitionOverlap == null) {mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(R.styleable.Window_windowAllowReturnTransitionOverlap, true);}if (mBackgroundFadeDurationMillis < 0) {mBackgroundFadeDurationMillis = getWindowStyle().getInteger(R.styleable.Window_windowTransitionBackgroundFadeDuration,DEFAULT_BACKGROUND_FADE_DURATION_MS);}if (mSharedElementsUseOverlay == null) {mSharedElementsUseOverlay = getWindowStyle().getBoolean(R.styleable.Window_windowSharedElementsUseOverlay, true);}}}
}

3、继续来看Activity和窗口动画相关的源码。

public class Activity extends ContextThemeWrapperimplements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,Window.OnWindowDismissedCallback,AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;   final void performCreate(Bundle icicle, PersistableBundle persistentState) {...代码省略...      mActivityTransitionState.readState(icicle);...代码省略...//将Window的进入动画存入mActivityTransitionStatemActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());...代码省略...}final void performStart(String reason) {...代码省略...//将Window的进入动画存入mActivityTransitionStatemActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());...代码省略...mActivityTransitionState.enterReady(this);...代码省略...}protected void onResume() {...代码省略...mActivityTransitionState.onResume(this);...代码省略...}protected void onStop() {...代码省略...mActivityTransitionState.onStop(this);...代码省略...}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/5931.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构 - C/C++

快速跳转 数组链表栈队列串树 目录 数据结构 逻辑结构 物理结构 数据结构 数据 数据不仅仅包括整型、实型等数值类型&#xff0c;还包括字符及声音、图像、视频等非数值类型。 计算机可以理解并按照指定格式处理。 结构 元素相互之间存在一种或多种特定关系的数据集合。 …

tuxera ntfs for mac是什么 tuxera ntfs for mac怎么用 tuxera激活码

Tuxera NTFS for Mac是一款完全的mac读写软件&#xff0c;可辅助mac电脑读写ntfs格式&#xff0c;进行磁盘的管理。本文会详细讲解tuxera ntfs for mac的操作方法。 Tuxera NTFS for Mac 2023安装包免费下载&#xff1a;https://souurl.cn/IE35lO 一、Tuxera NTFS for Mac是什…

goget配置多个golang 运行环境

一台主机安装多个golang 运行环境 本环境 windows10 为 基础 mac linux也可以按照此方法操作 背景 开发不同的运维工具会用到不同版本的golang&#xff0c;但是开发者不能一直进行重装来处理 &#xff0c;因此 需要一个工具进行golang版本的管理 go管理工具介绍 gvm (Go V…

微服务保护和分布式事务(Sentinel、Seata)笔记

一、雪崩问题的解决的服务保护技术了解 二、Sentinel 2.1Sentinel入门 1.Sentinel的安装 &#xff08;1&#xff09;下载Sentinel的tar安装包先 &#xff08;2&#xff09;将jar包放在任意非中文、不包含特殊字符的目录下&#xff0c;重命名为 sentinel-dashboard.jar &…

【C++报错】error C2143:语法错误:缺少“ : ”(在“<” 的前面)[ 相互引用问题 ]

这里写自定义目录标题 情景再现问题分析是经典的互相引用问题 解决方案 情景再现 问题分析 template<class K,class T,class KeyofT,class Hash>class __HTIterator{typedef HashNode<T> Node;typedef HashTable<K, T, KeyofT, Hash> HT; 【★】typedef …

Halcon如何制作标定板的关键点

前面用下面算子生成文件和PS文件&#xff0c;我就不说了&#xff0c;太多人说了 gen_caltab(7,7,0.0125,0.5,caltab_120mm.descr,120_120.ps) 生成之后&#xff0c;大部分人.ps文件是用PhotoShop打开&#xff0c;然后去打印&#xff0c;再做后续的标定等工序&#xff0c;但是打…

基于springboot+vue+Mysql的网上商城购物系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

Java创建并遍历N叉树(前序遍历)

力扣 title589&#xff1a;N叉树的前序遍历 给定一个 n 叉树的根节点 root &#xff0c;返回 其节点值的 前序遍历 。 n 叉树 在输入中按层序遍历进行序列化表示&#xff0c;每组子节点由空值 null 分隔&#xff08;请参见示例&#xff09;。 思路&#xff1a; 1.初始化时…

AtCoder Beginner Contest 351 E题 Jump Distance Sum

E题&#xff1a;Jump Distance Sum 标签&#xff1a;思维题意&#xff1a;在坐标平面上&#xff0c;有 N N N个点 P 1 , P 2 , … , P N P_1,P_2,…,P_N P1​,P2​,…,PN​&#xff0c;其中点 P i P_i Pi​的坐标为 ( X i , Y i ) (X_i,Y_i) (Xi​,Yi​)。两点 A A A与 B B B之…

[ACTF2020 新生赛]BackupFile 1 [极客大挑战 2019]BuyFlag 1 [护网杯 2018]easy_tornado 1

目录 [ACTF2020 新生赛]BackupFile 1 1.打开页面&#xff0c;叫我们去找源文件 2.想到用disearch扫描&#xff0c;发现源文件index.php.bak 3.访问这个文件&#xff0c;下载一个文件&#xff0c;用记事本打开 4.翻译php代码 5.构造payload url/?key123&#xff0c;得到fl…

在不同操作系统上自动生成Protocol Buffers的Java语言包的方法2

在《在不同操作系统上自动生成Protocol Buffers的Java语言包的方法》中我们使用了protobuf-maven-plugin插件来给Proto文件生成Java语言版代码。本文我们将使用一种更简单的插件来完成这个功能。 本文实验的操作系统和代码库都和《在不同操作系统上自动生成Protocol Buffers的J…

如何配置和使用Apollo的component里的plugin

关于如何使用Apollo的Component里的plugin&#xff0c;在Apollo的文档里只有如果和开发的说明却没有找到一个清楚完整说明怎么把plugin跑起来的说明&#xff0c;例如我想把lidar_detection_filter按我们的需求对目标过滤算法作修改然后编译完后&#xff0c;执行 cyber_launch …

IoTDB 入门教程④——数据库用户管理和用户权限管理

文章目录 一、前文二、修改ROOT密码三、用户登录四、查看用户列表五、创建用户六、删除用户七、修改用户八、查看指定用户的权限范围九、添加指定用户的权限范围十、删除指定用户的权限范围十一、参考 一、前文 IoTDB入门教程——导读 本文主要讲述数据库用户管理和用户权限管理…

【七十三】【算法分析与设计】516. 最长回文子序列,二叉树,329. 矩阵中的最长递增路径,记忆化递归填表

516. 最长回文子序列 给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列。 示例 1&#xff1a; 输入&#xff1a;s &qu…

《QT实用小工具·五十一》带动画的 CheckBox

1、概述 源码放在文章末尾 该项目实现了带动画效果的多选框&#xff0c;鼠标放在上面或者选中都会呈现炫酷的动画效果&#xff0c;demo演示如下&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef LINEARCHECKBOX_H #define LINEARCHECKBOX_H#include <QCheckBox> …

2024年北京高校数学建模校际联赛竞赛赛题浅析

一图流&#xff1a; 题目复杂性技术需求数据处理主要难点A题&#xff1a;格陵兰入海冰川3气象学、物理学、环境科学时间序列分析、空间数据处理多学科集成、预测模型的准确性和策略制定B题&#xff1a;铁道线路动态检测数据分析1数据科学、机器学习、信号处理实时数据流处理、异…

Vue Json stringify() 转换和过滤

参考 JS/TS 对象转成JSON string 字符串 过滤其中的部分项 allMenu.value.forEach((_item) > {console.log(JSON.stringify(_item, [menuId]))})console.log(JSON.stringify(_item, [menuId, menuName])) 一下方法需要进一步核对&#xff0c;没有调试通过 console.log(JS…

OPPO手机支持深度测试+免深度测试解锁BL+ROOT权限机型整理-2024年3月更新

绿厂OPPO手机线上线下卖的都很不错&#xff0c;目前市场份额十分巨大&#xff0c;用户自然也非常多&#xff0c;而近期ROM乐园后台受到很多关于OPPO手机的私信&#xff0c;咨询哪些机型支持解锁BL&#xff0c;ROOT刷机&#xff0c;今天ROM乐园正式盘点当前市场上可以解BL刷root…

Mysql-黑马

Mysql-黑马 编写规范&#xff1a;## 一级1. 二级三级 1.Mysql概述 数据库概念mysql数据仓库 cmd启动和停止 net start mysql180 net stop mysql180备注&#xff1a;其中的mysql180是服务名 客户端连接 远程连接数据仓库 -h 主机号 -P端口号 mysql [-h 127.0.0.1] [-P 33…

1083 是否存在相等的差

solution 输出的是重复的差值&#xff0c;而非全部差值 #include<iostream> #include<algorithm> using namespace std; const int maxn 1e4 10; int flag[maxn] {0}; int main(){int n, x;scanf("%d", &n);for(int i 1; i < n; i){scanf(&…