Window和WindowManager的簡介和使用
在某些特殊的時候,我們需要在桌面建立一個類似懸浮窗的東西,這種效果就需要用到Window來實現,Window是一個抽象的概念,它的具體實現是PhoneWindow。建立一個Window只需要通過WindowManager即可完成。WindowManager是外界訪問Window的入口,Window的具體實現在WindowManagerService中,WindowManager和WindowManagerService的互動是一個IPC的過程。Android所有的檢視都是通過Window來呈現的,不管是ACtivity,Dialog還是Toast,他們的檢視實際上都是附加在Window上的,因此,Window實際是View的直接管理者。View的事件分發機制,從Window傳遞給DecorView,再由DecorView 傳遞給我們的View,Activity設定檢視的方法setContentView()的方法也是在Window實現的
1.用WindowManager新增一個Window
mLayourParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT);
mLayourParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams .FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mLayourParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayourParams.x = 100;
mLayourParams.y = 300;
mWinManager = getWindowManager();
mWinManager.addView(view, mLayourParams);
WindowManager.LayoutParam中的flag和type比較重要
Flags引數標示Window的屬性,三種常用的
(1)FLAG_NOT_FOCUSABLE 這種 模式的Window不需要獲取焦點,也不需要接收各種輸入事件,此標記會同時啟動(2),事件最終會傳遞給下層具有焦點的Window
(2)FLAG_NOT_TOUCH_MODEL 系統會將Window區域外的單擊事件傳遞給底層的Window,當前WIndow區域的單擊事件自己處理,一般都需要開啟此標記,不然其他Window將無法接收到點選事件
(3)FLAG_SHOW_WHEN_LOCKED 可以讓Window顯示在鎖屏的介面上
Type引數標示Window的型別:
1.應用Window,應用類Window對應著一個Activity。
2.子Window ,子Window不能單獨存在,它需要附屬在特定的父Window之中,比如常見的Dialog就是一個子Window。
3.系統Window,是需要宣告許可權才能建立的Window,比如Toast和系統狀態列這些都是系統的Window
Window是分層級的,層級大的會覆蓋在層級小的上面,應用Window的層級是1-99.子Window的層級是1000-1999,系統Window的層級是2000-2999
mLayourParams.type= WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
WindowManager提供了三個方法,addView(),updataViewLayout(),removeView()
view.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
mLayourParams.x = rawX;
mLayourParams.y = rawY;
mWinManager.updateViewLayout(view, mLayourParams);
break;
default:
break;
}
return false;
}
});