那曲檬骨新材料有限公司

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

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

3天內(nèi)不再提示

鴻蒙OS開發(fā)實戰(zhàn):【懸浮窗口】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-03-28 20:39 ? 次閱讀

背景

懸浮視圖或者窗體,在AndroidiOS兩大移動平臺均有使用,HarmonyOS 也實現(xiàn)了此功能,如下為大家分享一下效果

準備

  1. 熟讀HarmonyOS 懸浮窗口指導
  2. 熟讀HarmonyOS 手勢指導
  3. 熟讀ALC簽名指導,用于可以申請 “ohos.permission.SYSTEM_FLOAT_WINDOW” 權限。
  4. 熟悉的文檔在下方
    |

搜狗高速瀏覽器截圖20240326151547.png

實踐代碼

  1. 如果開啟了懸浮窗口,任何界面的物理返回鍵事件都會被懸浮窗口攔截掉,即 手勢返回廢了
  2. 參數(shù)類型易混淆, 拖動 PanGesture 中的onActionUpdate接口,數(shù)據(jù)單位為 vp ,window中的 moveWindowTo接口參數(shù),數(shù)據(jù)單位為px
  3. 采用moveWindowTo實現(xiàn)的窗口拖動效果十分不平滑
  4. 通過 requestPermissionsFromUser 申請 ohos.permission.SYSTEM_FLOAT_WINDOW 權限時,無法彈出系統(tǒng)權限提示框

片段代碼

配置module.json5

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "phone",
      "tablet"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
......
      {
        "name": "FloatWindowAbility",
        "srcEntry": "./ets/myentryability/FloatWindowAbility.ts",
        "description": "$string:FloatWindowAbility_desc",
        "icon": "$media:icon",
        "label": "$string:FloatWindowAbility_label",
        "startWindowIcon": "$media:icon",
        "startWindowBackground": "$color:start_window_background",
      },
    ],
    "requestPermissions": [
       {
        "name": "ohos.permission.SYSTEM_FLOAT_WINDOW",
        "usedScene": {
          "abilities": [
            "FloatWindowAbility"
          ],
          "when": "always"
        }
      }
    ]
  }
}

懸浮窗口UIAbility

import window from '@ohos.window';
import BaseUIAbility from '../baseuiability/BaseUIAbility';
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';

const permissions: Array< Permissions > = ['ohos.permission.SYSTEM_FLOAT_WINDOW'];

export default class FloatWindowAbility extends BaseUIAbility {

  onWindowStageCreate(windowStage: window.WindowStage) {
    // Main window is created, set main page for this ability
    let context = this.context;
    let atManager = abilityAccessCtrl.createAtManager();

    checkPermissions().then((result)= >{
      if(result){
        // requestPermissionsFromUser會判斷權限的授權狀態(tài)來決定是否喚起彈窗
        atManager.requestPermissionsFromUser(context, permissions).then((data) = > {
          let grantStatus: Array< number > = data.authResults;
          let length: number = grantStatus.length;

          for (let i = 0; i < length; i++) {
            if (grantStatus[i] === 0) {
              // 用戶授權,可以繼續(xù)訪問目標操作
              console.log('用戶授權,可以繼續(xù)訪問目標操作')
            } else {
              // 用戶拒絕授權,提示用戶必須授權才能訪問當前頁面的功能,并引導用戶到系統(tǒng)設置中打開相應的權限
              console.log('用戶拒絕授權,提示用戶必須授權才能訪問當前頁面的功能,并引導用戶到系統(tǒng)設置中打開相應的權限')
              return;
            }
          }

          // 授權成功
          // 1.創(chuàng)建懸浮窗。
          let windowClass = null;
          let config = {name: "floatWindow", windowType: window.WindowType.TYPE_FLOAT, ctx: this.context};
          window.createWindow(config, (err, data) = > {
            if (err.code) {
              console.error('Failed to create the floatWindow. Cause: ' + JSON.stringify(err));
              return;
            }
            console.info('Succeeded in creating the floatWindow. Data: ' + JSON.stringify(data));
            windowClass = data;

            // 2.懸浮窗窗口創(chuàng)建成功后,設置懸浮窗的位置、大小及相關屬性等。
            windowClass.moveWindowTo(0, 200, (err) = > {
              if (err.code) {
                console.error('Failed to move the window. Cause:' + JSON.stringify(err));
                return;
              }
              console.info('Succeeded in moving the window.');
            });
            windowClass.resize(1080, 151, (err) = > {
              if (err.code) {
                console.error('Failed to change the window size. Cause:' + JSON.stringify(err));
                return;
              }
              console.info('Succeeded in changing the window size.');

            });

            // 3.為懸浮窗加載對應的目標頁面。
            windowClass.setUIContent("custompages/FloatPage", (err) = > {
              if (err.code) {
                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
                return;
              }
              console.info('Succeeded in loading the content.');
              // 3.顯示懸浮窗。
              windowClass.showWindow((err) = > {
                if (err.code) {
                  console.error('Failed to show the window. Cause: ' + JSON.stringify(err));
                  return;
                }
                console.info('Succeeded in showing the window.');
              });

              try {
                windowClass.setWindowBackgroundColor('#00000000')
              } catch (exception) {
                console.error('Failed to set the background color. Cause: ' + JSON.stringify(exception));
              }

            });

          })

        }).catch((err) = > {
          console.error(`requestPermissionsFromUser failed, code is ${err.code}, message is ${err.message}`);
        })

      }
    })

  }

}

async function checkAccessToken(permission: Permissions): Promise< abilityAccessCtrl.GrantStatus > {
  let atManager = abilityAccessCtrl.createAtManager();
  let grantStatus: abilityAccessCtrl.GrantStatus;

  // 獲取應用程序的accessTokenID
  let tokenId: number;
  try {
    let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
    let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
    tokenId = appInfo.accessTokenId;
  } catch (err) {
    console.error(`getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}`);
  }

  // 校驗應用是否被授予權限
  try {
    grantStatus = await atManager.checkAccessToken(tokenId, permission);
  } catch (err) {
    console.error(`checkAccessToken failed, code is ${err.code}, message is ${err.message}`);
  }

  return grantStatus;
}

async function checkPermissions(): Promise< boolean > {
  const permissions: Array< Permissions > = ['ohos.permission.SYSTEM_FLOAT_WINDOW'];
  let grantStatus: abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions[0]);

  if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
    // 已經(jīng)授權,可以繼續(xù)訪問目標操作
    console.log('沒有授權')
    return true
  } else {
    // 申請日歷權限
    console.log('已授權')
    return false
  }
}

懸浮窗口頁面

import common from '@ohos.app.ability.common';
import window from '@ohos.window';

@Entry
@Component
struct Index {
  @State lasttime: number = 0

  @State message: string = '懸浮窗'
  @State foldStatus: boolean = false
  @State idleName: string = '收起'
  @State floatWindowWidth: number = 0
  @State offsetX: number = 0
  @State offsetY: number = 0
  @State positionX: number = 0
  @State positionY: number = 0
  @State windowPosition: Position = { x: 0, y: 0 };

  private context = getContext(this) as common.UIAbilityContext;
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });

  floatWindow: window.Window

  aboutToAppear(){
    this.eventHubFunc()
    this.floatWindow = window.findWindow("floatWindow")
    this.floatWindowWidth = 1080
    this.panOption.setDistance(1)
  }

  onBackPress(){
    console.log('返回')
  }

  build() {
    Row() {

         Text('X').width(px2vp(140))
           .textAlign(TextAlign.Center)
           .fontColor(Color.Red).onClick(()= >{
           //關閉所依賴的UIAbility
           this.context.terminateSelf()
           //銷毀懸浮窗。當不再需要懸浮窗時,可根據(jù)具體實現(xiàn)邏輯,使用destroy對其進行銷毀。
           this.floatWindow.destroyWindow((err) = > {
             if (err.code) {
               console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));
               return;
             }
             console.info('Succeeded in destroying the window.');
           });
         })

         Text(this.idleName)
           .width(px2vp(140))
           .height('100%')
           .fontSize(18)
           .fontColor(Color.White)
           .textAlign(TextAlign.Center)
           .backgroundColor(Color.Gray)
           .onClick(()= >{
             this.foldStatus = !this.foldStatus

             if(this.foldStatus){
               this.idleName = "展開"
               this.floatWindowWidth = 280
             } else {
               this.idleName = "收起"
               this.floatWindowWidth = 1080
             }
           })

         Divider().vertical(true).color(Color.Red)

         if(!this.foldStatus) {
           Text(this.message)
             .width(px2vp(800))
             .fontSize(18)
             .fontColor(Color.White)
             .padding('12vp')
         }

    }
    .width(px2vp(this.floatWindowWidth))
    .height(px2vp(150))
    .borderRadius('12vp')
    .backgroundColor(Color.Green)
    .gesture(
      // 綁定PanGesture事件,監(jiān)聽拖拽動作
      PanGesture(this.panOption)
        .onActionStart((event: GestureEvent) = > {
          console.info('Pan start');
        })
          // 發(fā)生拖拽時,獲取到觸摸點的位置,并將位置信息傳遞給windowPosition
        .onActionUpdate((event: GestureEvent) = > {

          console.log(event.offsetX +' ' + event.offsetY)

          this.offsetX = this.positionX + event.offsetX
          this.offsetY = this.positionY + event.offsetY

          this.floatWindow.moveWindowTo(vp2px(this.offsetX), vp2px(this.offsetY));

        })
        .onActionEnd(() = > {
          this.positionX = this.offsetX
          this.positionY = this.offsetY
          console.info('Pan end');
        })
    )

  }

  eventHubFunc() {
    this.context.eventHub.on('info', (data) = > {
        this.message = data
    });
  }

}

審核編輯 黃宇

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

    關注

    57

    文章

    2392

    瀏覽量

    43046
  • HarmonyOS
    +關注

    關注

    79

    文章

    1982

    瀏覽量

    30567
  • 鴻蒙OS
    +關注

    關注

    0

    文章

    190

    瀏覽量

    4537
收藏 人收藏

    評論

    相關推薦

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

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

    鴻蒙實戰(zhàn)基礎(ArkTS)-窗口管理

    (CommonConstants.HOME_PAGE_ACTION); }, CommonConstants.LOGIN_WAIT_TIME); } 本文主要是對基于窗口能力,實現(xiàn)驗證碼登錄的場景。有關鴻蒙的進階技能大家可以前往主頁查看更多
    發(fā)表于 01-12 17:51

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

    一、設置懸浮窗說明 懸浮窗可以在已有的任務基礎上,創(chuàng)建一個始終在前臺顯示的窗口。即使創(chuàng)建懸浮窗的任務退至后臺,懸浮窗仍然可以在前臺顯示。通常
    發(fā)表于 02-04 14:05

    鴻蒙實戰(zhàn)項目開發(fā):【短信服務】

    數(shù)據(jù)管理 電話服務 分布式應用開發(fā) 通知與窗口管理 多媒體技術 安全技能 任務管理 WebGL 國際化開發(fā) 應用測試 DFX面向未來設計 鴻蒙系統(tǒng)移植和裁剪定制 …… ? 《
    發(fā)表于 03-03 21:29

    鴻蒙OS崛起,鴻蒙應用開發(fā)工程師成市場新寵

    應用的形態(tài)也在發(fā)生著翻天覆地的變化。作為全球領先的移動操作系統(tǒng)和智能終端制造商,華為公司自主研發(fā)的鴻蒙OS應運而生,致力于構建一個統(tǒng)一的分布式操作系統(tǒng),為各行各業(yè)的應用開發(fā)帶來全新的可能性。 一、
    發(fā)表于 04-29 17:32

    OpenHarmony實戰(zhàn)開發(fā)-如何實現(xiàn)窗口開發(fā)概述

    ],單位為vp。 系統(tǒng)窗口存在大小限制,寬度范圍:[0, 2560],高度范圍:[0, 2560],單位為vp。 最后 如果大家覺得這篇內(nèi)容對學習鴻蒙開發(fā)有幫助,我想邀請大家?guī)臀胰齻€小忙: 點贊,轉(zhuǎn)發(fā),有
    發(fā)表于 05-06 14:29

    鴻蒙OS應用程序開發(fā)

    這份學習文檔主要是帶領大家在鴻蒙OS上學習開發(fā)一個應用程序,主要知識點如下:1、U-Boot引導文件燒寫方式;2、內(nèi)核鏡像燒寫方式;3、鏡像運行。
    發(fā)表于 09-11 14:39

    鴻蒙 OS 應用開發(fā)初體驗

    的操作系統(tǒng)平臺和開發(fā)框架。HarmonyOS 的目標是實現(xiàn)跨設備的無縫協(xié)同和高性能。 DevEco Studio 對標 Android Studio,開發(fā)鴻蒙 OS 應用的 IDE。
    發(fā)表于 11-02 19:38

    鴻蒙OS 2.0手機開發(fā)者Beta版發(fā)布會在京舉辦

    三個月前,鴻蒙OS 2.0正式在華為開發(fā)者大會2020亮相。12月16日,鴻蒙OS 2.0手機開發(fā)
    的頭像 發(fā)表于 12-16 09:29 ?1.9w次閱讀

    華為發(fā)布鴻蒙OS Beta版

    昨天華為發(fā)布鴻蒙OS Beta版了?鴻蒙系統(tǒng)一直在按照既有步伐前進,現(xiàn)在華為發(fā)布鴻蒙OS Beta版,而且一些生態(tài)
    的頭像 發(fā)表于 12-17 08:41 ?2929次閱讀

    鴻蒙OS與Lite OS的區(qū)別是什么

    鴻蒙OS鴻蒙OS面向未來、面向全場景、分布式。在單設備系統(tǒng)能力基礎上,鴻蒙OS提出了基于同一套系
    的頭像 發(fā)表于 12-24 12:40 ?5097次閱讀

    鴻蒙os怎么升級

    6月2日,華為正式發(fā)布了鴻蒙armonyOS 2系統(tǒng),那么鴻蒙os如何升級?現(xiàn)將鴻蒙os升級方式告知如下。
    的頭像 發(fā)表于 06-08 16:26 ?2803次閱讀

    華為開發(fā)者大會2021鴻蒙os在哪場

    華為開發(fā)者大會2021將在10月22日-24日舉辦,地點為東莞松山湖,鴻蒙os 3.0或?qū)⑴c我們見面,那么華為開發(fā)者大會2021鴻蒙
    的頭像 發(fā)表于 10-22 15:24 ?1954次閱讀

    RISC-V MCU開發(fā)實戰(zhàn) (三):移植鴻蒙OS項目

    移植鴻蒙OS項目
    的頭像 發(fā)表于 11-01 11:08 ?2998次閱讀
    RISC-V MCU<b class='flag-5'>開發(fā)</b><b class='flag-5'>實戰(zhàn)</b> (三):移植<b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b>項目

    鴻蒙實戰(zhàn)開發(fā):【實現(xiàn)應用懸浮窗】

    如果你要做的是系統(tǒng)級別的懸浮窗,就需要判斷是否具備懸浮窗權限。然而這又不是一個標準的動態(tài)權限,你需要兼容各種奇葩機型的懸浮窗權限判斷。
    的頭像 發(fā)表于 04-03 22:18 ?540次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>實戰(zhàn)</b><b class='flag-5'>開發(fā)</b>:【實現(xiàn)應用<b class='flag-5'>懸浮</b>窗】
    沽源县| 百家乐官网金海岸软件| 长江百家乐官网的玩法技巧和规则 | 大发888网页登录帐号| 百家乐官网最新打法| 百家乐官网娱乐场开户注册| 百家乐龙虎桌布| 大发德州扑克| 百家乐官网号技巧| 蓝盾百家乐庄家利润分| 一起游乐棋牌下载| 百家乐官网网上投注作弊| 百家乐赢足球博彩皇冠| 德州扑克玩法说明| 百家乐官网网站建设| 澳门百家乐海洋阿强| 香港六合彩官方网站| 菲律宾百家乐官网娱乐| 找真人百家乐的玩法技巧和规则 | 百家乐官网伴侣| 百家乐15人桌| 百家乐官网厅| 百家乐最安全打法| 百家乐官网出千原理| 百家乐管理启发书| 百乐门娱乐| 百家乐蓝盾假网| 狮威娱乐城| 百家乐游戏算牌| 大发扑克网站| 24山什么来龙是真龙| 蜀都棋牌游戏| 网址百家乐官网的玩法技巧和规则| 永利高平台| 网上百家乐官网有哪些玩法| 爱拼百家乐的玩法技巧和规则| 百家乐官网的技术与心态| 百家乐网上真钱娱乐网| 百家乐官网视频多开器| 百家乐博弈之赢者理论坛| 百家乐官网投注法|