我是靠谱客的博主 天真仙人掌,这篇文章主要介绍全面了解Window,现在分享给大家,希望可以做个参考。

前置知识

  1. Window是什么?Window是一个组件,View是由Window呈现出来的。Window实际上就是管理着View,对Window的操作最终都会转化成对View的操作。
  2. 经常使用的WindowActivityDialogPopupWindowToast等。系统中常见的WindowStatusBarNavigationBarInputMethod(软键盘)等。StatusBarNavigationBar等是在单独的进程中使用的。

问题

1.WindowManager.LayoutParam(继承ViewGroup.LayoutParams)类很重要,flagstype 等等。

type,相当于Window 的类型,主要分为3大类。

  • 1-99对应应用Window(token 必须设置为Activity 的token,即Context需要设置为Activity)。Activity 中的Window 对应的type 是TYPE_BASE_APPLICATIONDialog默认的是TYPE_APPLICATIONWindowManager.LayoutParams默认构造函对应的type也是TYPE_APPLICATION
  • 1000-1999对应子Window。PopupWindow 默认是TYPE_APPLICATION_PANEL
  • 2000-2999 对应的是系统Window。Toast对应TYPE_TOAST,StatusBar对应TYPE_STATUS_BARNavigationBar对应TYPE_NAVIGATION_BAR,键盘对应着”TYPE_INPUT_METHOD”。

flags,各种不一样属性,控制Window 的一些特殊显示。

2.DialogPopupWindow的异同。

  • DialogPopupWindoow 都会在一个新的Window中展示。
  • Dialog不能使用ApplicationContext,上面就可以知道Dailog是应用Window,只能使用Activity
  • PopupWindow不能在Activity.onCreate中创建。PopupWindow默认是一个子Window,需要在Activity创建以后使用。
  • PopupWindow一定需要设置widthheight,默认是0。
  • Dialog是创建了一个PhoneWindow然后获取的DecorView,所有默认有Title,而PopupWindow没有。
  • PopupWindow默认不会响应Back键,可以设置popupWindow.setFocusable(true);
  • 通过Activity来管理Dialog的时候,Activity.mManagedDialogs,当Activity后台销毁的时候再次进入可以恢复(参考Dialog.onSaveInstanceStateDialog.onRestoreInstanceState)。而PopupWindow没有恢复机制。

至于网上很多说PopupWindow是阻塞式的而Dialog是非阻塞式的,是非常误解人的。关于坑爹的PopupWindow的“阻塞”争议问题:Android没有真正的“阻塞式”对话框

3.Toast展示以后可以将Toast点击的事件传递到下面的View,Dialog以及Popupindow都不行,跟WindowManager.LayoutParams.flags有关。

4.Activity设置windowSoftInputMode属性的时候,会对ActivityWindow有一些影响。

5.一个App 中有多少个Window?应该是某个状态下Window的个数,Activity+Dialog+PopupWindow+Toast+WindowManage.addView

基本操作

WindowManager继承ViewManager,基本的操作如下。操作的实际上是ViewWindowManagerImpl保存着一族对应的mViewsmRootsmParams。对于每一个展示的Window实际上对应着mViews[k]mRoots[k]mParams[k]。具体可以看后面的流程分析。

复制代码
1
2
3
4
// ViewManager.java public void addView(View view, ViewGroup.LayoutParams params); public void updateViewLayout(View view, ViewGroup.LayoutParams params); public void removeView(View view);

流程分析

Window.setStatusBarColor流程(api 21以上)。

StatusBarNavigationBar都是一个View展示在最上面和最下面??

1.Window.setStatusBarColor`。

复制代码
1
2
3
4
5
6
7
8
9
10
// PhoneWindow.java @Override public void setStatusBarColor(int color) { mStatusBarColor = color; mForcedStatusBarColor = true; if (mDecor != null) { // 直接调用到了DecorView.updateColorViews() mDecor.updateColorViews(null, false /* animate */); } }

2.DecorView.updateColorViews。从代码中看就是修改了mNavigationColorViewStatemStatusColorViewState里面包含的ViewbackgroundColor

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// DecorView.java private WindowInsets updateColorViews(WindowInsets insets, boolean animate) { // insets null animate false WindowManager.LayoutParams attrs = getAttributes(); // 获取系统状态栏的显示属性 int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility(); if (!mIsFloating && ActivityManager.isHighEndGfx()) { boolean disallowAnimate = !isLaidOut(); disallowAnimate |= ((mLastWindowFlags ^ attrs.flags) & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; mLastWindowFlags = attrs.flags; if (insets != null) { // 省略相关代码 } // 这里相当于是横竖屏判断 boolean navBarToRightEdge = mLastBottomInset == 0 && mLastRightInset > 0; int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset; // 更新Navigation updateColorViewInt(mNavigationColorViewState, sysUiVisibility, mNavigationBarColor, navBarSize, navBarToRightEdge, 0 /* rightInset */, animate && !disallowAnimate); boolean statusBarNeedsRightInset = navBarToRightEdge && mNavigationColorViewState.present; int statusBarRightInset = statusBarNeedsRightInset ? mLastRightInset : 0; // 更新Status updateColorViewInt(mStatusColorViewState, sysUiVisibility, mStatusBarColor, mLastTopInset, false /* matchVertical */, statusBarRightInset, animate && !disallowAnimate); } // 省略代码 return insets; }

3.DecorView.updateColorViewInt

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// DecorView.java private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color, int size, boolean verticalBar, int rightMargin, boolean animate, boolean force) { // animate false state.present = (sysUiVis & state.systemUiHideFlag) == 0 && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0 && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 || force); boolean show = state.present && (color & Color.BLACK) != 0 && ((mWindow.getAttributes().flags & state.translucentFlag) == 0 || force); boolean showView = show && !isResizing() && size > 0; boolean visibilityChanged = false; View view = state.view; int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size; int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT; // 横屏和竖屏展示的为位置不一样,分别对应着设置的horizontalGravity和verticalGravity int resolvedGravity = verticalBar ? state.horizontalGravity : state.verticalGravity; if (view == null) { if (showView) { // 为空会创建。相当于创建了Navigation 和Status View // 即改变StatusBar/NavigationBar 实际上是改变了一个View 的颜色 state.view = view = new View(mContext); view.setBackgroundColor(color); view.setTransitionName(state.transitionName); view.setId(state.id); visibilityChanged = true; view.setVisibility(INVISIBLE); state.targetVisibility = VISIBLE; LayoutParams lp = new LayoutParams(resolvedWidth, resolvedHeight, resolvedGravity); lp.rightMargin = rightMargin; addView(view, lp); updateColorViewTranslations(); } } else { int vis = showView ? VISIBLE : INVISIBLE; visibilityChanged = state.targetVisibility != vis; state.targetVisibility = vis; LayoutParams lp = (LayoutParams) view.getLayoutParams(); if (lp.height != resolvedHeight || lp.width != resolvedWidth || lp.gravity != resolvedGravity || lp.rightMargin != rightMargin) { lp.height = resolvedHeight; lp.width = resolvedWidth; lp.gravity = resolvedGravity; lp.rightMargin = rightMargin; view.setLayoutParams(lp); } if (showView) { view.setBackgroundColor(color); } } // 省略颜色修改无关代码 state.visible = show; state.color = color; }

setStatusBarColor(api 21以上)这个流程可以分析出来,ActivityDecoeViewStatusBarNavigationBar对应的是一个普通的View(系统中的StatusBarNavigationBar都对应着一个WindowStatusBar中展示的电量、wifi等都是Window中的ViewNavigationBar中展示的返回键、Home键等也是Window中的View)。可以通过反射改变StatusBar颜色和大小来验证(看源码也行的)DecoeView对应着的是普通的View

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** * 利用反射来设置StatusBar(DecorView中对应的StatusBar)颜色和高度(需要api21 以上) */ public void changeStatusBarColor2(View view) { // reflect 改变 try { Field field = getWindow().getDecorView().getClass().getDeclaredField("mStatusColorViewState"); field.setAccessible(true); Object object = field.get(getWindow().getDecorView()); Field objectField = object.getClass().getDeclaredField("view"); objectField.setAccessible(true); View view1 = (View) objectField.get(object); Log.e("ChangeStatusBarColor", "status bar height = " + view1.getHeight()); view1.setBackgroundColor(0xffff0000); ViewGroup.LayoutParams params = view1.getLayoutParams(); params.height = 200; view1.setLayoutParams(params); } catch (Exception e) { e.printStackTrace(); } }

WindowManager.addView()流程。

1.执行到WindowManagerImpl.addView()WindowManagerImpl继承WindowManager)。

复制代码
1
2
3
4
5
6
7
// WindowManagerImpl.java @Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); // 在Activity 中调用的话,这里的mParentWindow 就会是Activity 中的Window。 mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); }

2.执行到WindowManagerGlobal.addView() 方法。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// WindowManagerGlobal.java public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (display == null) { throw new IllegalArgumentException("display must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; ... // 省略很多代码 ViewRootImpl root; synchronized (mLock) { ... // 省略很多代码 root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); // 在mViews中增加了需要add 的View mRoots.add(root); // 在mRoots 中增加新的ViewRootImpl mParams.add(wparams); // mParams 中增加新的WindowManager.LayoutParams } try { root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { synchronized (mLock) { final int index = findViewLocked(view, false); if (index >= 0) { removeViewLocked(index, true); } } throw e; } }

一个WindowManager中对应着一系列的mViewsmRootsmParams,也就是WindowManager管理着多个Window,每一个Window都对应着mViews[k]mRoots[k]mParams[k]如下所示。

复制代码
1
2
3
4
5
// WindowManagerGlobal.java private final ArrayList<View> mViews = new ArrayList<View>(); private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>(); private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();

3.执行到ViewRootImpl.setView()方法。ViewRootImpl相当于ViewViewManager之间的桥梁。里面的代码比较的长,会执行到ViewRootImpl.requestLayout()

4.执行到ViewRootImpl.requestLayout()方法以及mWindowSession.addToDisplay,其中ViewRootImpl.requestLayout()会接着执行到了ViewRootImpl.scheduleTraversals()

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ViewRootImpl.java void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); // 这里通过mChoreographer.postCallback,最后相当于通过Handler发送了一个消息 //最后会执行到mTraversalRunnable的run mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); if (!mUnbufferedInputDispatch) { scheduleConsumeBatchedInput(); } notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } }

5.执行到TraversalRunnable.run(),最后执行到了ViewRootImpl.doTraversal()

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ViewRootImpl.java void doTraversal() { if (mTraversalScheduled) { mTraversalScheduled = false; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); if (mProfile) { Debug.startMethodTracing("ViewAncestor"); } performTraversals(); if (mProfile) { Debug.stopMethodTracing(); mProfile = false; } } }

6.执行到ViewRootImpl.performTraversals()。计算希望的大小,
判断是否是第一次,判断视图是否修改(例如:内容区域),判断Window 是否需要调整大小,判断是否改变了View 的可见性。最后会执行到ViewRootImpl.performMeasure()ViewRootImpl.performLayout()ViewRootImpl.performDraw()

7.ViewRootImpl.performMeasure()会调用View.measure对View进行测量;ViewRootImpl.performLayout()会调用View.layout对View进行布局。ViewRootImpl.performDraw()会调用ViewRootImpl.draw,然后会调用到ViewRootImpl.drawSoftware,最后就会调用到View.draw。这一系列的操作完成以后就会相当于展示创建了一个View,大小、位置以及视图也完全处理完毕。

8.第4步中执行到ViewRootImpl.requestLayout()以后的过程已经分析完毕,相当于是对View 进行了测量、布局以及绘制。接下来执行mWindowSession.addToDisplaymWindowSession对应的是一个IWindowSession.aidl,Java 层实现的类是com.android.server.wm.Session

复制代码
1
2
3
4
5
6
7
8
@Override public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) { // mService 对应的是WindowManagerService return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outContentInsets, outStableInsets, outOutsets, outInputChannel); }

9.执行WindowManagerService.addWindow。这里就是Window的添加等,没有细看。

总结:通过WindowManagerWindow的操作实际上就是对里面View的操作,展示的也是里面View的信息。

WindowManager.removeView()流程。

这里有一个问题需要考虑一下,通过Activity.getWindowManager().removeView(View view),这里removeView的参数是什么?Activity中设置的View中的一个子View`吗?

addView第2步就有说明,这个View其实是一个整体的View,不是某个View中的子View而是一个Window 中展示的View。

1.直接看到WindowManagerGlobal.removeView()

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// WindowManagerGlobal.java public void removeView(View view, boolean immediate) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } synchronized (mLock) { // 获取到view 对应的index,默认是-1 int index = findViewLocked(view, true); View curView = mRoots.get(index).getView(); removeViewLocked(index, immediate); if (curView == view) { return; } throw new IllegalStateException("Calling with view " + view + " but the ViewAncestor is attached to " + curView); } }

2.执行WindowManagerGlobal.removeViewLocked

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// WindowManagerGlobal.java private void removeViewLocked(int index, boolean immediate) { ViewRootImpl root = mRoots.get(index); View view = root.getView(); if (view != null) { InputMethodManager imm = InputMethodManager.getInstance(); // 执行remove 操作。 if (imm != null) { imm.windowDismissed(mViews.get(index).getWindowToken()); } } // 执行die 操作。 boolean deferred = root.die(immediate); if (view != null) { view.assignParent(null); if (deferred) { // 将View 加入到mDyingViews 中。 mDyingViews.add(view); } } }

总结:removeView也是对View的操作。

PopupWindow显示流程

showAsDropDown(View anchor)/showAtLocation(View parent, int gravity, int x, int y)preparePopup(WindowManager.LayoutParams p),最后invokePopup(WindowManager.LayoutParams p),这里不再分析。

Dialog显示流程

show(),这里不再分析。

其它内容

1.查看当前Window的信息

复制代码
1
2
3
4
5
6
Egos-MacBook-Pro:~ Egos$ adb shell dumpsys window windows | grep -E 'mCurrentFocus' // Activity 对应的当前Window 信息 mCurrentFocus=Window{1cd90da2 u0 com.egos.samples/com.egos.samples.window.WindowActivity} Egos-MacBook-Pro:~ Egos$ adb shell dumpsys window windows | grep -E 'mCurrentFocus' // Activity 打开PopupWindow(使用Dialog 的时候效果也是一样的)之后对应的当前Window 信息 mCurrentFocus=Window{1ad2aefa u0 com.egos.samples/com.egos.samples.window.WindowActivity}

2.adb shell dumpsys window 查看当前所有的Window信息,包括Window的大小、位置。下面一个例子,拿中Window #3 来展示mAttrs就展示了大小,mHasSurface展示了起始位置。WindownManage.LayoutParams.mTitle 对应了名称。

复制代码
1
2
3
4
5
6
7
8
9
Window #3 Window{914ba56 u0 com.egos.samples/com.egos.samples.window.WindowActivity}: mDisplayId=0 stackId=1 mSession=Session{b853937 2930:u0a10102} mClient=android.os.BinderProxy@4d81c71 mOwnerUid=10102 mShowToOwnerOnly=true package=com.egos.samples appop=NONE mAttrs=WM.LayoutParams{(0,0)(200x200) sim=#20 ty=2 fl=#0} Requested w=200 h=200 mLayoutSeq=152 mHasSurface=true mShownPosition=[440,824] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{31dbad7 com.egos.samples/com.egos.samples.window.WindowActivity}: Surface: shown=true layer=21015 alpha=1.0 rect=(440.0,824.0) 200.0 x 200.0

一个详细的例子。下面总共有9个Window(0,1,..8),可以看到NavigationBarStatusBar(StatusBarWindowManager管理着StatusBar Window的)等其实都是Window。也非常好验证,将StatusBar向下滑动唤出全屏的通知栏,执行adb shell dumpsys window会发现StatusBar 变成了全屏(从mAttrs可以看出)。

PS:PhoneStatusBar.java控制着StatusBarNavigationBar。详情可以查看源码frameworks.base.packages.SystemUI包下面的代码,包含了StatusBarNavigationBar、截屏Window、锁屏Window等。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
Egos-MacBook-Pro:aosp Egos$ adb shell dumpsys window //.. 这里省略了很多信息,下面总共有9个Window(0,1,..8) WINDOW MANAGER WINDOWS (dumpsys window windows) Window #8 Window{c65e61c u0 NavigationBar}: mDisplayId=0 stackId=0 mSession=Session{39b4687 2046:u0a10023} mClient=android.os.BinderProxy@d23238f mOwnerUid=10023 mShowToOwnerOnly=false package=com.android.systemui appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#20 ty=2019 fl=#1840068 fmt=-3} Requested w=1080 h=144 mLayoutSeq=271 mHasSurface=true mShownPosition=[0,1776] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{4b5dd83 NavigationBar}: mAnimating=false mLocalAnimating=false mAnimationIsEntrance=true mAnimation=null mStackClip=1 Surface: shown=true layer=211000 alpha=1.0 rect=(0.0,1776.0) 1080.0 x 144.0 Window #7 Window{6fa7c9a u0 StatusBar}: mDisplayId=0 stackId=0 mSession=Session{39b4687 2046:u0a10023} mClient=android.os.BinderProxy@4f62d45 mOwnerUid=10023 mShowToOwnerOnly=false package=com.android.systemui appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillx72) gr=#30 sim=#10 ty=2000 fl=#81840048 fmt=-3 vsysui=0x600} Requested w=1080 h=72 mLayoutSeq=271 mHasSurface=true mShownPosition=[0,0] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{83a4c32 StatusBar}: mAnimating=false mLocalAnimating=false mAnimationIsEntrance=true mAnimation=null mStackClip=1 Surface: shown=true layer=161000 alpha=1.0 rect=(0.0,0.0) 1080.0 x 72.0 Window #6 Window{7cba79f u0 KeyguardScrim}: mDisplayId=0 stackId=0 mSession=Session{ddf9b54 1962:1000} mClient=android.view.ViewRootImpl$W@2c300ec mOwnerUid=1000 mShowToOwnerOnly=false package=android appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#10 ty=2029 fl=#1110900 pfl=0x1 fmt=-3 or=5 vsysui=0x3610000} Requested w=1080 h=1776 mLayoutSeq=58 mHasSurface=false mShownPosition=[0,0] isReadyForDisplay()=false hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{b8b9c3d KeyguardScrim}: mLastFreezeDuration=+2m59s819ms Window #5 Window{401d23f u0 AssistPreviewPanel}: mDisplayId=0 stackId=0 mSession=Session{39b4687 2046:u0a10023} mClient=android.os.BinderProxy@eb66e5e mOwnerUid=10023 mShowToOwnerOnly=true package=com.android.systemui appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillx750) gr=#800053 sim=#31 ty=2033 fl=#1000118 fmt=-3 vsysui=0x700} Requested w=0 h=0 mLayoutSeq=57 mHasSurface=false mShownPosition=[0,0] isReadyForDisplay()=false hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{10d4994 AssistPreviewPanel}: mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0 Window #4 Window{7af7b99 u0 DockedStackDivider}: mDisplayId=0 stackId=0 mSession=Session{39b4687 2046:u0a10023} mClient=android.os.BinderProxy@ab9dce0 mOwnerUid=10023 mShowToOwnerOnly=false package=com.android.systemui appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillx144) sim=#20 ty=2034 fl=#21840028 pfl=0x40 fmt=-3 vsysui=0x700} Requested w=1080 h=144 mLayoutSeq=271 mPolicyVisibility=false mPolicyVisibilityAfterAnim=false mAppOpVisibility=true mAttachedHidden=false mHasSurface=false mShownPosition=[0,0] isReadyForDisplay()=false hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{d3489e7 DockedStackDivider}: mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0 Window #3 Window{699ad0c u0 com.egos.samples/com.egos.samples.toast.ToastActivity}: mDisplayId=0 stackId=1 mSession=Session{153e999 3360:u0a10102} mClient=android.os.BinderProxy@e9ef03f mOwnerUid=10102 mShowToOwnerOnly=true package=com.egos.samples appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#120 ty=1 fl=#81810100 pfl=0x20000 wanim=0x1030465 vsysui=0x600 needsMenuKey=2} Requested w=1080 h=1704 mLayoutSeq=271 mHasSurface=true mShownPosition=[0,0] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{7b190d3 com.egos.samples/com.egos.samples.toast.ToastActivity}: Surface: shown=true layer=21015 alpha=1.0 rect=(0.0,0.0) 1080.0 x 1920.0 Window #2 Window{df42f03 u0 com.android.launcher3/com.android.launcher3.Launcher}: mDisplayId=0 stackId=0 mSession=Session{da8c367 2497:u0a10014} mClient=android.os.BinderProxy@820f3b2 mOwnerUid=10014 mShowToOwnerOnly=true package=com.android.launcher3 appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#120 ty=1 fl=#81910100 fmt=-2 wanim=0x1030465 vsysui=0x700 needsMenuKey=2} Requested w=1080 h=1920 mLayoutSeq=227 mHasSurface=false mShownPosition=[0,0] isReadyForDisplay()=false hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{371f101 com.android.launcher3/com.android.launcher3.Launcher}: mLastFreezeDuration=+2m59s941ms mWallpaperX=0.0 mWallpaperY=0.5 Window #1 Window{2126153 u0 com.android.systemui/com.android.systemui.recents.RecentsActivity}: mDisplayId=0 stackId=0 mSession=Session{39b4687 2046:u0a10023} mClient=android.os.BinderProxy@c0a3d42 mOwnerUid=10023 mShowToOwnerOnly=true package=com.android.systemui appop=NONE mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#120 ty=1 fl=#81910100 pfl=0x24040 fmt=-3 vsysui=0x700 needsMenuKey=2} Requested w=1080 h=1920 mLayoutSeq=187 mHasSurface=false mShownPosition=[0,0] isReadyForDisplay()=false hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{9f984a2 com.android.systemui/com.android.systemui.recents.RecentsActivity}: mAnimating=true mLocalAnimating=false mAnimationIsEntrance=false mAnimation=null mStackClip=1 XForm: has=true hasLocal=false {alpha=1.0 matrix=[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]} mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0 mGlobalScale=1.0 mDsDx=1.0 mDtDx=0.0 mDsDy=0.0 mDtDy=1.0 Window #0 Window{c4fa95f u0 com.android.systemui.ImageWallpaper}: mDisplayId=0 stackId=0 mSession=Session{39b4687 2046:u0a10023} mClient=android.os.BinderProxy@6adfe mOwnerUid=10023 mShowToOwnerOnly=true package=com.android.systemui appop=NONE mAttrs=WM.LayoutParams{(0,0)(1920x1920) gr=#800033 ty=2013 fl=#318 fmt=1 wanim=0x10302f2} Requested w=1920 h=1920 mLayoutSeq=238 mIsImWindow=false mIsWallpaper=true mIsFloatingLayer=true mWallpaperVisible=false mHasSurface=true mShownPosition=[0,0] isReadyForDisplay()=false hasSavedSurface()=false mWindowRemovalAllowed=false WindowStateAnimator{860a6e8 com.android.systemui.ImageWallpaper}: Surface: shown=false layer=21000 alpha=1.0 rect=(0.0,0.0) 1920.0 x 1920.0 mLastFreezeDuration=+2m58s925ms mWallpaperX=0.0 mWallpaperY=0.5 mCurConfiguration={1.0 310mcc260mnc [en_US] ldltr sw360dp w360dp h568dp 480dpi nrml port finger qwerty/v/v dpad/v s.6} mHasPermanentDpad=false mCurrentFocus=Window{699ad0c u0 com.egos.samples/com.egos.samples.toast.ToastActivity} mFocusedApp=AppWindowToken{26954dc token=Token{2ae93ae ActivityRecord{9a6a429 u0 com.egos.samples/.toast.ToastActivity t169}}} mInTouchMode=true mLayoutSeq=271 mLastDisplayFreezeDuration=0 due to Window{df42f03 u0 com.android.launcher3/com.android.launcher3.Launcher} mLastWakeLockHoldingWindow=null mLastWakeLockObscuringWindow=Window{699ad0c u0 com.egos.samples/com.egos.samples.toast.ToastActivity} Egos-MacBook-Pro:aosp Egos$

3.PhoneWindowManager.java拦截键盘消息(比如home操作、截屏操作等)的处理类。

4.通过Android Studio查看View Hierarchy等信息。分析布局更加全面。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
View Hierarchy: com.android.internal.policy.DecorView{3afab2c V.E..... ... 0,0-1080,1920} android.widget.LinearLayout{7fb79f5 V.E..... ... 0,0-1080,1776} android.view.ViewStub{db9c38a G.E..... ... 0,0-0,0 #10203e8 android:id/action_mode_bar_stub} android.widget.FrameLayout{8687dfb V.E..... ... 0,0-1080,1776} android.support.v7.widget.ActionBarOverlayLayout{6024e18 V.E..... ... 0,0-1080,1776 #7f0c0055 app:id/decor_content_parent} android.support.v7.widget.ContentFrameLayout{156c071 V.E..... ... 0,0-1080,1776 #1020002 android:id/content} android.widget.LinearLayout{8f88e56 V.E..... ... 0,0-1080,1776} android.support.v7.widget.AppCompatButton{9b6fed7 VFED..C. ... 0,240-635,384} android.support.v7.widget.AppCompatButton{5da33c4 VFED..C. ... 0,384-659,528} android.support.v7.widget.AppCompatButton{745f2ad VFED..C. ... 0,528-653,672} android.support.v7.widget.ActionBarContainer{78739e2 V.ED.... ... 0,72-1080,240 #7f0c0056 app:id/action_bar_container} android.support.v7.widget.Toolbar{f02b173 V.E..... ... 0,0-1080,168 #7f0c0057 app:id/action_bar} android.support.v7.widget.AppCompatTextView{828c830 V.ED.... ... 48,43-280,124} android.support.v7.widget.ActionMenuView{b7c0ca9 V.E..... ... 1080,0-1080,168} android.support.v7.widget.ActionBarContextView{363122e G.E..... ... 0,0-0,0 #7f0c0058 app:id/action_context_bar} android.view.View{e4cf1cf V.ED.... ... 0,1776-1080,1920 #1020030 android:id/navigationBarBackground} android.view.View{d8a375c V.ED.... ... 0,0-1080,72 #102002f android:id/statusBarBackground}

最后

以上就是天真仙人掌最近收集整理的关于全面了解Window的全部内容,更多相关全面了解Window内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(78)

评论列表共有 0 条评论

立即
投稿
返回
顶部