自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

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

51CTO 開源基礎軟件社區(qū)

https://ost.51cto.com

場景介紹

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

效果呈現

本例最終效果如下:

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

環(huán)境要求

本例基于以下環(huán)境開發(fā),開發(fā)者也可以基于其他適配的版本進行開發(fā):

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

實現思路

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

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

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

開發(fā)步驟

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

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

showSubWindow() {
    // 創(chuàng)建應用子窗口。
    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));
      // 子窗口創(chuàng)建成功后,設置子窗口的位置
      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拖拽事件,拖拽事件發(fā)生時獲取到觸摸點的位置信息,使用@Watch監(jiān)聽到位置變量的變化,然后調用窗口的moveWindowTo方法將窗口移動到對應位置,從而實現拖拽效果。
具體代碼如下:

import window from '@ohos.window';

interface Position {
  x: number,
  y: number
}

@Entry
@Component
struct SubWindow{
  ...
  // 創(chuàng)建位置變量,并使用@Watch監(jiān)聽,變量發(fā)生變化調用moveWindow方法移動窗口
  @State @Watch("moveWindow") windowPosition: Position = { x: 0, y: 0 };
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
  private subWindow: window.Window
  // 通過懸浮窗名稱“hiSubWindow”獲取到創(chuàng)建的懸浮窗
  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');
        })
        // 發(fā)生拖拽時,獲取到觸摸點的位置,并將位置信息傳遞給windowPosition
        .onActionUpdate((event: GestureEvent) => {
          this.windowPosition.x += event.offsetX;
          this.windowPosition.y += event.offsetY;
        })
        .onActionEnd(() => {
          console.info('Pan end');
        })
    )
  }
}

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

  • 在創(chuàng)建窗口時觸發(fā)的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框架監(jiān)聽到,從而完成UI狀態(tài)刷新。
...
// 使用@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() {
    // 創(chuàng)建應用子窗口。
    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));
      // 子窗口創(chuàng)建成功后,設置子窗口的位置、大小及相關屬性等。
      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('創(chuàng)建子窗口')
          .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;
  // 創(chuàng)建位置變量,并使用@Watch監(jiān)聽,變量發(fā)生變化調用moveWindow方法移動窗口
  @State @Watch("moveWindow") windowPosition: Position = { x: 0, y: 0 };
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
  private subWindow: window.Window
  // 通過懸浮窗名稱“hiSubWindow”獲取到創(chuàng)建的懸浮窗
  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');
        })
        // 發(fā)生拖拽時,獲取到觸摸點的位置,并將位置信息傳遞給windowPosition
        .onActionUpdate((event: GestureEvent) => {
          this.windowPosition.x += event.offsetX;
          this.windowPosition.y += event.offsetY;
        })
        .onActionEnd(() => {
          console.info('Pan end');
        })
    )
  }
}

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

51CTO 開源基礎軟件社區(qū)

https://ost.51cto.com

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

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多窗口

2009-12-24 14:38:52

WPF全屏幕窗口

2010-05-18 13:27:44

IIS管理

2011-06-08 15:14:46

Qt 教程

2013-01-07 13:15:39

Android開發(fā)窗口背景視圖

2010-05-18 13:33:45

IIS管理

2021-05-17 10:39:14

KDE文件管理器客戶端

2022-11-23 14:47:29

北向開發(fā)鴻蒙

2020-04-07 15:25:22

Fluxbox窗口管理器Linux

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

2017-12-29 09:47:11

Web服務器萬維網
點贊
收藏

51CTO技術棧公眾號