非侵入式無(wú)權(quán)限應(yīng)用內(nèi)懸浮窗的實(shí)現(xiàn)

前言

一般的懸浮窗實(shí)現(xiàn)方式,需要申請(qǐng)權(quán)限,并還是要對(duì)部分機(jī)型進(jìn)行適配才能正常顯示。那么這里,我們換一種思路,實(shí)現(xiàn)一個(gè)不一樣的懸浮窗。

一、應(yīng)用內(nèi)懸浮窗實(shí)現(xiàn)思路

通常的懸浮窗是通過(guò)WindowManager直接添加的,在不同的Android系統(tǒng)上需要做不同的適配,在Android6.0以上的機(jī)型上,還需要引導(dǎo)用戶(hù)跳轉(zhuǎn)到設(shè)置界面手動(dòng)開(kāi)啟懸浮窗權(quán)限。雖然這樣實(shí)現(xiàn)懸浮窗有完整的解決方案,但是開(kāi)啟懸浮窗過(guò)程對(duì)用戶(hù)并不是很友好。下面,我們換一種思路,去使用一個(gè)應(yīng)用內(nèi)懸浮窗,避免機(jī)型適配和權(quán)限申請(qǐng)的坑,讓?xiě)腋〈跋衿胀ǖ?code>View一樣顯示在界面上。

一般懸浮窗的實(shí)現(xiàn)方案是向系統(tǒng)window添加typeTYPE_PHONE或者TYPE_TOASTView,從而使懸浮窗可以作為一個(gè)獨(dú)立的View進(jìn)行展示。Android對(duì)這一行為作了限制,那我們可以考慮從比較常規(guī)的途徑添加View:向每一個(gè)展示界面,即Activity,添加一個(gè)View作為懸浮窗。這樣,我們使用懸浮窗時(shí)就可以避免適配和權(quán)限問(wèn)題。那么,怎么樣實(shí)現(xiàn)這樣的懸浮窗更好呢?

要實(shí)現(xiàn)這樣一個(gè)懸浮窗,相當(dāng)于我們要在Activity加載完后將懸浮窗的View添加的Activity上,我們不想在原有的Activity上插入這段代碼,這時(shí)就可以利用ActivityLifecycleCallbacksfragment的加載特性來(lái)完成一個(gè)無(wú)侵入式的懸浮窗的顯示。

二、應(yīng)用內(nèi)懸浮窗的實(shí)現(xiàn)

  1. 首先,我們先自定義一個(gè)View用于顯示懸浮窗界面,就叫它FloatingWindow。至于怎么實(shí)現(xiàn),這個(gè)各位可以自由發(fā)揮。
  2. 接下來(lái),我們要把FloatingWindow添加到每一個(gè)Activity上,這時(shí)就利用ActivityLifecycleCallbacks。Activity的每個(gè)生命周期都能回調(diào)到ActivityLifecycleCallbacks,這時(shí)我們只要在onActivityCreated(Activity activity, Bundle savedInstanceState)中加上懸浮窗View。但是,onActivityCreated(Activity activity, Bundle savedInstanceState)方法是在onCreate(Bundle savedInstanceState)時(shí)被調(diào)用的,我們需要保證在setContentView()之后才添加懸浮窗,讓?xiě)腋〈疤幱谏蠈?,所以我們插入一個(gè)空Fragment,利用FragmentonActivityCreated(Bundle savedInstanceState)是在ActivityonCreate(Bundle savedInstanceState)之后的特性來(lái)加入懸浮窗。
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));
        }
    }
}

通過(guò)這幾行核心代碼,我們便完成了一個(gè)不需要權(quán)限申請(qǐng)的懸浮窗。細(xì)節(jié)一點(diǎn)的實(shí)現(xiàn)可以參考我的demo:https://github.com/windinwork/floatingwindowdemo

三、總結(jié)

像我們這樣的懸浮窗,有優(yōu)點(diǎn)也有缺點(diǎn)。優(yōu)點(diǎn)顯而易見(jiàn),它不需要向系統(tǒng)申請(qǐng)?zhí)厥獾臋?quán)限即可正常顯示;缺點(diǎn)的話(huà)即是每一個(gè)Activity都有一個(gè)懸浮窗,相互獨(dú)立存在,當(dāng)然這個(gè)是可以?xún)?yōu)化一下實(shí)現(xiàn)方式解決的,這里不細(xì)講,另一個(gè)缺點(diǎn)即是這樣的懸浮窗無(wú)法在應(yīng)用退到后臺(tái)的時(shí)候存在,當(dāng)然在在合適的應(yīng)用場(chǎng)景這也不是問(wèn)題。以上便是一個(gè)無(wú)侵入式無(wú)權(quán)限的懸浮窗實(shí)現(xiàn)方式,希望能為小伙伴提供不同的懸浮窗實(shí)現(xiàn)思路。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,057評(píng)論 25 709
  • 懶得處理樣式了, 將就著看吧. 官網(wǎng)地址: https://developer.android.com/topic...
    Reddington_604e閱讀 1,918評(píng)論 0 1
  • 1、懸浮窗的基本介紹 懸浮窗,大家應(yīng)該也不陌生,凌駕于應(yīng)用之上的一個(gè)小彈窗,實(shí)現(xiàn)上很簡(jiǎn)單,就是添加一個(gè)系統(tǒng)級(jí)別的窗...
    C6C閱讀 48,473評(píng)論 50 83
  • 湖北荊州公安金獅谷升寺,村人素強(qiáng)橫,遠(yuǎn)近聞名。 有跑江湖的來(lái)賣(mài)藝,一老一小,一挑擔(dān)。老者團(tuán)團(tuán)作揖,介紹:此為古彩戲...
    快樂(lè)的山地人閱讀 2,730評(píng)論 1 2
  • 伊娃格林是我的女神,所以我的昵稱(chēng)就是我的女神。 今年24歲,大學(xué)專(zhuān)業(yè)是商務(wù)日語(yǔ)。畢業(yè)后由于專(zhuān)業(yè)不精又不清楚自己想干...
    吃了個(gè)西瓜閱讀 742評(píng)論 0 0

友情鏈接更多精彩內(nèi)容