編輯:關於Android編程
之所以把PopupWindow與懸浮窗這兩個放到一起講,是因為這兩個的實現原理基本是一致的,只是有點不同而已。
原理:
使用系統服務(WindowManagerService)將要顯示的View添加進Window中。
WindowManagerService和ActivityManagerService是Android系統中兩個最重要的服務,其中一個管理窗口顯示,一個管理四大組件。
ActivityManagerService這裡呢先不講,以後再說。
簡單講下WindowManagerService,想深入了解的建議看下老羅大大的博客,新手慎入:傳送門
以一個最簡單的HelloWorld來說明:
當Activity被啟動時,Activity會被分配一個Window,一個window代表一個充滿屏幕的窗口。然後當我們調用setContentView時,我們要顯示的View(後面用contentView表示)就會被添加進該Activity的window中。window接收到contentView後會根據設置在其外部包裹一些其它view(比如titlebar),然後請求WindowManagerService,WindowManagerService則向底層一層一層發送請求直到硬件將其顯示出來。
上面的說明簡化了很多過程,因為不是我想講的重點,這一篇只是想簡單講下怎麼用WindowManagerService,而不是它的實現原理(原理我也講不來。。)。
一般我們添加View的方式是將子view添加到一個已經存在於window上的父view中。但其實利用WindowManagerService我們是可以直接將view添加的window中的,就像系統幫我們自動將setContentView的contentView添加到window一樣。
兩種方式的主要區別在於子view添加進父view,那麼子view和父view就位於同一個window,但用WindowManagerService添加view,我們可以指定不同window(如果你有足夠權限的話),我這裡說的不同window是指他們的等級不同。PopupWindow依附於Activity,屬於應用級。而懸浮窗就是屬於系統級,所以它才可以保持在前端顯示(其它系統級的window還有來電提醒,ANR、FC等系統警告等)。
再說說WindowManagerService和WindowManager的區別:
WindowManagerService是系統服務,當並不完全對開發者開放,而是使用WindowManager做為代理,提供部分功能和包裝後的功能,可以說WindowManager是閹割版的WindowManagerService,那些會危害系統安全的功能被屏蔽了。Android系統中的系統服務基本都是這種方式。
說完原理來看看代碼證實一下,先看下系統實現的PopupWindow,在根據原理來實現一個懸浮窗。
PopupWindow:
其實PopupWindow裡面只有兩句核心的代碼,其它的都是一些位置和大小的計算。
(1)在構造方法中,通過傳入的context或則view獲得WindowManager:
mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
或者:
mContext = contentView.getContext(); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
(2)通過WindowManager將PopupWindow添加進window:
mWindowManager.addView(mPopupView, p);
是不是炒雞簡單?
那麼我們來開始實現懸浮窗:
(1)先獲取WindowManager:
mWindowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);
注意這裡要使用Application的context來獲取WindowManager,如果使用activity.getSystemService(Context.WINDOW_SERVICE)來獲取的話,得到的WindowManager的生命周期是小於等於Activity的,而使用上面這種方式得到的WindowManager是跟整個應用一樣的,這樣除非你的整個應用進程都被終結了,不然你的懸浮窗就可以一直顯示。
(2)設置參數WindowManager.LayoutParams:
大小位置等可以根據需求來設置,但是要記住設置顯示的級別:
wmParams.type = LayoutParams.TYPE_PHONE;
(3)將要顯示的view添加進window:
mWindowManager.addView(floatView, wmParams);
mWindowManager.updateViewLayout(floatView, wmParams);
你可以監聽觸摸事件,得到觸摸位置並設置進wmParams裡,再調用updateViewLayout方法來實現懸浮窗隨手指移動的效果。
一點補充:網上的懸浮窗demo很多都是在Service中生成的,其實在Activity生成是一樣的。但Service的有個好處是可以讓應用進程不那麼容易被殺死。
樓主寫的一個demo效果圖:
這裡的吃豆人是我再另一篇博文寫得demo摘出來的,沒啥好說的,有興趣的可以去支持下:
一個有吃豆人刪除動畫的ListView
先上效果圖: 驗證碼采用PHP返回的imageview來實現,xml如下:
前言:protobuf是google的一個開源項目,主要的用途是:1.數據存儲(序列化和反序列化),這個功能類似xml和json等;2.制作網絡通信協議;一、資源下載:1
概要 若讀者之前沒接觸過service,對下面內容有個大致了解即可。待使用過service之後再來閱讀本章內容,會理解更深刻。
今天學習了Spinner組件的使用,非常好用的一款組件,相當於從下拉列表中選擇項目,今天收獲頗多,下面給大家演示一下Spinner的使用(分別使用ArrayAdapter