Skip to content

Latest commit

 

History

History
448 lines (341 loc) · 16.5 KB

6.常用组件.md

File metadata and controls

448 lines (341 loc) · 16.5 KB

6.常用组件

在我们常用的应用中,经常会有视图内容切换的场景,来展示更加丰富的内容。比如经典的首页和我的页面,点击底部的页签的选项,可以实现“首页”和“我的”

Tabs组件仅可包含子组件TabContent,每一个页签对应一个内容视图即TabContent组件。下面的示例代码构建了一个简单的页签页面:

@Entry
@Component
struct TabsExample {
  private controller: TabsController = new TabsController()

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
        TabContent() {
          Column().width('100%').height('100%').backgroundColor(Color.Green)
        }
        .tabBar('green')

        TabContent() {
          Column().width('100%').height('100%').backgroundColor(Color.Blue)
        }
        .tabBar('blue')

        TabContent() {
          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
        }
        .tabBar('yellow')

        TabContent() {
          Column().width('100%').height('100%').backgroundColor(Color.Pink)
        }
        .tabBar('pink')
      }
      .barWidth('100%') // 设置TabBar宽度
      .barHeight(60) // 设置TabBar高度
      .width('100%') // 设置Tabs组件宽度
      .height('100%') // 设置Tabs组件高度
      .backgroundColor(0xF5F5F5) // 设置Tabs组件背景颜色
    }
    .width('100%')
    .height('100%')
  }
}
  • TabContent组件不支持设置通用宽度属性,其宽度默认撑满Tabs父组件。
  • TabContent组件不支持设置通用高度属性,其高度由Tabs父组件高度与TabBar组件高度决定。

因为Tabs的布局模式默认是Fixed的,所以Tabs的页签是不可滑动的。当页签比较多的时候,可能会导致页签显示不全,将布局模式设置为Scrollable的话,可以实现页签的滚动。

Tabs的布局模式有Fixed(默认)和Scrollable两种:

  • BarMode.Fixed:所有TabBar平均分配barWidth宽度(纵向时平均分配barHeight高度),页签不可滚动。

  • BarMode.Scrollable:每一个TabBar均使用实际布局宽度,超过总长度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。

Tabs组件页签默认显示在顶部,某些场景下您可能希望Tabs页签出现在底部或者侧边,您可以使用Tabs组件接口中的参数barPosition设置页签位置。此外页签显示位置还与vertical属性相关联,vertical属性用于设置页签的排列方向,当vertical的属性值为false(默认值)时页签横向排列,为true时页签纵向排列。

barPosition的值可以设置为BarPosition.Start(默认值)和BarPosition.End

自定义TabBar

image

上面的这种底部页签效果,需要用到自定义TabBar。

TabContent的tabBar属性除了支持string类型,还支持使用@Builder装饰器修饰的函数。您可以使用@Builder装饰器,构造一个生成自定义TabBar样式的函数,实现上面的底部页签效果,示例代码如下:

@Entry
@Component
struct TabsExample {
  @State currentIndex: number = 0;
  private tabsController: TabsController = new TabsController();

  @Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
    Column() {
      Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
        .size({ width: 25, height: 25 })
      Text(title)
        .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
    }
    .width('100%')
    .height(50)
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.currentIndex = targetIndex;
      this.tabsController.changeIndex(this.currentIndex);
    })
  }

  build() {
    Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
      TabContent() {
        Column().width('100%').height('100%').backgroundColor('#00CB87')
      }
      .tabBar(this.TabBuilder('首页', 0, $r('app.media.home_selected'), $r('app.media.home_normal')))

      TabContent() {
        Column().width('100%').height('100%').backgroundColor('#007DFF')
      }
      .tabBar(this.TabBuilder('我的', 1, $r('app.media.mine_selected'), $r('app.media.mine_normal')))
    }
    .barWidth('100%')
    .barHeight(50)
    .onChange((index: number) => {
      this.currentIndex = index;
    })
  }
}

示例代码中将barPosition的值设置为BarPosition.End,使页签显示在底部。使用@Builder修饰TabBuilder函数,生成由Image和Text组成的页签。同时也给Tabs组件设置了TabsController控制器,当点击某个页签时,调用changeIndex方法进行页签内容切换。

最后还需要给Tabs添加onChange事件,Tab页签切换后触发该事件,这样当我们左右滑动内容视图的时候,页签样式也会跟着改变。

Video(value: {src?: string | Resource, currentProgressRate?: number | string |PlaybackSpeed, previewUri?: string |PixelMap | Resource, controller?: VideoController})
  • src表示视频播放源的路径,可以支持本地视频路径和网络路径。使用网络地址时,如https,需要注意的是需要在module.json5文件中申请网络权限。
  • currentProgressRate表示视频播放倍速,其参数类型为number,取值支持0.75,1.0,1.25,1.75,2.0,默认值为1.0倍速;
  • previewUri表示视频未播放时的预览图片路径;
  • controller表示视频控制器。

视频支持的规格是:mp4、mkv、webm、TS。

objectFit 中视频显示模式包括Contain、Cover、Auto、Fill、ScaleDown、None 6种模式,默认情况下使用ImageFit.Cover(保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界),其他效果(如自适应显示、保持原有尺寸显示、不保持宽高比进行缩放等)可以根据具体使用场景/设备来进行选择。

Video组件回调事件介绍

Video组件能够支持常规的点击、触摸等通用事件,同时也支持onStart、onPause、onFinish、onError等事件,具体事件的功能描述见下表:

  • onStart(event:() => void) : 播放时触发该事件。

  • onPause(event:() => void) : 暂停时触发该事件。

  • onFinish(event:() => void) : 播放结束时触发该事件。

  • onError(event:() => void) : 播放失败时触发该事件。

  • onPrepared(callback:(event?: { duration: number }) => void)
    视频准备完成时触发该事件,通过duration可以获取视频时长,单位为s。

  • onSeeking(callback:(event?: { time: number }) => void)
    操作进度条过程时上报时间信息,单位为s。

  • onSeeked(callback:(event?: { time: number }) => void)
    操作进度条完成后,上报播放时间信息,单位为s。

  • onUpdate(callback:(event?: { time: number }) => void)
    播放进度变化时触发该事件,单位为s,更新时间间隔为250ms。

  • onFullscreenChange(callback:(event?: { fullscreen: boolean }) => void)
    在全屏播放与非全屏播放状态之间切换时触发该事件

Dialog

弹窗是一种模态窗口,通常用来展示用户当前需要的或用户必须关注的信息或操作。在弹出框消失之前,用户无法操作其他界面内容。ArkUI为我们提供了丰富的弹窗功能,弹窗按照功能可以分为以下两类:

  • 确认类:例如警告弹窗AlertDialog。
  • 选择类:包括文本选择弹窗TextPickerDialog 、日期滑动选择弹窗DatePickerDialog、时间滑动选择弹窗TimePickerDialog等。
Button('点击显示弹窗')
  .onClick(() => {
    AlertDialog.show(
      {
        title: '删除联系人', // 标题
        message: '是否需要删除所选联系人?', // 内容
        autoCancel: false, // 点击遮障层时,是否关闭弹窗。
        alignment: DialogAlignment.Bottom, // 弹窗在竖直方向的对齐方式
        offset: { dx: 0, dy: -20 }, // 弹窗相对alignment位置的偏移量
        primaryButton: {
          value: '取消',
          action: () => {
            console.info('Callback when the first button is clicked');
          }
        },
        secondaryButton: {
          value: '删除',
          fontColor: '#D94838',
          action: () => {
            console.info('Callback when the second button is clicked');
          }
        },
        cancel: () => { // 点击遮障层关闭dialog时的回调
          console.info('Closed callbacks');
        }
      }
    )
  })

此外,您还可以使用AlertDialog,构建只包含一个操作按钮的确认弹窗,使用confirm响应操作按钮回调。

AlertDialog.show(
  {
    title: '提示',
    message: '提示信息',
    autoCancel: true,
    alignment: DialogAlignment.Bottom,
    offset: { dx: 0, dy: -20 },
    confirm: {
      value: '确认',
      action: () => {
        console.info('Callback when confirm button is clicked');
      }
    },
    cancel: () => {
      console.info('Closed callbacks')
    }
  }
)

自定义弹窗

自定义弹窗的使用更加灵活,适用于更多的业务场景,在自定义弹窗中您可以自定义弹窗内容,构建更加丰富的弹窗界面。自定义弹窗的界面可以通过装饰器@CustomDialog定义的组件来实现,然后结合CustomDialogController来控制自定义弹窗的显示和隐藏。

Web组件

ArkUI为我们提供了Web组件来加载网页,借助它我们就相当于在自己的应用程序里嵌入一个浏览器,从而非常轻松地展示各种各样的网页。

Web组件的使用非常简单,只需要在Page目录下的ArkTS文件中创建一个Web组件,传入两个参数就可以了。其中

@Entry
@Component
struct WebComponent {
  controller: WebController = new WebController();
  build() {
    Column() {
      Web({ src: 'https://developer.harmonyos.com/', controller: this.controller })
    }
  }
}

访问在线网页时您需要在module.json5文件中申明网络访问权限:ohos.permission.INTERNET。

加载本地网页

前面实现了Web组件加载在线网页,Web组件同样也可以加载本地网页。首先在main/resources/rawfile目录下创建一个HTML文件,然后通过$rawfile引用本地网页资源,示例代码如下:

@Entry
@Component
struct SecondPage {
  controller: WebController = new WebController();

  build() {
    Column() {
      Web({ src: $rawfile('index.html'), controller: this.controller })
    }
  }
}

有的网页可能不能很好适配手机屏幕,需要对其缩放才能有更好的效果,开发者可以根据需要给Web组件设置zoomAccess属性,zoomAccess用于设置是否支持手势进行缩放,默认允许执行缩放。Web组件默认支持手势进行缩放。
您还可以使用zoom(factor: number)方法用于设置网站的缩放比例。其中factor表示缩放倍数。

文本缩放

如果需要对文本进行缩放,可以使用textZoomAtio(textZoomAtio: number)方法。其中textZoomAtio用于设置页面的文本缩放百分比,默认值为100,表示100%,使用textZoomAtio,文本会放大,但是图片不会随着文本一起放大。

Web组件事件

Web组件还提供了处理Javascript的对话框、网页加载进度及各种通知与请求事件的方法。例如onProgressChange可以监听网页的加载进度,onPageEnd在网页加载完成时触发该回调,且只在主frame触发,onConfirm则在网页触发confirm告警弹窗时触发回调。下面以onConfirm事件为例讲解Web组件事件的使用,更多Web组件事件可以查看事件。

如果您希望响应Web组件中网页的警告弹窗事件,您可以在onAlert或者onConfirm的回调方法中处理这些事件。以confirm弹窗为例,在网页触发onConfirm()告警弹窗时,显示一个AlertDialog弹窗。

@Entry
@Component
struct WebComponent {
  controller:WebController = new WebController();
  build() {
    Column() {
      Web({ src:$rawfile('index.html'), controller:this.controller })
        .onConfirm((event) => {
          AlertDialog.show({
            title: 'title',
            message: event.message,
            confirm: {
              value: 'onAlert',
              action: () => {
                event.result.handleConfirm();
              }
            },
            cancel: () => {
              event.result.handleCancel();
            }
          })
          return true;
        })
    }
  }
}

Web和JavaScript交互

在开发专为适配Web组件的网页时,您可以实现Web组件和JavaScript代码之间的交互。Web组件可以调用JavaScript方法,JavaScript也可以调用Web组件里面的方法。

如果您希望加载的网页在Web组件中运行JavaScript,则必须为您的Web组件启用JavaScript功能,默认情况下是允许JavaScript执行的。

Web({ src:'https://www.example.com', controller:this.controller })
    .javaScriptAccess(true)

Web组件调用JS方法 您可以在Web组件onPageEnd事件中添加runJavaScript方法。事件是网页加载完成时的回调,runJavaScript方法可以执行HTML中的JavaScript脚本。

// xxx.ets @Entry @Component struct WebComponent { controller: WebController = new WebController(); @State webResult: string = '' build() { Column() { Text(this.webResult).fontSize(20) Web({ src: $rawfile('index.html'), controller: this.controller }) .javaScriptAccess(true) .onPageEnd(e => { this.controller.runJavaScript({ script: 'test()', callback: (result: string)=> { this.webResult = result; }}); }) } } }

<script type="text/javascript"> function test() { return "This value is from index.html" } </script> 当页面加载完成时,触发onPageEnd事件,调用HTML文件中的test方法并将结果返回给Web组件。

JS调用Web组件方法 您可以使用registerJavaScriptProxy将Web组件中的JavaScript对象注入daowindow对象中,这样网页中的JS就可以直接调用该对象了。需要注意的是,要想registerJavaScriptProxy方法生效,须调用refresh方法。下面的示例将ets文件中的对象testObj注入到了window对象中。

// xxx.ets @Entry @Component struct WebComponent{ @State dataFromHtml: string = '' controller: WebController = new WebController() testObj = { test: (data) => { this.dataFromHtml = data; return 'ArkUI Web Component'; }, toString: () => { console.log('Web Component toString'); } }

build() { Column() { Text(this.dataFromHtml).fontSize(20) Row() { Button('Register JavaScript To Window').onClick(() => { this.controller.registerJavaScriptProxy({ object: this.testObj, name: 'objName', methodList: ['test', 'toString'], }); this.controller.refresh(); }) }

  Web({ src: $rawfile('index.html'), controller: this.controller })
    .javaScriptAccess(true)
}

} } 其中object表示参与注册的对象,name表示注册对象的名称为objName,与window中调用的对象名一致;methodList表示参与注册的应用侧JavaScript对象的方法,包含test、toString两个方法。在HTML中使用的时候直接使用objName调用methodList里面对应的方法即可,示例如下:

// index.html

调用Web组件里面的方法 <script type="text/javascript"> function htmlTest() { str = objName.test("param from Html"); } </script> 您还可以使用deleteJavaScriptRegister删除通过registerJavaScriptProxy注册到window上的指定name的应用侧JavaScript对象。

处理页面导航

当我们在使用浏览器浏览网页时,可以执行返回、前进、刷新等操作,Web组件同样支持这些操作。您可以使用backward()返回到上一个页面,使用forward()前进一个页面,您也可以使用refresh()刷新页面,使用clearHistory()来清除历史记录。