成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何創建子窗口并與主窗口通信(Window模塊以及AppStorage的使用)

開發 前端
本文使用AppStorage實現主窗口和子窗口之間的數據傳遞,除此之外,Emitter和EventHub等方式也可以實現,用戶可以根據實際業務需要進行選擇。

想了解更多關于開源的內容,請訪問:

51CTO 開源基礎軟件社區

https://ost.51cto.com

場景介紹

應用開發過程中,經常需要創建彈窗(子窗口)用來承載跟當前內容相關的業務,比如電話應用的撥號彈窗;閱讀應用中長按當前內容觸發的編輯彈窗;購物應用經常出現的抽獎活動彈窗等。
本文為大家介紹如何創建子窗口并實現子窗口與主窗口的數據通信。

效果呈現

本例最終效果如下:

如何創建子窗口并與主窗口通信(window模塊以及AppStorage的使用)-開源基礎軟件社區如何創建子窗口并與主窗口通信(window模塊以及AppStorage的使用)-開源基礎軟件社區

環境要求

本例基于以下環境開發,開發者也可以基于其他適配的版本進行開發:

  • IDE: DevEco Studio 4.0 Beta1。
  • SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1)。

實現思路

本例關鍵特性及實現方案如下:

  • 點擊“創建子窗口”按鈕創建子窗口:使用window模塊的createSubWindow方法創建子窗口,在創建時設置子窗口的大小、位置、內容等。
  • 子窗口可以拖拽:通過gesture屬性為子窗口綁定PanGesture拖拽事件,使用moveWindowTo方法將窗口移動到拖拽位置,呈現拖拽效果。
  • 點擊主窗口的“子窗口數據+1”按鈕,子窗口中的數據加1,反之亦然,即實現主窗口和子窗口間的數據通信:將數據變量存儲在AppStorage中,在主窗口和子窗口中引用該數據,并通過@StorageLink與AppStorage中的數據進行雙向綁定,從而實現主窗口和子窗口之間的數據聯動。
說明

本文使用AppStorage實現主窗口和子窗口之間的數據傳遞,除此之外,Emitter和EventHub等方式也可以實現,用戶可以根據實際業務需要進行選擇。

開發步驟

由于本例重點講解子窗口的創建以及主窗口和子窗口之間的通信,所以開發步驟會著重講解相關內容的開發,其余內容不做贅述,全量代碼可參考完整代碼章節。

創建子窗口。
使用createSubWindow方法創建名為“hiSubWindow”的子窗口,并設置窗口的位置、大小、顯示內容。將創建子窗口的動作放在自定義成員方法showSubWindow()中,方便后續綁定到按鈕上。具體代碼如下:

showSubWindow() {
    // 創建應用子窗口。
    this.windowStage.createSubWindow("hiSubWindow", (err, data) => {
      if (err.code) {
        console.error('Failed to create the subwindow. Cause: ' + JSON.stringify(err));
        return;
      }
      this.sub_windowClass = data;
      console.info('Succeeded in creating the subwindow. Data: ' + JSON.stringify(data));
      // 子窗口創建成功后,設置子窗口的位置
      this.sub_windowClass.moveWindowTo(300, 300, (err) => {
        if (err.code) {
          console.error('Failed to move the window. Cause:' + JSON.stringify(err));
          return;
        }
        console.info('Succeeded in moving the window.');
      });
      // 設置子窗口的大小
      this.sub_windowClass.resize(350, 350, (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.');
      });
      // 為子窗口加載對應的目標頁面。
      this.sub_windowClass.setUIContent("pages/SubWindow",(err) => {
        if (err.code) {
          console.error('Failed to load the content. Cause:' + JSON.stringify(err));
          return;
        }
        console.info('Succeeded in loading the content.');
        // 顯示子窗口。
        this.sub_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.');
        });
        this.sub_windowClass.setWindowBackgroundColor('#E8A027')
      });
    })
  }

實現子窗口可拖拽。
為頁面內容綁定PanGesture拖拽事件,拖拽事件發生時獲取到觸摸點的位置信息,使用@Watch監聽到位置變量的變化,然后調用窗口的moveWindowTo方法將窗口移動到對應位置,從而實現拖拽效果。
具體代碼如下:

import window from '@ohos.window';

interface Position {
  x: number,
  y: number
}

@Entry
@Component
struct SubWindow{
  ...
  // 創建位置變量,并使用@Watch監聽,變量發生變化調用moveWindow方法移動窗口
  @State @Watch("moveWindow") windowPosition: Position = { x: 0, y: 0 };
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
  private subWindow: window.Window
  // 通過懸浮窗名稱“hiSubWindow”獲取到創建的懸浮窗
  aboutToAppear() {
    this.subWindow = window.findWindow("hiSubWindow")
  }
  // 將懸浮窗移動到指定位置
  moveWindow() {
    this.subWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y);
  }

  build(){
    Column(){
      Text(`AppStorage保存的數據:${this.storData}`)
        .fontSize(12)
        .margin({bottom:10})
      Button('主窗口數據+1')
        .fontSize(12)
        .backgroundColor('#A4AE77')
        .onClick(()=>{
          this.storData += 1
        })
    }
    .height('100%')
    .width('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .gesture(
      PanGesture(this.panOption)
        .onActionStart((event: GestureEvent) => {
          console.info('Pan start');
        })
        // 發生拖拽時,獲取到觸摸點的位置,并將位置信息傳遞給windowPosition
        .onActionUpdate((event: GestureEvent) => {
          this.windowPosition.x += event.offsetX;
          this.windowPosition.y += event.offsetY;
        })
        .onActionEnd(() => {
          console.info('Pan end');
        })
    )
  }
}

實現主窗口和子窗口間的數據通信。本例中即實現點擊主窗口的“子窗口數據+1”按鈕,子窗口中的數據加1,反之亦然。本例使用應用全局UI狀態存儲AppStorage來實現對應效果。

  • 在創建窗口時觸發的onWindowStageCreate回調中將自定義數據變量“data”存入AppStorage。
onWindowStageCreate(windowStage: window.WindowStage) {
    // 將自定義數據變量“data”存入AppStorage
    AppStorage.SetOrCreate('data', 1);
    ...
    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }
  • 在主窗口中定義變量“storData”,并使用@StorageLink將其與AppStorage中的變量“data”進行雙向綁定,這樣一來,“mainData”的變化可以傳導至“data”,并且該變化可以被UI框架監聽到,從而完成UI狀態刷新。
...
// 使用@StorageLink將"mainData"與AppStorage中的變量"data"進行雙向綁定
@StorageLink('data') mainData: number = 1;
...
build() {
    Row() {
      Column() {
        Text(`AppStorage保存的數據:${this.mainData}`)
          .margin({bottom:30})
        Button('子窗口數據+1')
          .backgroundColor('#A4AE77')
          .margin({bottom:30})
          .onClick(()=>{
            // 點擊,storData的值加1
            this.mainData += 1
          })
      ...
      }
      .width('100%')
    }
    .height('100%')
  }
  • 在主窗口中定義變量“subData”,并使用@StorageLink將其與AppStorage中的變量“data”進行雙向綁定。由于主窗口的“mainData”也與“data”進行了綁定,因此,“mainData”的值可以通過“data”傳遞給“subData”,反之亦然。這樣就實現了主窗口和子窗口之間的數據同步。
...
// 使用@StorageLink將"subData"與AppStorage中的變量"data"進行雙向綁定
  @StorageLink('data') subData: number = 1;
...
  build(){
    Column(){
      Text(`AppStorage保存的數據:${this.subData}`)
        .fontSize(12)
        .margin({bottom:10})
      Button('主窗口數據+1')
        .fontSize(12)
        .backgroundColor('#A4AE77')
        .onClick(()=>{
          // 點擊,subData的值加1
          this.subData += 1
        })
    }
    ...
  }

完整代碼

本例完整代碼如下:
EntryAbility文件代碼:

// EntryAbility.ts
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';

let sub_windowClass = null;
export default class EntryAbility extends UIAbility {

  destroySubWindow() {
    // 銷毀子窗口。當不再需要子窗口時,可根據具體實現邏輯,使用destroy對其進行銷毀。
    sub_windowClass.destroyWindow((err) => {
      if (err.code) {
        console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));
        return;
      }
      console.info('Succeeded in destroying the window.');
    });
  }

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {

    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy() {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    // 將自定義數據變量“data”存入AppStorage
    AppStorage.SetOrCreate('data', 1);
    AppStorage.SetOrCreate('window', windowStage);
    // 為主窗口添加加載頁面
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }

  onWindowStageDestroy() {
    this.destroySubWindow();
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground() {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground() {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

主窗口代碼:

// Index.ets
import window from '@ohos.window';

@Entry
@Component
struct Index {
  // 使用@StorageLink將"mainData"與AppStorage中的變量"data"進行雙向綁定
  @StorageLink('data') mainData: number = 1;
  @StorageLink('window') storWindow:window.WindowStage = null
  private windowStage = this.storWindow
  private sub_windowClass = null

  showSubWindow() {
    // 創建應用子窗口。
    this.windowStage.createSubWindow("hiSubWindow", (err, data) => {
      if (err.code) {
        console.error('Failed to create the subwindow. Cause: ' + JSON.stringify(err));
        return;
      }
      this.sub_windowClass = data;
      console.info('Succeeded in creating the subwindow. Data: ' + JSON.stringify(data));
      // 子窗口創建成功后,設置子窗口的位置、大小及相關屬性等。
      this.sub_windowClass.moveWindowTo(300, 300, (err) => {
        if (err.code) {
          console.error('Failed to move the window. Cause:' + JSON.stringify(err));
          return;
        }
        console.info('Succeeded in moving the window.');
      });
      this.sub_windowClass.resize(350, 350, (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.');
      });
      // 為子窗口加載對應的目標頁面。
      this.sub_windowClass.setUIContent("pages/SubWindow",(err) => {
        if (err.code) {
          console.error('Failed to load the content. Cause:' + JSON.stringify(err));
          return;
        }
        console.info('Succeeded in loading the content.');
        // 顯示子窗口。
        this.sub_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.');
        });
        this.sub_windowClass.setWindowBackgroundColor('#E8A027')
      });
    })
  }

  build() {
    Row() {
      Column() {
        Text(`AppStorage保存的數據:${this.mainData}`)
          .margin({bottom:30})
        Button('子窗口數據+1')
          .backgroundColor('#A4AE77')
          .margin({bottom:30})
          .onClick(()=>{
            // 點擊,storData的值加1
            this.mainData += 1
          })
        Button('創建子窗口')
          .backgroundColor('#A4AE77')
          .onClick(()=>{
            // 點擊彈出子窗口
            this.showSubWindow()
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

子窗口代碼:

// SubWindow.ets
import window from '@ohos.window';

interface Position {
  x: number,
  y: number
}

@Entry
@Component
struct SubWindow{
  // 使用@StorageLink將"subData"與AppStorage中的變量"data"進行雙向綁定
  @StorageLink('data') subData: number = 1;
  // 創建位置變量,并使用@Watch監聽,變量發生變化調用moveWindow方法移動窗口
  @State @Watch("moveWindow") windowPosition: Position = { x: 0, y: 0 };
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
  private subWindow: window.Window
  // 通過懸浮窗名稱“hiSubWindow”獲取到創建的懸浮窗
  aboutToAppear() {
    this.subWindow = window.findWindow("hiSubWindow")
  }
  // 將懸浮窗移動到指定位置
  moveWindow() {
    this.subWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y);
  }

  build(){
    Column(){
      Text(`AppStorage保存的數據:${this.subData}`)
        .fontSize(12)
        .margin({bottom:10})
      Button('主窗口數據+1')
        .fontSize(12)
        .backgroundColor('#A4AE77')
        .onClick(()=>{
          // 點擊,subData的值加1
          this.subData += 1
        })
    }
    .height('100%')
    .width('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .gesture(
      PanGesture(this.panOption)
        .onActionStart((event: GestureEvent) => {
          console.info('Pan start');
        })
        // 發生拖拽時,獲取到觸摸點的位置,并將位置信息傳遞給windowPosition
        .onActionUpdate((event: GestureEvent) => {
          this.windowPosition.x += event.offsetX;
          this.windowPosition.y += event.offsetY;
        })
        .onActionEnd(() => {
          console.info('Pan end');
        })
    )
  }
}

想了解更多關于開源的內容,請訪問:

51CTO 開源基礎軟件社區

https://ost.51cto.com

責任編輯:jianghua 來源: 51CTO 開源基礎軟件社區
相關推薦

2011-05-11 17:48:31

CocoaiOS

2023-11-10 16:28:02

TCP窗口

2009-11-26 14:23:11

Silverlight

2010-08-11 14:41:08

Flex窗口

2023-02-19 15:33:51

WindowsC++窗口程序

2013-11-14 17:02:41

Android多窗口

2025-05-19 00:02:45

SQL窗口函數

2010-05-18 13:27:44

IIS管理

2009-12-24 14:38:52

WPF全屏幕窗口

2011-06-08 15:14:46

Qt 教程

2013-01-07 13:15:39

Android開發窗口背景視圖

2010-05-18 13:33:45

IIS管理

2022-11-23 14:47:29

北向開發鴻蒙

2020-04-07 15:25:22

Fluxbox窗口管理器Linux

2021-05-17 10:39:14

KDE文件管理器客戶端

2023-12-10 14:43:30

PythonGUIeel

2009-11-11 10:56:15

調用Visual St

2023-12-11 07:41:30

PyQt6Python用對象樹管理窗口

2011-09-02 17:38:33

UbuntuEmerald

2024-08-29 08:00:00

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲成人一区 | 亚洲一区二区三区在线免费观看 | 免费国产一区二区 | 色在线看| 国产美女视频 | 欧美福利视频一区 | 国产夜恋视频在线观看 | 午夜精品导航 | 国产精品视频在线免费观看 | 日韩电影一区 | 中文精品视频 | 青青艹在线视频 | 欧美日韩国产中文 | 国产污视频在线 | 成年人在线视频 | 不卡的av电影 | 高清国产一区二区 | 伊人春色成人网 | 91精品国产手机 | 国产欧美精品一区二区三区 | 视频二区 | 亚洲精品在线看 | 久久不卡区 | 在线观看电影av | 免费成人高清在线视频 | av天空| 久久久激情 | 亚洲第一天堂 | 特级特黄特色的免费大片 | 亚州精品天堂中文字幕 | 日韩欧美一级精品久久 | 午夜久久久 | 欧美在线视频不卡 | 欧美日韩亚洲国产 | 一区二区三区四区av | 中文字幕在线一区二区三区 | 999re5这里只有精品 | 81精品国产乱码久久久久久 | 成人免费久久 | 国外成人在线视频网站 | 九九免费 |