色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙實戰開發:【實現應用懸浮窗】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-03 22:18 ? 次閱讀

如果你要做的是系統級別的懸浮窗,就需要判斷是否具備懸浮窗權限。然而這又不是一個標準的動態權限,你需要兼容各種奇葩機型的懸浮窗權限判斷,下面的代碼來自于某著名開源庫:EasyFloat[1] 。

fun checkPermission(context: Context): Boolean =
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) when {
    RomUtils.checkIsHuaweiRom() - > huaweiPermissionCheck(context)
    RomUtils.checkIsMiuiRom() - > miuiPermissionCheck(context)
    RomUtils.checkIsOppoRom() - > oppoROMPermissionCheck(context)
    RomUtils.checkIsMeizuRom() - > meizuPermissionCheck(context)
    RomUtils.checkIs360Rom() - > qikuPermissionCheck(context)
            else - > true
} else commonROMPermissionCheck(context)

private fun commonROMPermissionCheck(context: Context): Boolean =
        if (RomUtils.checkIsMeizuRom()) meizuPermissionCheck(context) else {
            var result = true
            if (Build.VERSION.SDK_INT >= 23) try {
                val clazz = Settings::class.java
                val canDrawOverlays = clazz.getDeclaredMethod("canDrawOverlays", Context::class.java)
                result = canDrawOverlays.invoke(null, context) as Boolean
            } catch (e: Exception) {
                Log.e(TAG, Log.getStackTraceString(e))
            }
            result
        }

如果你要做的是應用內的全局懸浮窗,那么對不起,不支持,自己想辦法。普遍的做法是在根布局 DecorView 直接塞進去。

遙遙領先qr23.cn/AKFP8k獲取

.png

或者加mau123789是v直接領取!

鴻蒙上實現懸浮窗相對就要簡單的多。

對于系統級別彈窗,仍然需要權限,但也不至于那么麻煩的適配。

對于應用內全局彈出,鴻蒙提供了 應用子窗口 可以直接實現。

本文主要介紹如何利用應用子窗口實現應用內全局懸浮窗。

創建應用子窗口需要先拿到窗口管理器 WindowStage 對象,在 EntryAbility.onWindowStageCreate() 回調中取。

FloatManager.init(windowStage)

init(windowStage: window.WindowStage) {
  this.windowStage_ = windowStage
}

然后通過 WindowStage.createSubWindow() 創建子窗口。

// 創建子窗口
showSubWindow() {
    if (this.windowStage_ == null) {
        Log.error(TAG, 'Failed to create the subwindow. Cause: windowStage_ is null');
    } else {
        this.windowStage_.createSubWindow("HarmonyWorld", (err: BusinessError, data) = > {
            ...
            this.sub_windowClass = data;
            // 子窗口創建成功后,設置子窗口的位置、大小及相關屬性等
            // moveWindowTo 和 resize 都可以重復調用,實現拖拽效果
            this.sub_windowClass.moveWindowTo(this.locationX, this.locationY, (err: BusinessError) = > {
                ...
            });
            this.sub_windowClass.resize(this.size, this.size, (err: BusinessError) = > {
                ...
            });
            // 給子窗口設置內容
            this.sub_windowClass.setUIContent("pages/float/FloatPage", (err: BusinessError) = > {
                ...
                // 顯示子窗口。
                (this.sub_windowClass as window.Window).showWindow((err: BusinessError) = > {
                    ...
                    // 設置透明背景
                    data.setWindowBackgroundColor("#00000000")
                });
            });
        })
    }
}

這樣就可以在指定位置顯示指定大小的的懸浮窗了。

然后再接著完善手勢拖動和點擊事件。

既要監聽拖動,又要監聽手勢,就需要通過 GestoreGroup,并把設置模式設置為 互斥識別

@Entry
@Component
export struct FloatPage {
  private context = getContext(this) as common.UIAbilityContext

  build() {
    Column() {
      Image($r('app.media.mobile_dev'))
        .width('100%')
        .height('100%')
    }
    .gesture(
      GestureGroup(GestureMode.Exclusive,
        // 監聽拖動
        PanGesture()
          .onActionUpdate((event: GestureEvent | undefined) = > {
            if (event) {
              // 更新懸浮窗位置
              FloatManager.updateLocation(event.offsetX, event.offsetY)
            }
          }),
        // 監聽點擊
        TapGesture({ count: 1 })
          .onAction(() = > {
             router.pushUrl(...)
          }))
    )
  }
}

在拖動手勢 PanGestureonActionUpdate() 回調中,可以實時拿到拖動的距離,然后通過 Window.moveWindowTo() 就可以實時更新懸浮窗的位置了。

updateLocation(offSetX: number, offsetY: number) {
    if (this.sub_windowClass != null) {
        this.locationX = this.locationX + offSetX
        this.locationY = this.locationY + offsetY
        this.sub_windowClass.moveWindowTo(this.locationX, this.locationY, (err: BusinessError) = > {
            ......
        });
    }
}

在點擊手勢 TapGesture中,我的需求是路由到指定頁面,直接調用 router.pushUrl()。看似很正常的調用,在這里確得到了意想不到的結果。

發生頁面跳轉的并不是預期中的應用主窗口,而是應用子窗口。

把問題拋到群里之后,得到了群友的熱心解答。

每個 Window 對應自己的 UIContext,UIContext 持有自己的 Router ,所以應用主窗口和應用子窗口的 Router 是相互獨立的。

那么,問題就變成了如何在子窗口中讓主窗口進行路由跳轉?通過 EventHub 或者 emitter 都可以。emiiter 可以跨線程,這里并不需要,EventHub 寫起來更簡單。我們在點擊手勢中發送事件:

TapGesture({ count: 1 })
  .onAction(() = > {
      this.context.eventHub.emit("event_click_float")
  })

EntryAbility 中訂閱事件:

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    eventHub.on("event_click_float", () = > {
      if (this.mainRouter) {
        this.mainRouter.pushUrl(...)
      }
    })
}

這里的 mainRouter 我們可以提前在主 Window 調用 loadContent() 之后獲取:

windowStage.loadContent(pages/Index', (err, data) = > {
  this.mainRouter = this.windowClass!.getUIContext().getRouter()
});

最后還有一個小細節,如果在拖動懸浮窗之后,再使用系統的返回手勢,按照預期應該是主窗口的頁面返回,但這時候焦點在子窗口,主窗口并不會響應返回手勢。

我們需要在子窗口承載的 Page 頁面監聽 onBackPress(),并通過 EventHub 通知主窗口。

onBackPress(): boolean | void {
    this.context.eventHub.emit("float_back")
  }

主窗口接收到通知后,調用 mainRouter.back 。

eventHub.on("clickFloat", () = > {
  if (this.mainRouter) {
    this.mainRouter.back()
  }
})

應用內全局,可拖拽的懸浮窗就完成了。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鴻蒙
    +關注

    關注

    57

    文章

    2339

    瀏覽量

    42805
收藏 人收藏

    評論

    相關推薦

    鴻蒙Flutter實戰:11-使用 Flutter SDK 3.22.0

    # 使用 Flutter SDK 3.22.0 ## SDK 安裝 參考[鴻蒙Flutter實戰:01-搭建開發環境]文章的說明,首先安裝 Flutter SDK 3.22.0。 目前
    發表于 11-01 15:03

    鴻蒙Flutter實戰:08-如何調試代碼

    # 鴻蒙Flutter實戰:如何調試代碼 ## 1.環境搭建 參考文章[鴻蒙Flutter實戰:01-搭建開發環境](https://g
    發表于 10-23 16:29

    鴻蒙Flutter實戰:07混合開發

    # 鴻蒙Flutter實戰:混合開發 鴻蒙Flutter混合開發主要有兩種形式。 ## 1.基于har 將flutter module
    發表于 10-23 16:00

    鴻蒙Flutter實戰:05-使用第三方插件

    # 鴻蒙Flutter 實戰:使用第三方插件 在鴻蒙Flutter開發中,如果涉及到使用原生功能,就要使用插件。使用插件有兩種方式,一種是自己編寫原生ArkTS代碼,在Dart側調用
    發表于 10-22 21:54

    36歲了還有必要轉行鴻蒙開發嗎?

    開發員的職業前景光明,提供了大量的創新機會,助力實現個人職業目標。 最后 如果大家覺得這篇內容對學習鴻蒙開發有幫助,我想邀請大家幫我三個小忙: 點贊,轉發,有你們的 『點贊和評論』,
    發表于 05-09 17:01

    HarmonyOS實戰開發-如何通過BlendMode屬性來實現掛件和圖片的混合

    ||---BlendModeView.ets // 視圖層-應用主頁面 模塊依賴 本實例依賴common模塊來實現日志的打印、資源 的調用、依賴動態路由模塊來實現頁面的動態加載。 最后 如果大家覺得這篇內容對學習鴻蒙
    發表于 05-07 14:45

    OpenHarmony實戰開發-如何實現窗口開發概述

    你們的 『點贊和評論』,才是我創造的動力。 關注小編,同時可以期待后續文章ing?,不定期分享原創知識。 更多鴻蒙最新技術知識點,請關注作者博客:鴻蒙實戰經驗分享:鴻蒙基礎入門
    發表于 05-06 14:29

    鴻蒙OS開發學習:【尺寸適配實現

    鴻蒙開發中,尺寸適配是一個重要的概念,它可以幫助我們在不同屏幕尺寸的設備上正確顯示和布局我們的應用程序。本文將介紹如何在鴻蒙開發實現尺寸
    的頭像 發表于 04-10 16:05 ?1733次閱讀
    <b class='flag-5'>鴻蒙</b>OS<b class='flag-5'>開發</b>學習:【尺寸適配<b class='flag-5'>實現</b>】

    鴻蒙OS元服務開發:【(Stage模型)設置懸浮

    懸浮可以在已有的任務基礎上,創建一個始終在前臺顯示的窗口。即使創建懸浮的任務退至后臺,懸浮
    的頭像 發表于 04-03 15:32 ?1099次閱讀
    <b class='flag-5'>鴻蒙</b>OS元服務<b class='flag-5'>開發</b>:【(Stage模型)設置<b class='flag-5'>懸浮</b><b class='flag-5'>窗</b>】

    鴻蒙OS開發實戰:【懸浮窗口】

    懸浮視圖或者窗體,在Android和iOS兩大移動平臺均有使用,HarmonyOS 也實現了此功能,如下為大家分享一下效果。
    的頭像 發表于 03-28 20:39 ?1053次閱讀
    <b class='flag-5'>鴻蒙</b>OS<b class='flag-5'>開發</b><b class='flag-5'>實戰</b>:【<b class='flag-5'>懸浮</b>窗口】

    深圳市24年,實現鴻蒙原生應用數占全國總量10%以上

    行動計劃》 深圳市提出在鴻蒙原生應用發展上的具體目標:在2024年內實現深圳市鴻蒙原生應用數量占全國總量10%以上;深圳市主要垂域實現鴻蒙
    發表于 03-04 21:42

    鴻蒙實戰項目開發:【短信服務】

    、OpenHarmony 多媒體技術、Napi組件、OpenHarmony內核、Harmony南向開發鴻蒙項目實戰等等)鴻蒙(Harmony NEXT) 技術知識點 如果你是一名An
    發表于 03-03 21:29

    鴻蒙應用/元服務開發-窗口(Stage模型)設置懸浮

    一、設置懸浮說明 懸浮可以在已有的任務基礎上,創建一個始終在前臺顯示的窗口。即使創建懸浮
    發表于 02-04 14:05

    使用 Taro 開發鴻蒙原生應用 —— 快速上手,鴻蒙應用開發指南

    隨著鴻蒙系統的不斷完善,許多應用廠商都希望將自己的應用移植到鴻蒙平臺上。最近,Taro 發布了 v4.0.0-beta.x 版本,支持使用 Taro 快速開發鴻蒙原生應用,也可將現有的
    的頭像 發表于 02-02 16:09 ?859次閱讀
    使用 Taro <b class='flag-5'>開發</b><b class='flag-5'>鴻蒙</b>原生應用 —— 快速上手,<b class='flag-5'>鴻蒙</b>應用<b class='flag-5'>開發</b>指南

    鴻蒙基礎開發實戰-(ArkTS)像素轉換

    的使用。通過像素轉換案例,向開發者講解了如何使用像素單位設置組件的尺寸、字體的大小以及不同像素單位之間的轉換方法。更多鴻蒙4.0的學習,可以前往主頁學習或前往《鴻蒙4.0開發學習目錄》
    發表于 01-11 16:53
    主站蜘蛛池模板: 国产亚洲精品香蕉视频播放| 成在线人免费| 3a丝袜论坛| 99热久久这里只精品国产WWW| 午夜阳光影院在线观看视频| 亚洲 日韩 在线 国产 视频| 亚洲视频中文字幕在线| 中文字幕久久久| av天堂影音先锋在线| 高h辣h双处全是肉一对一| 国产女人视频免费观看| 精品香蕉99久久久久网站| 两个人的视频hd全免费| 轻点慢点1V2啊高H抽插| 天天躁日日躁狠狠躁中文字幕老牛 | 有码 亚洲 制服 国产 在线| 正在播放一区二区| jlzz中国jizz日本老师水多| 国产产一区二区三区久久毛片国语| 国产人成高清在线视频99| 久久久久久久久久久福利观看| 欧美极限扩肛| 無码一区中文字幕少妇熟女网站| 亚洲国产在线2020最新| 18国产精品白浆在线观看免费| 成人性生交大片免费看中文 | 人人射人人爱| 洗濯屋H纯肉动漫在线观看| 在线免费视频国产| 高清mv视频免费观看| 九九99国产香蕉视频| 让男人玩尿道的女人| 亚洲男人的天堂久久精品麻豆| 99精品久久| 国产性夜夜性夜夜爽91| 免费网站在线观看国产v片| 无码日韩人妻精品久久蜜桃入口 | 亚洲国产AV无码综合在线| 99国产在线视频| 国产一级毛片在线| 欧美片内射欧美美美妇|