Android 實現頂層窗口、浮動窗口(附Demo)

  作過Window程序開發的朋友應該都知道,咱們要把程序窗口置頂很簡單,只要設置一些窗口屬性便可。可是到了Android,你沒法簡單設置一個屬性,就讓Android的Activity置頂。由於只要有新的Activity啓動,你的Activity界面就會被擋住。今天介紹一下如何把一個窗口置頂。html

  也許會有人說:你的窗口置頂了,就會破壞系統的穩定性,影響其餘程序使用,這是流氓行爲o(╯□╰)o 。對於這個問題,若是你的頂層窗口沒有處理好,的確會有這個問題。不過對於一些定製系統來講,這個功能能夠實現頗有用的功能,例如:對於一些須要長時間提示用戶的危險警告。例以下面效果圖,在瀏覽圖片的時候,系統彈出一個警告框,會一直提示用戶注意安全,就算切換到其餘程序,這個提示框也會一直在頂層。安全

 

(PS:新建的QQ羣,有興趣能夠加入一塊兒討論:Android羣:322599434)佈局

 

一、WindowManager介紹spa

  所有Android的窗口機制是基於一個叫作WindowManager實現,這個接口能夠添加view到屏幕,也能夠從屏幕刪除view。它面向的對象一端是屏幕,另外一端就是View,直接忽視咱們之前的Activity或者Dialog之類的元素。其實咱們的Activity或者Diolog底層的實現也是通過WindowManager,WindowManager是全局的,整個系統只有一個WindowManager。它是顯示View的最底層了。WindowManager主要用來管理窗口的一些狀態、屬性、view增長、刪除、更新、窗口順序、消息收集和處理等。經過Context.getSystemService(Context.WINDOW_SERVICE)的方式能夠得到WindowManager的實例.WindowManager繼承自ViewManager,裏面涉及到窗口管理的三個重要方法,分別是3d

  • addView(); 
  • updateViewLayout();
  • removeView();

  在WindowManager中還有一個重要的靜態類LayoutParams。經過它能夠設置和得到當前窗口的一些屬性。咱們先來看看addView()方法,在addView中,會利用LayoutParams得到window的View屬性,併爲每一個window創ViewRoot,ViewRoot是View和WindowManager之間的橋樑,真正把View傳遞給WindowManager的是經過ViewRoot的setView()方法,ViewRoot實現了View和WindowManager之間的消息傳遞。在將主窗口添加到WindowManger時,它首先會創建一個代理對象:代理

wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE)code

而且打開會話(IWindowSession),以後Window將經過該會話與WindowManager創建聯繫。orm

 

 

二、使用WindowManager實現浮動窗口視頻

    

//Edited by mythou
//http://www.cnblogs.com/mythou/
  private void createFloatView() { Button btn_floatView = new Button() btn_floatView = new Button(getApplicationContext()); btn_floatView.setText("懸浮窗"); wm = (WindowManager) getApplicationContext().getSystemService( Context.WINDOW_SERVICE); params = new WindowManager.LayoutParams(); // 設置window type params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; /* * 若是設置爲params.type = WindowManager.LayoutParams.TYPE_PHONE; 那麼優先級會下降一些, * 即拉下通知欄不可見 */ params.format = PixelFormat.RGBA_8888; // 設置圖片格式,效果爲背景透明 // 設置Window flag params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; /* * 下面的flags屬性的效果形同「鎖定」。 懸浮窗不可觸摸,不接受任何事件,同時不影響後面的事件響應。 * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL | * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE; */ // 設置懸浮窗的長得寬 params.width = 100; params.height = 100; // 設置懸浮窗的Touch監聽 btn_floatView.setOnTouchListener(new OnTouchListener() { int lastX, lastY; int paramX, paramY; public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); paramX = params.x; paramY = params.y; break; case MotionEvent.ACTION_MOVE: int dx = (int) event.getRawX() - lastX; int dy = (int) event.getRawY() - lastY; params.x = paramX + dx; params.y = paramY + dy; // 更新懸浮窗位置 wm.updateViewLayout(btn_floatView, params); break; } return true; } }); wm.addView(btn_floatView, params); isAdded = true; }

  上面是一段建立一個浮動窗口的代碼,主要就是使用了WindowManager的addView方法,把咱們建立的一個View添加到WindowManager裏面去。除了使用上面的代碼動態建立一個View,咱們也能夠直接加載某個XML文件,而後生成一個View,咱們日常使用的XML佈局文件解析完,都是能生成一個View對象,所以咱們能夠直接編寫一個佈局文件而後使用LayoutInflater來加載對應的View。例以下面的代碼:htm


//Edited by mythou
//http://www.cnblogs.com/mythou/
LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
//加載須要的XML佈局文件 RelativeLayout mInView
= (RelativeLayout)inflater.inflate(R.layout.in_vedio, null, false);

//......
//添加到WindowManager裏面
wm.addView(btn_floatView, params);

  若是須要實現一個全屏置頂的窗口,只要編寫一個全屏的XML配置文件便可,跟咱們在Activity裏面使用的XML配置界面同樣。 

 

三、注意事項

  在使用WindowManager的時候有一點須要注意的是,你只能把父節點的View添加到WindowManager裏面,也就是說,你要添加的View不能是已經有父節點的某個子節點,不然會出現下面的問題:

 

四、結語

  上面就是建立一個頂層窗口或者浮動窗口的大體流程。之因此研究這個,我並非爲了作浮動窗口,而是爲了作浮動視頻播放,這個下次有空,再寫一篇如何作浮動視頻播放的文章。

  最後補充一點,不要輕易使用全屏置頂的方法,由於這個會影響你係統其它程序的運行。特別是你的View設置爲透明和全屏置頂,會致使界面沒法操做。

 

給出一個浮動窗口的DemoFloating_window2013-8-7.rar

 

Edited by mythou

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3244208.html 

相關文章
相關標籤/搜索