前言
一般的懸浮窗實現方式,需要申請許可權,並還是要對部分機型進行適配才能正常顯示。那麼這裡,我們換一種思路,實現一個不一樣的懸浮窗。
一、應用內懸浮窗實現思路
通常的懸浮窗是通過WindowManager
直接新增的,在不同的Android系統上需要做不同的適配,在Android
6.0以上的機型上,還需要引導使用者跳轉到設定介面手動開啟懸浮窗許可權。雖然這樣實現懸浮窗有完整的解決方案,但是開啟懸浮窗過程對使用者並不是很友好。下面,我們換一種思路,去使用一個應用內懸浮窗,避免機型適配和許可權申請的坑,讓懸浮窗像普通的View
一樣顯示在介面上。
一般懸浮窗的實現方案是向系統window
新增type
為TYPE_PHONE
或者TYPE_TOAST
的View
,從而使懸浮窗可以作為一個獨立的View
進行展示。Android
對這一行為作了限制,那我們可以考慮從比較常規的途徑新增View
:向每一個展示介面,即Activity
,新增一個View
作為懸浮窗。這樣,我們使用懸浮窗時就可以避免適配和許可權問題。那麼,怎麼樣實現這樣的懸浮窗更好呢?
要實現這樣一個懸浮窗,相當於我們要在Activity
載入完後將懸浮窗的View
新增的Activity
上,我們不想在原有的Activity上插入這段程式碼,這時就可以利用ActivityLifecycleCallbacks
和fragment
的載入特性來完成一個無侵入式的懸浮窗的顯示。
二、應用內懸浮窗的實現
- 首先,我們先自定義一個
View
用於顯示懸浮窗介面,就叫它FloatingWindow
。至於怎麼實現,這個各位可以自由發揮。 - 接下來,我們要把
FloatingWindow
新增到每一個Activity
上,這時就利用ActivityLifecycleCallbacks
。Activity
的每個生命週期都能回撥到ActivityLifecycleCallbacks
,這時我們只要在onActivityCreated(Activity activity, Bundle savedInstanceState)
中加上懸浮窗View
。但是,onActivityCreated(Activity activity, Bundle savedInstanceState)
方法是在onCreate(Bundle savedInstanceState)
時被呼叫的,我們需要保證在setContentView()
之後才新增懸浮窗,讓懸浮窗處於上層,所以我們插入一個空Fragment,利用Fragment
的onActivityCreated(Bundle savedInstanceState)
是在Activity
的onCreate(Bundle savedInstanceState)
之後的特性來加入懸浮窗。
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
super.onActivityCreated(activity, savedInstanceState);
if (activity instanceof FragmentActivity) {
FragmentManager fm = ((FragmentActivity) activity).getSupportFragmentManager();
fm.beginTransaction().add(new SupportFragment(), FRAGMENT_TAG).commitAllowingStateLoss();
}
}
...
});
public static class SupportFragment extends Fragment {
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Activity activity = getActivity();
if (activity != null) {
FloatingWindow fw = new FloatingWindow(activity);
activity.addContentView(fw, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
}
}
複製程式碼
通過這幾行核心程式碼,我們便完成了一個不需要許可權申請的懸浮窗。細節一點的實現可以參考我的demo:github.com/windinwork/…
三、總結
像我們這樣的懸浮窗,有優點也有缺點。優點顯而易見,它不需要向系統申請特殊的許可權即可正常顯示;缺點的話即是每一個Activity
都有一個懸浮窗,相互獨立存在,當然這個是可以優化一下實現方式解決的,這裡不細講,另一個缺點即是這樣的懸浮窗無法在應用退到後臺的時候存在,當然在在合適的應用場景這也不是問題。以上便是一個無侵入式無許可權的懸浮窗實現方式,希望能為小夥伴提供不同的懸浮窗實現思路。