需求
在項目中需要用到不依賴Activity Context啟動的Dialog围辙,并且Dialog的顯示層級要在最頂部(沒錯弹囚,就是流氓軟件9Ф浮)
方案
在網(wǎng)絡(luò)上搜索“Android AlertDialog 置頂”对雪、“Android AlertDialog level”都找不到我想要的乔夯,最后搜索“Android AlertDialog Priority”找到了一篇文章,提示了我征椒。
我重新整理了一下娇哆,Dialog是在WindowManager顯示的,而WindowManager分很多不同的層勃救,使用AlertDialog的alertDialog.getWindow().setType(WindowManager.LayoutParams.***)
方法可以設(shè)置這個層碍讨,這里就是關(guān)鍵了。從源碼(WindowManager.java)里面看蒙秒,type有很多垄开,我們只關(guān)注系統(tǒng)等級且沒有被隱藏的,目前有如下類型:
/**
* Start of system-specific window types. These are not normally
* created by applications.
*window類型:第一個系統(tǒng)窗口税肪。這些彈窗不是通過application正常創(chuàng)建的。
*/
public static final int FIRST_SYSTEM_WINDOW = 2000;
/**
* Window type: the status bar. There can be only one status bar
* window; it is placed at the top of the screen, and all other
* windows are shifted down so they are below it.
* In multiuser systems shows on all users' windows.
* window類型:狀態(tài)欄窗口榜田。因為只能有個一個狀態(tài)欄window益兄,所以它被放在屏幕最上面,
* 且其他window在它下面箭券。在多用戶系統(tǒng)净捅,可以顯示在所有用戶的window之上。
*/
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;
/**
* Window type: the search bar. There can be only one search bar
* window; it is placed at the top of the screen.
* In multiuser systems shows on all users' windows.
* window類型:搜索條窗口辩块。(后面同上蛔六,略)
*/
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;
/**
* Window type: phone. These are non-application windows providing
* user interaction with the phone (in particular incoming calls).
* These windows are normally placed above all applications, but behind
* the status bar.
* In multiuser systems shows on all users' windows.
* window類型:通話窗口。這些非應(yīng)用window為用戶提供通話的交互废亭,特別是來電的時候
* 在多用戶系統(tǒng)国章,可以顯示在所有用戶的window之上。
*/
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;
/**
* Window type: system window, such as low power alert. These windows
* are always on top of application windows.
* In multiuser systems shows only on the owning user's window.
* window類型:系統(tǒng)警告窗口豆村,例如低電彈窗液兽。這些window總在應(yīng)用之上的window層。
* 在多用戶系統(tǒng)掌动,只顯示在自己的window之上四啰。
*/
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;
/**
* Window type: keyguard window.
* In multiuser systems shows on all users' windows.
* @removed
* window類型:屏保(guard為守衛(wèi)的意思)。
* 在多用戶系統(tǒng)粗恢,可以顯示在所有用戶的window之上柑晒。
*/
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;
/**
* Window type: transient notifications.
* In multiuser systems shows only on the owning user's window.
* window類型:Toast對應(yīng)的窗口。
* 在多用戶系統(tǒng)眷射,只顯示在自己的window之上匙赞。
*/
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;
/**
* Window type: system overlay windows, which need to be displayed
* on top of everything else. These windows must not take input
* focus, or they will interfere with the keyguard.
* In multiuser systems shows only on the owning user's window.
* window類型:系統(tǒng)覆蓋窗口佛掖,用來在頂部展示腕柜。
* 這類window需要釋放輸入焦點多艇,不然會中斷屏幕保護滔韵。
* 在多用戶系統(tǒng)森缠,只顯示在自己的window之上亡鼠。
*/
public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6;
/**
* Window type: priority phone UI, which needs to be displayed even if
* the keyguard is active. These windows must not take input
* focus, or they will interfere with the keyguard.
* In multiuser systems shows on all users' windows.
* window類型:在屏幕保護下的通話窗口嗓蘑。
* 這類window需要釋放輸入焦點源祈,不然會中斷屏幕保護榆苞。
* 在多用戶系統(tǒng)猛拴,可以顯示在所有用戶的window之上羹铅。
*/
public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7;
/**
* Window type: panel that slides out from the status bar
* In multiuser systems shows on all users' windows.
* window類型:從狀態(tài)欄下拉下來的面板。(變量名又是系統(tǒng)對話框愉昆,估計就是和它同級吧)
* 在多用戶系統(tǒng)职员,可以顯示在所有用戶的window之上。
*/
public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8;
/**
* Window type: dialogs that the keyguard shows
* In multiuser systems shows on all users' windows.
* window類型:屏保彈出的對話框
* 在多用戶系統(tǒng)跛溉,可以顯示在所有用戶的window之上焊切。
*/
public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9;
/**
* Window type: internal system error windows, appear on top of
* everything they can.
* In multiuser systems shows only on the owning user's window.
* window類型:系統(tǒng)錯誤窗口
* 在多用戶系統(tǒng),只顯示在自己的window之上芳室。
*/
public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10;
/**
* Window type: internal input methods windows, which appear above
* the normal UI. Application windows may be resized or panned to keep
* the input focus visible while this window is displayed.
* In multiuser systems shows only on the owning user's window.
* window類型:輸入法窗口专肪,出現(xiàn)在正常UI之上。
* 應(yīng)用可能會重置大小
* 在多用戶系統(tǒng)堪侯,只顯示在自己的window之上嚎尤。
*/
public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11;
/**
* Window type: internal input methods dialog windows, which appear above
* the current input method window.
* In multiuser systems shows only on the owning user's window.
* window類型:輸入法中備選窗口,出現(xiàn)在當前輸入法窗口之上伍宦。
* 在多用戶系統(tǒng)芽死,只顯示在自己的window之上。
*/
public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;
/**
* Window type: wallpaper window, placed behind any window that wants
* to sit on top of the wallpaper.
* In multiuser systems shows only on the owning user's window.
* window類型:墻紙對應(yīng)的窗口次洼,放置在任何想在其之上的窗口之后关贵。
* 在多用戶系統(tǒng),只顯示在自己的window之上滓玖。
*/
public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13;
/**
* Window type: panel that slides out from over the status bar
* In multiuser systems shows on all users' windows.
* window類型:從狀態(tài)欄下拉下來的面板坪哄。
* 在多用戶系統(tǒng),可以顯示在所有用戶的window之上势篡。
*/
public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14;
PS:我測試了其中部分類型翩肌,文首說提醒我的那篇文章說系統(tǒng)彈窗不需要依賴Activity,其實部分還是需要的禁悠,我以 TYPE_SYSTEM_ERROR為準測試各個類型彈窗的層級其結(jié)果為:
類型 | 直接調(diào)用結(jié)果 |
---|---|
TYPE_INPUT_METHOD | 報錯需要Activity |
TYPE_STATUS_BAR_PANEL | 相當于 TYPE_SYSTEM_ERROR |
TYPE_INPUT_METHOD_DIALOG | 在 TYPE_SYSTEM_ERROR之下 |
TYPE_WALLPAPER | 報錯需要Activity |
TYPE_SYSTEM_DIALOG | 在 TYPE_SYSTEM_ERROR之下 |
TYPE_PRIORITY_PHONE | 在 TYPE_SYSTEM_ERROR之下 |
TYPE_TOAST | 在 TYPE_SYSTEM_ERROR之下 |
TYPE_STATUS_BAR | 報錯需要Activity |
TYPE_SYSTEM_OVERLAY | 相當于 TYPE_SYSTEM_ERROR念祭, 但是能點擊背景 |
注意:我只是根據(jù)表象判斷,大家可以各取所需碍侦。知道如何再深入源碼查找窗口層級變化的大神可以指教指教粱坤。
代碼
//權(quán)限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
//代碼
AlertDialog alertDialog;
// 創(chuàng)建構(gòu)建器
AlertDialog.Builder builder = new AlertDialog.Builder(mContext,AlertDialog.THEME_HOLO_LIGHT);
// 設(shè)置參數(shù)
builder.setTitle("提示")
.setNeutralButton("忽略", new DialogInterface.OnClickListener() {// 中那個按鈕
@Override
public void onClick(DialogInterface dialog,int which) {
dismissDialog();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
dismissDialog();
}
});
alertDialog= builder.create();
//設(shè)置層級
Window window = mAlertDialog.getWindow();
if (window == null) {
Log.w("system dialog","dialog window is null");
return;
}
window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);//這里我選了最高級
注意:彈窗可以在Service中彈出隶糕,也可以在BroadcastReceiver中彈出,當然你選擇的等級應(yīng)該不需要Activity才行
注意事項
- 其實站玄,并不建議使用系統(tǒng)級彈窗枚驻,會在其他應(yīng)用之上,影響用戶體驗株旷。
- 當窗口的層級高于屏幕保護(鎖屏)的層級時再登,連續(xù)按開機鍵,彈窗會駐留在鎖屏界面晾剖,有可能遮擋用戶的鎖屏密碼界面锉矢,甚至無法解鎖,注意在鎖屏?xí)r關(guān)閉彈窗齿尽。
- 如上第二條沽损,即使及時關(guān)閉彈窗,在5.0以上的系統(tǒng)也會閃一下循头;而在4.2.2上暫時沒有發(fā)現(xiàn)绵估。