關(guān)于Window和WindowManager的幾個(gè)知識(shí)點(diǎn)

為了分析Window的工作機(jī)制,我們需要先了解如何使用WindowManager添加一個(gè)Window,下面的代碼演示了通過(guò)WindowManager添加Window的過(guò)程

Button mFloatingButton =new Button(this);
mFloatingButton.setText("button");

int type = WindowManager.LayoutParams.TYPE_TOAST;
int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
WindowManager.LayoutParams  mLayoutParams = new 
WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,type ,flags , PixelFormat.TRANSPARENT);
mLayoutParams.gravity = Gravity.LEFT|Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 300;

WindowManager mWindowManager = this.getWindowManager();
mWindowManager.addView(mFloatingButton,mLayoutParams);

上述代碼可以將一個(gè)Button添加到屏幕坐標(biāo)為(100,300)的位置上。WindowManager.LayoutParams中的flags和type這兩個(gè)參數(shù)比較重要,下面對(duì)其進(jìn)行說(shuō)明。

Flags參數(shù)表示W(wǎng)indow的屬性,它有很多選項(xiàng),通過(guò)這些選項(xiàng)可以控制Window的顯示特性,這里介紹幾個(gè)常用的選項(xiàng):

  • FLAG_NOT_FOCUSABLE
    表示W(wǎng)indow不需要獲取焦點(diǎn),也不需要接收各種輸入事件,此標(biāo)記會(huì)同時(shí)啟用FLAG_NOT_TOUCH_MODAL,最終事件會(huì)直接傳遞給下層的具有焦點(diǎn)的Window。
  • FLAG_NOT_TOUCH_MODAL
    系統(tǒng)會(huì)將當(dāng)前Window區(qū)域以外的單擊事件傳遞給底層的Window,當(dāng)前Window區(qū)域內(nèi)的單擊事件則自己處理。這個(gè)標(biāo)記很重要,一般來(lái)說(shuō)都需要開(kāi)啟此標(biāo)記。否則其他Window將無(wú)法收到單擊事件。
  • FLAG_SHOW_WHEN_LOCKED
    開(kāi)啟此模式可以讓W(xué)indow顯示在鎖屏的界面上。

Type參數(shù)表示W(wǎng)indow的類型,Window有三種類型,分別是應(yīng)用Window、子Window和系統(tǒng)Window。應(yīng)用類Window對(duì)應(yīng)一個(gè)Activity。子Window不能單獨(dú)存在,它需要附屬在特定的父Window之中,比如常見(jiàn)的一些Dialog就是一個(gè)子Window。系統(tǒng)Window是需要聲明權(quán)限在能創(chuàng)建的Window,比如Toast和系統(tǒng)狀態(tài)欄這些都是系統(tǒng)Window。

Window是分層的,每個(gè)Window都有對(duì)應(yīng)的z-ordered,層級(jí)大的會(huì)覆蓋在層級(jí)小的Window的上面,這和HTML中的z-index的概念是完全一致的。在三類Window中,應(yīng)用Window的層級(jí)范圍是199,子Window的層級(jí)范圍是10001999,系統(tǒng)Window的層級(jí)范圍是2000~2999,這些層級(jí)范圍對(duì)應(yīng)著WindowManager.LayoutParams的type參數(shù)。如果想要Window位于所有Window的最頂層,那么采用較大的層級(jí)即可。很顯然系統(tǒng)Window的層級(jí)是最大的,而且系統(tǒng)層級(jí)有很多值,一般我們可以選用TYPE_SYSTEM_OVERLAY或者TYPE_SYSTEM_ERROR,如果 采用TYPE_SYSTEM_ERROR,只需要為type參數(shù)指定這個(gè)層級(jí)即可:mLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;同時(shí)聲明權(quán)限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW“>。
因?yàn)橄到y(tǒng)類型的Window是需要檢查權(quán)限的,如果不在AndroidManifest中使用相應(yīng)的權(quán)限,那么創(chuàng)建Window的時(shí)候就會(huì)報(bào)錯(cuò)。

WindowManager所提供的功能很簡(jiǎn)單,常用的只要三個(gè)方法 ,即添加View、更新View和刪除View,這三個(gè)方法定義在ViewManager中,而WindowManager繼承了ViewManager。

public interface ViewManager{   
   public void addView(View view, ViewGroup.LayoutParams params);    
   public void updateViewLayout(View view, ViewGroup.LayoutParams params);   
   public void removeView(View view);
}

Window是一個(gè)抽象概念,每一個(gè)Window都對(duì)應(yīng)著一個(gè)View和一個(gè)ViewRootImpl,Window和View通過(guò)ViewRootImpl來(lái)建立聯(lián)系,因此Window并不是實(shí)際存在的,它是以View的是形式存在。這點(diǎn)可以從WindowManager的定義中看出來(lái),它提供的三個(gè)接口方法addView、updateViewLayout以及removeView都是針對(duì)View的,這說(shuō)明View才是Window存在的實(shí)體,有視圖的地方就有Window,比如Activity、Dialog、Toast,除此之外,還有一些依托Window而實(shí)現(xiàn)的視圖,比如PopUpWindow、菜單。在實(shí)際使用中無(wú)法直接訪問(wèn)Window,必須通過(guò)WindowManager。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容