Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android好奇寶寶_05_PopupWindow與懸浮窗

Android好奇寶寶_05_PopupWindow與懸浮窗

編輯:關於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);

當然你也可以對floatView和其子view進行點擊、觸摸等事件的監聽,然後可以通過WindowManager的另一個方法來刷新floatView:

 

 

mWindowManager.updateViewLayout(floatView, wmParams);

 


舉個栗子:

 

你可以監聽觸摸事件,得到觸摸位置並設置進wmParams裡,再調用updateViewLayout方法來實現懸浮窗隨手指移動的效果。

 

一點補充:網上的懸浮窗demo很多都是在Service中生成的,其實在Activity生成是一樣的。但Service的有個好處是可以讓應用進程不那麼容易被殺死。


樓主寫的一個demo效果圖:

data-cke-saved-src=https://www.android5.online/Android/UploadFiles_5356/201702/2017022316114773.gif

這裡的吃豆人是我再另一篇博文寫得demo摘出來的,沒啥好說的,有興趣的可以去支持下:

一個有吃豆人刪除動畫的ListView

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved