PopupWindow之了解
来源:互联网 发布:unity3d灯光闪烁效果 编辑:程序博客网 时间:2024/05/29 18:48
在分析PopupWindow之前,我们将首先说一下什么是PopupWindow?理解一个类最好的方式就是看一下这个类的定义,这里我们摘要了一下Android系统中PopupWindow的类的说明:
A popup window that can be used to display an arbitrary view. The popup window is a floating container that appears on top of the current
activity.
一个PopupWindow能够被用于展示任意的View,PopupWindow是一个悬浮的容易展示在当前Activity的上面。
简单来说PopupWindow就是一个悬浮在Activity之上的窗口,可以用展示任意布局文件。
PopupWindow 设置可点击可有两种方法~
1、在构造函数中 super(activity)
2、给PopupWindow 设置一个背景:如:
ColorDrawable dw = new ColorDrawable(0x00000000);
setBackgroundDrawable(dw);
在说明PopupWindow的加载绘制机制之前,我们还是先写一个简单的例子用于说明一下PopupWindow的简单用法。
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">public static View showPopupWindowMenu(Activity mContext, View anchorView, int layoutId) { LayoutInflater inflater = (LayoutInflater) mContext<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getSystemService</span>(Context<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.LAYOUT</span>_INFLATER_SERVICE)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> View view = inflater<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.inflate</span>(layoutId, null)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> popupWindow = new PopupWindow(view, DisplayUtil<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.dip</span>2px(mContext, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">148</span>), WindowManager<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.LayoutParams</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.WRAP</span>_CONTENT)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> popupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setBackgroundDrawable</span>(mContext<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getResources</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getDrawable</span>(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawable</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.menu</span>_bg))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> popupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setFocusable</span>(true)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> popupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setOutsideTouchable</span>(true)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> int[] location = new int[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> anchorView<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getLocationOnScreen</span>(location)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> popupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setAnimationStyle</span>(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.style</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.popwin</span>_anim_style)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> popupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.showAtLocation</span>(anchorView, Gravity<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NO</span>_GRAVITY, location[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] - popupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>() + anchorView<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>() - DisplayUtil<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.dip</span>2px(mContext, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>), location[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] + anchorView<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getHeight</span>() - DisplayUtil<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.dip</span>2px(mContext, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> popupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setOnDismissListener</span>(new PopupWindow<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.OnDismissListener</span>() { @Override public void onDismiss() { popupWindow = null<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } })<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> return view<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>
可以看到我们首先通过LayoutInflater对象将布局文件解析到内存中View对象,然后创建了一个PopupWindow对象,可以看到传递了三个参数,一个是View对象,一个是PopupWindow的宽度和高度。
这里就是PopupWindow的初始化流程的开始了,好吧,我们来看一下PopupWindow的构造方法的实现:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">PopupWindow</span>(View contentView, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> width, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> height) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(contentView, width, height, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
可以看到这里调用了PopupWindow的重载构造方法,好吧,继续看一下这个重载构造方法的实现逻辑:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">PopupWindow</span>(View contentView, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> width, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> height, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> focusable) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (contentView != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { mContext = contentView.getContext(); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } setContentView(contentView); setWidth(width); setHeight(height); setFocusable(focusable); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>
这里首先根据传入的View是否为空做了一下判断,若不为空,则初始化成员变量,Context和mWindowManager,可以发现这里的mContext对象就是传入的View组件中保留的Context对象,这里的mWindowManager是应用进程创建的时候注册的服务本地接口。然后调用了setContentView方法,这里就是为PopupWindow的contentView赋值。然后后面调用的setWidth、setHeight、setFocusable方法都是为PopupWindow的成员变量,width,height,focusable等赋值,这样PopupWindow的构造方法就执行完成了。
我们继续回到我们的例子代码中,在后续的代码中我们调用了:popupWindow.setBackgroundDrawable、popupWindow.setFocusable、PopupWindow.setOutsideTouchable、
PopupWindow.setAnimationStyle等方法,初始化了PopupWindow中的相关成员变量,最后我们调用了popupWindow.showAtLocation方法用于展示PopupWindow,这里我们具体看一下showAtLocation的实现逻辑:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">showAtLocation</span>(View parent, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> gravity, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> y) { showAtLocation(parent.getWindowToken(), gravity, x, y); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
可以发现,这里调用了showAtLocation的重载函数,这样我们继续看一下这个重载函数的实现方式:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">showAtLocation</span>(IBinder token, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> gravity, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> y) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isShowing() || mContentView == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>; } TransitionManager.endTransitions(mDecorView); unregisterForScrollChanged(); mIsShowing = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>; mIsDropdown = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> WindowManager.LayoutParams p = createPopupLayoutParams(token); preparePopup(p); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Only override the default if some gravity was specified.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (gravity != Gravity.NO_GRAVITY) { p.gravity = gravity; } p.x = x; p.y = y; invokePopup(p); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul>
可以看到通过调用createPopupLayoutParams方法创造了WindowManager.LayoutParams对象,然后又调用了preparePopup方法,可以看一下preparePopup方法的具体实现:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">preparePopup</span>(WindowManager.LayoutParams p) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mContentView == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mContext == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mWindowManager == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"You must specify a valid content view by "</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"calling setContentView() before attempting to show the popup."</span>); } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The old decor view may be transitioning out. Make sure it finishes</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// and cleans up before we try to create another one.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDecorView != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { mDecorView.cancelTransitions(); } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// When a background is available, we embed the content view within</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// another view that owns the background drawable.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mBackground != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { mBackgroundView = createBackgroundView(mContentView); mBackgroundView.setBackground(mBackground); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { mBackgroundView = mContentView; } mDecorView = createDecorView(mBackgroundView); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The background owner should be elevated so that it casts a shadow.</span> mBackgroundView.setElevation(mElevation); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// We may wrap that in another view, so we'll need to manually specify</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// the surface insets.</span> final <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> surfaceInset = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) Math.ceil(mBackgroundView.getZ() * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>); p.surfaceInsets.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span>(surfaceInset, surfaceInset, surfaceInset, surfaceInset); p.hasManualSurfaceInsets = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>; mPopupViewInitialLayoutDirectionInherited = (mContentView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT); mPopupWidth = p.width; mPopupHeight = p.height; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li></ul>
preparePopup方法的参数是WindowManager.LayoutParams,然后设置了PopupWindow中的几个比较重要的成员变量,首先看一下mBackgroundView的初始化过程:
<code class="hljs matlab has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mBackground != null) <span class="hljs-cell" style="box-sizing: border-box;">{ mBackgroundView = createBackgroundView(mContentView); mBackgroundView.setBackground(mBackground); }</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-cell" style="box-sizing: border-box;">{ mBackgroundView = mContentView; }</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
可以发现如果我们设置了mBackground变量也就是我们在初始化的时候执行了popupWindow的setBackgound方法,那么我们这里执行的就是if分之,这里看一下createBackgourndView的具体执行逻辑:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> PopupBackgroundView <span class="hljs-title" style="box-sizing: border-box;">createBackgroundView</span>(View contentView) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> height; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (layoutParams != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) { height = ViewGroup.LayoutParams.WRAP_CONTENT; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { height = ViewGroup.LayoutParams.MATCH_PARENT; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> PopupBackgroundView backgroundView = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PopupBackgroundView(mContext); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> PopupBackgroundView.LayoutParams listParams = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PopupBackgroundView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, height); backgroundView.addView(contentView, listParams); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> backgroundView; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
可以看到,createBackgroundView的执行逻辑就是在参数contentView的外面一层包裹一层PopupBackgroundView,而这里的PopupBackgroundView值我们自定义的FrameLayout的子类,重写了其onCreateDrawableState方法。
继续回到我们的preparePopup方法,这里我们又调用了createDecorView方法初始化mDectorView变量,我们可以看一下createDecorView的具体实现:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> PopupDecorView <span class="hljs-title" style="box-sizing: border-box;">createDecorView</span>(View contentView) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> height; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (layoutParams != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) { height = ViewGroup.LayoutParams.WRAP_CONTENT; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { height = ViewGroup.LayoutParams.MATCH_PARENT; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> PopupDecorView decorView = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PopupDecorView(mContext); decorView.addView(contentView, ViewGroup.LayoutParams.MATCH_PARENT, height); decorView.setClipChildren(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>); decorView.setClipToPadding(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> decorView; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
可以发现这里也是给参数contentView外面包裹了一层PopupDecorView,这里的PopupDecorView也是我们自定义的FrameLayout的子类,PopupDecorView的源码比较多,这里就不都贴出来了,这里具体看一下其onTouchEvent方法的实现:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">@Override <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> boolean <span class="hljs-title" style="box-sizing: border-box;">onTouchEvent</span>(MotionEvent <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>) { final <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getX(); final <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> y = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getY(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getAction() == MotionEvent.ACTION_DOWN) && ((x < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) || (x >= getWidth()) || (y < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) || (y >= getHeight()))) { dismiss(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getAction() == MotionEvent.ACTION_OUTSIDE) { dismiss(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> super.onTouchEvent(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>); } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
可以发现其重写了onTouchEvent时间,这样我们在点击popupWindow外面的时候就会执行pupopWindow的dismiss方法,取消PopupWindow。
好吧,继续回到我们的showAsDropDown方法,在执行完成preparePopup方法之后又调用了invokePopup方法,这里的方法应该就是具体执行PopupWindow的加载与显示逻辑了。这里我们具体看一下其实现逻辑:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">invokePopup</span>(WindowManager.LayoutParams p) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mContext != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { p.packageName = mContext.getPackageName(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> PopupDecorView decorView = mDecorView; decorView.setFitsSystemWindows(mLayoutInsetDecor); setLayoutDirectionFromAnchor(); mWindowManager.addView(decorView, p); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mEnterTransition != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { decorView.requestEnterTransition(mEnterTransition); } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
我们看到这里我们调用了mWindowManager.addView方法,看过我们前面几篇关于Dialog和Activity的加载与现实流程的同学应该知道这里的addView其实是我们布局绘制的流程,这里的mWindowManager是我们在调用PopupWIndow的构造函数的时候初始化的,其调用的是:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mWindowManager == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mContentView != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
而这里的mContext.getSystemService是一个接口其具体的实现是在ContextImpl中实现的,所以这里我们看一下ContextImpl的getSystemService的实现:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">getSystemService</span>(String name) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> SystemServiceRegistry.getSystemService(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, name); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
好吧,在ContextImpl中的getSystemService方法又调用了SystemServiceRegister中的静态方法getSystemService,这样我们再看看一下在SystemServiceRegister是如何实现的。
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Object <span class="hljs-title" style="box-sizing: border-box;">getSystemService</span>(ContextImpl ctx, String name) { ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span>(name); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> fetcher != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> ? fetcher.getService(ctx) : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
这里发现服务对象的获取就是通过一个SYSTEM_SERVICE_FETCHERS的map数据结构获取的,那么这个map对象的数据是何时填充的呢?通过查看源码我们发下在SystemServiceRegister中有一段静态代码主要用于注册本地服务接口,其中关于windowManagerService本地服务的代码如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">registerService(Context.WINDOW_SERVICE, WindowManager.class, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CachedServiceFetcher<WindowManager>() { <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> WindowManager <span class="hljs-title" style="box-sizing: border-box;">createService</span>(ContextImpl ctx) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> WindowManagerImpl(ctx.getDisplay()); }});</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
好吧,原来我们通过mContext.getSystemService获取的WindowManager其实际上是一个WindowManagerImpl对象,而我们调用的addView就是WindowManagerImpl的addView方法。
这样就回到了我们前几篇讲解的内容上了,通过调用WindowManagerImpl实现了布局文件的绘制流程。。。。
好了,经过上面的一系列的操作我们分析完了PopupWindow的加载绘制流程,其和Dialog,Activity的加载绘制流程类似,都是通过Window对象控制布局文件的加载与绘制流程。
总结:
PopupWindow的界面加载绘制流程也是通过Window对象实现的;
PopupWindow内部保存的mWindowManager对象通过ContextImpl中获取,并且取得的是WindowManagerImpl对象;
PopupWindow通过为传入的View添加一层包裹的布局,并重写该布局的点击事件,实现点击PopupWindow之外的区域PopupWindow消失的效果;
- PopupWindow之了解
- Android开发之PopupWindow
- Android之PopupWindow
- android之PopupWindow
- android控件之popupWindow
- Android之动画PopupWindow
- android之PopupWindow
- Android开发之PopupWindow
- android组件之PopupWindow
- android学习之popupWindow
- Android开发之PopupWindow
- Android开发之PopupWindow
- Android之动画PopupWindow
- Android开发之PopupWindow
- Android学习之PopupWindow
- 用户界面View之PopupWindow
- Android总结之PopupWindow
- PopupWindow之动态生成
- 字符串的格式化
- Android项目Tab类型主界面大总结 Fragment+TabPageIndicator+ViewPager
- 人件读书笔记(14)霍恩布洛尔因素
- RelativeLayout、TableLayout的属性
- C++静态库与动态库
- PopupWindow之了解
- 本机连接不上github
- java.lang.UnsupportedClassVersionError【版本不一致出错】
- Maven 项目中所依赖的jar包的导出和项目的导出
- protocol buf的简单使用
- Springboot学习记录4------profile
- 万用表检测驻极体话筒好坏
- 关于ncurses库获取键盘方向键
- android对字符串的加密和解密方法