Window表示是一個窗口的概念,它是一個抽象類,具體的實現是PhoneWindow,創建一個Window是很簡單的事,只需要通過WindowManager就可以完成,Android中所有的視圖都是通過Window來實現的,比如Activity,Toast和Dialog,當我們需要做懸浮窗口的需求的時候,就需要用到它們,下面來看看
Window和WindowManager
先來看看如何通過WindowManager添加一個Window
Button button=new Button(this);
WindowManager wmManager=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams lp=new WindowManager.LayoutParams();
lp.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
lp.gravity= Gravity.TOP;
lp.x=100;
lp.y=300;
wmManager.addView(button,lp);
代碼很簡單,創建一個view之后就可以用WindowManager的addView方法引用到屏幕x=100和y=300坐標上了,其實WindowManager常用的方法就是添加view,更新view和刪除view,也就是addView,updateViewLayout和removeView
(一)Flags
參數表示Window的屬性,它有很多選項,通過這些選項可以控制Window的顯示特性
FLAG_NOT_FOCUSABLE
表示window不需要獲取焦點,這個比較好理解,設置了這個屬性后,window將不會獲取到焦點
FLAG_NOT_TOUCH_MODAL
在此模式下,系統會將當前Window區域以外的單擊事件傳遞給底層的Window,當前Window區域以內的單擊事件則自己處理。 一般來說都需要開啟此標記,否則其他Window將無法收到單擊事件
FLAG_SHOW_WHEN_LOCKED
此模式可以讓Window顯示在鎖屏的界面上
(二)Type
Type代表的是window的類型,共有3種,分別是:應用window,子window和系統window,應用window對應一個Activity,子window需要依附在父window上,不能單獨存在,比如dialog,系統window就是系統提供的,比如toast,狀態欄等,這些在使用的時候需要聲明權限,否則報錯,每一類型的window都有一個范圍
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
應用window(1-99):Activity,Fragment等
子window(1000-1999):Dialog,Popupwindow等
系統window(2000-2999):Toast,狀態欄,通知等
層級范圍對應這WindowManager.LayoutParams的type參數,層級大的會覆蓋在層級小的Window上面。所以系統層級是最大的,系統層級一般選用TYPE_SYSTEM_ERROR或者TYPE_SYSTEM_OVERLAY
上面提到了windowManger對view的操作有addView,updateViewLayout和removeView,這3個方法定義在ViewManager中,而WindowManger是繼承了ViewManager,我們來看看這三個方法:
public interface ViewManager
{
/**
* Assign the passed LayoutParams to the passed View and add the view to the window.
* <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming
* errors, such as adding a second view to a window without removing the first view.
* <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a
* secondary {@link Display} and the specified display can't be found
* (see {@link android.app.Presentation}).
* @param view The view to be added to this window.
* @param params The LayoutParams to assign to view.
*/
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
這3個功能足夠我們平常用了,其實WindowManager操作Window的過程就好像Window操作view的過程,我們有時候看到那些可以拖動Window的效果,其實就可以通過updateViewLayout來實現,設置view的onTouchListener,然后根據手指拖動來改變x和y的值,不斷更新view就可以了
button.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getRawX();
int y= (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
lp.x=x;
lp.y=y;
wmManager.updateViewLayout(button,lp);
break;
}
return false;
}
});
好了,這篇文章到這就結束了