[转]Android 之 Window、WindowManager 与窗口管理
這篇是對前兩天研究的懸浮窗的內(nèi)容的一個小小的資料整理吧。首先是轉(zhuǎn)載一篇介紹Android窗口的內(nèi)容,覺得寫得不錯:http://blog.csdn.net/xieqibao/article/details/6567814
為防止丟失還是把內(nèi)容也拷一遍吧(*^__^*) 嘻嘻……
其實在android中真正展示給用戶的是window和view,activity在android中所其的作用主要是處理一些邏輯問題,比如生命周期的管理、建立窗口等。在android中,窗口的管理還是比較重要的一塊,因為他直接負責(zé)把內(nèi)容展示給用戶,并和用戶進行交互。響應(yīng)用戶的輸入等。
在講窗口管理時,有必要先說下ViewManager這個接口,這個接口主要有以下的實現(xiàn)子接口和實現(xiàn)類,分別是:WindowManager和ViewGroup里面還有三個重要的方法:
- addView();?
- updateViewLayout();
- removeView();
在WindowManager中,addView方法表示的是將主窗口中的頂級view(也就是DecorView)添加到WindowManager中,并建立會話。接下來會詳細介紹。我們先來看看Window
Window:
Window是android中的窗口,表示頂級窗口的意思,也就是主窗口,它有兩個實現(xiàn)類,PhoneWindow和MidWindow,我們一般的activity對應(yīng)的主要是PhoneWindow,在activity中經(jīng)常使用的setContentView等方法也是在這個里面實現(xiàn)的。
1 @Override 2 public void setContentView(View view,ViewGroup.LayoutParams params) 3 { 4 if (mContentParent == null) 5 { 6 installDecor(); 7 } 8 else 9 { 10 mContentParent.removeAllViews(); 11 } 12 mContentParent.addView(view, params); 13 final Callback cb = getCallback(); 14 if (cb != null) 15 { 16 cb.onContentChanged(); //窗口類容發(fā)生變化時更新 17 } 18 } View Code?每個主窗口中都有一個View,稱之為DecorView,是主窗口中的頂級view(實際上就是ViewGroup),在View中有兩個成員變量叫做mParent、mChildren,它是用來管理view的上下級關(guān)系的。而ViewGroup是對一組View的管理。因此,在ViewGroup中建立了所有view的關(guān)系網(wǎng)。而最終ViewGroup附屬在主窗口上。這樣就很容易在窗口中通過findViewById找到具體的View了。view中的事件處理也是根據(jù)這個路徑來處理的。
我們再來看看ActivityThead中的兩個重要的方法(至于ActivityThead將在一篇中詳細介紹):
- performLaunchActivity( );
- handleResumeActivity( );
在performLaunchActivity中,會調(diào)用activity.attach方法建立一個window,?在handleResumeActivity方法中啟動activity的時候,會將主窗口加入到WindowManager中
1 View decor =r.window.getDecorView(); //獲得窗口的頂級View 2 decor.setVisibility(View.INVISIBLE); 3 ViewManager wm= a.getWindowManager(); //WindowManager繼承自ViewManager 4 WindowManager.LayoutParams l= r.window.getAttributes(); 5 6 a.mDecor = decor; 7 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 8 l.softInputMode |= forwardBit; 9 10 if (a.mVisibleFromClient) 11 { 12 a.mWindowAdded = true; 13 wm.addView(decor, l); //實際上是把主窗口的頂級view加入到WindowMangaer 14 } View Code我們再來看看WindowManager。
WindowManager:
WindowManager主要用來管理窗口的一些狀態(tài)、屬性、view增加、刪除、更新、窗口順序、消息收集和處理等。
通過Context.getSystemService(Context.WINDOW_SERVICE)的方式可以獲得WindowManager的實例.
WindowManager繼承自ViewManager,里面涉及到窗口管理的三個重要方法,分別是:
- addView();?
- updateViewLayout();
- removeView();??
在WindowManager中還有一個重要的靜態(tài)類LayoutParams.通過它可以設(shè)置和獲得當前窗口的一些屬性。
我們先來看看addView()方法,在addView中,會利用LayoutParams獲得window的View屬性,并為每個window創(chuàng)建ViewRoot,ViewRoot是View和WindowManager之間的橋梁,真正把View傳遞給WindowManager的是通過ViewRoot的setView()方法,ViewRoot實現(xiàn)了View和WindowManager之間的消息傳遞。在將主窗口添加到WindowManger時,它首先會建立一個代理對象:
??????????????wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE)
并且打開會話(IWindowSession),之后Window將通過該會話與WindowManager建立聯(lián)系,
來看下setView方法:
1 try 2 { 3 res =sWindowSession.add(mWindow, mWindowAttributes, 4 getHostVisibility(), mAttachInfo.mContentInsets); 5 } 6 catch (RemoteException e) 7 { 8 mAdded = false; 9 mView = null; 10 mAttachInfo.mRootView =null; 11 unscheduleTraversals(); 12 throw newRuntimeException("Adding window failed", e); 13 } 14 finally 15 { 16 if (restore) 17 { 18 attrs.restore(); 19 } 20 } View Code在這段代碼中,ViewRoot通過IWindowSession把窗口添加到WindowManager中。ViewRoot繼承了Handler,實際上它的本質(zhì)就是一個Handler,窗口中View的事件處理、消息發(fā)送、回調(diào)等將通過ViewRoot來處理。
這樣就完成了把窗口添加到WindowManager中,并交由WindowManager來管理窗口的view、事件、消息收集處理等。
?
知道原理之后添加懸浮窗的工作就比較簡單了,主要關(guān)鍵點有以下幾個:
1. 首先是AndroidManifest.xml文件中添加權(quán)限<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
2. 獲取WindowManager窗口mWindowManager?=?(WindowManager)getApplication().getSystemService(getApplication().WINDOW_SERVICE);
3. 設(shè)置窗口屬性:
1 //設(shè)置window type 2 wmParams.type = LayoutParams.TYPE_PHONE; 3 //設(shè)置圖片格式,效果為背景透明 4 wmParams.format = PixelFormat.RGBA_8888; 5 //設(shè)置浮動窗口不可聚焦(實現(xiàn)操作除浮動窗口外的其他可見窗口的操作) 6 wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE; 7 //調(diào)整懸浮窗顯示的??课恢脼樽髠?cè)置頂 8 wmParams.gravity = Gravity.LEFT | Gravity.TOP; 9 // 以屏幕左上角為原點,設(shè)置x、y初始值,相對于gravity 10 wmParams.x = 0; 11 wmParams.y = 0; 12 13 //設(shè)置懸浮窗口長寬數(shù)據(jù) 14 wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 15 wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 16 17 /*// 設(shè)置懸浮窗口長寬數(shù)據(jù) 18 wmParams.width = 200; 19 wmParams.height = 80;*/ 20 21 LayoutInflater inflater = LayoutInflater.from(getApplication()); 22 //獲取浮動窗口視圖所在布局 23 mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null); 24 //添加mFloatLayout 25 mWindowManager.addView(mFloatLayout, wmParams); View Code轉(zhuǎn)載于:https://www.cnblogs.com/Pitty/articles/3861211.html
總結(jié)
以上是生活随笔為你收集整理的[转]Android 之 Window、WindowManager 与窗口管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《APUE》第6章笔记
- 下一篇: GB/T 17710-1999 PHP生