如何生成一个可以交互的移动子窗口

如何生成一个可以交互的移动子窗口

HarmonyOS
2024-05-26 11:48:30
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
okmwq

本文主要介绍关于子窗口的生成以及属性设置,在我们日常手机应用过程中,手机APP根据需要会弹出一个子窗口在本APP界面上显示,或者在手机桌面上显示,类似视频聊天界面等。

使用的核心API

  • AppStorage
  • gesture
  • window

核心代码解释

1.showSubWindow(),通过createSubWindow创建子窗口,moveWindowTo和resize来确定窗口的大小和位置,最后通过setUIContent绑定子窗口目标页面。

2.destroySubWindow(),通过destroyWindow来消除子窗口。

3.AppStorage,提供数据存储能力,实现主窗口和子窗口的数据交互。

4.gesture,绑定手势操作。

EntryAbility.ts文件

 onWindowStageCreate(windowStage: window.WindowStage) { 
    // 将自定义数据变量“data”存入AppStorage 
    AppStorage.setOrCreate('data', 1); 
    AppStorage.setOrCreate('window', windowStage); 
  }

主窗口界面

//Index 
import window from '@ohos.window'; 
  
  
@Entry 
@Component 
struct Index { 
  // 使用@StorageLink将"mainData"与AppStorage中的变量"data"进行双向绑定 
  @StorageLink('data') mainData: number = 1; 
  @StorageLink('window') storWindow:window.WindowStage  | null = null 
  private windowStage = this.storWindow 
  private sub_windowClass :window.Window | null = null 
  
  showSubWindow() { 
    // 创建应用子窗口。 
    if (this.windowStage == null) { 
      console.error('Failed to create the subwindow. Cause: windowStage_ is null'); 
    } else { 
      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(500, 500, (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(800, 800, (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 as window.Window).showWindow((err) => { 
            let errCode: number = err.code; 
            if (errCode) { 
              console.error('Failed to show the window. Cause: ' + JSON.stringify(err)); 
              return; 
            } 
            console.info('Succeeded in showing the window.'); 
          }); 
          if(this.sub_windowClass == null){ 
            console.error('Failed to create the subwindow. Cause: windowStage_ is null'); 
          }else { 
            this.sub_windowClass.setWindowBackgroundColor('#E8A027') 
          } 
        }); 
      }) 
    } 
  } 
  
  destroySubWindow() { 
    if(this.sub_windowClass==null){ 
      console.error('Failed to create the subwindow. Cause: windowStage_ is null'); 
    }else{ 
      this.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.'); 
      }); 
    } 
  
  } 
  
  
  build() { 
    Row() { 
      Column() { 
        Text(`数据传输:${this.mainData}`) 
          .margin({bottom:30}) 
        Button('子窗口数据+1') 
          .backgroundColor('#ff8599cd') 
          .margin({bottom:30}) 
          .onClick(()=>{ 
            // 点击,storData的值加1 
            this.mainData += 1 
          }) 
        Button('创建子窗口') 
          .backgroundColor('#ff8599cd') 
          .onClick(()=>{ 
            // 点击弹出子窗口 
            this.showSubWindow() 
          }) 
          .margin({bottom:30}) 
        Button('消除子窗口') 
          .backgroundColor('#ff8599cd') 
          .onClick(()=>{ 
            // 点击消除子窗口 
            this.destroySubWindow() 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

子窗口界面

// SubWindow.ets 
import window from '@ohos.window'; 
  
interface Position { 
  x: number, 
  y: number 
} 
  
@Entry 
@Component 
struct SubWindow{ 
  @State offsetX: number = 0 
  @State offsetY: number = 0 
  // 使用@StorageLink将"subData"与AppStorage中的变量"data"进行双向绑定 
  @StorageLink('data') subData: number = 1; 
  // 创建位置变量,并使用@Watch监听,变量发生变化调用moveWindow方法移动窗口 
  @State @Watch("moveWindow") windowPosition: Position = { x: 500, y: 500 }; 
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All }); 
  private subWindow:window.Window | null = null 
  // 通过悬浮窗名称“hiSubWindow”获取到创建的悬浮窗 
  aboutToAppear() { 
    this.subWindow = window.findWindow("hiSubWindow") 
  } 
  // 将悬浮窗移动到指定位置 
  
  moveWindow() { 
    if(this.subWindow == null){ 
      console.info('Faild in destroying the window.'); 
    }else{ 
      this.subWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y); 
    } 
  } 
  build(){ 
    Column(){ 
      Text(`传输的数据:${this.subData}`) 
        .fontSize(12) 
        .margin({bottom:10}) 
      Button('主窗口数据+1') 
        .fontSize(12) 
        .backgroundColor('#ff8599cd') 
        .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'); 
        }) 
    ) 
  } 
}

实现效果

生成一个可移动交互的子窗口

适配的版本信息

SDK:4.0.10.15

IDE:DevEco Studio 4.0.1.601

分享
微博
QQ
微信
回复
2024-05-27 15:37:07
相关问题
Scroll中点击某一个层图片移动到顶端
362浏览 • 1回复 待解决
如何定义一个未知类型对象
283浏览 • 2回复 待解决
如何实现一个折叠组件
403浏览 • 1回复 待解决
如何创建一个worker线程
398浏览 • 1回复 待解决
如何封装一个通用commonEvent工具类
779浏览 • 1回复 待解决
鸿蒙 如何实现一个渐变圆形图片;
11073浏览 • 2回复 已解决