当前位置:   article > 正文

鸿蒙开发(八)添加常用控件(下)_鸿蒙 站位控件

鸿蒙 站位控件

    添加控件的文章分成了上下两篇,上篇介绍了文本显示、文本输入、按钮、图片、单选框、切换按钮这六种常用控件,本篇继续介绍其他几种很重要但略微复杂的控件。

鸿蒙系列上一篇:

鸿蒙开发(七)添加常用控件(上)-CSDN博客文章浏览阅读673次,点赞19次,收藏15次。相信大家已经对鸿蒙开发的布局有了基本的了解。之前我们提到过,一个好的UI,离不开选择合理的布局。当然,也离不开适当的控件。本篇文章,带着大家一起学习下如何在页面里面添加常用的控件。由于控件较多,我会分为两篇文章来介绍。https://blog.csdn.net/qq_21154101/article/details/135747069?spm=1001.2014.3001.5501

目录

一、进度条(Progress)

1、线性样式

2、环形无刻度样式

3、环形有刻度样式

4、圆形样式

5、胶囊进度条 

二、自定义弹窗(CustomDialog)

1、创建自定义弹窗

2、展现弹窗和监听事件

三、视频(Video)

1、播放本地视频

2、播放沙箱视频 

3、播放网络视频

四、气泡(Popup)

1、系统气泡

2、自定义气泡 

(1)创建自定义气泡

(2)绑定自定义气泡

五、菜单(Menu)

1、默认菜单

2、自定义菜单

3、支持长按的菜单 


一、进度条(Progress)

    进度条是我们日常开发中经常使用的一种控件,用于显示某种操作的进度,给用户以友好的提示,Progress是进度条显示组件。使用如下方法创建:

Progress(options: {value: number, total?: number, type?: ProgressType})

    value为进度条的进度,total为进度的最大值,type为进度条的类型,支持如下几种类型:

ProgressType.Linear线型样式
ProgressType.Ring环形无刻度样式
ProgressType.ScaleRing环形有刻度样式
ProgressType.Eclipse圆形样式
ProgressType.Capsule胶囊样式

1、线性样式

    ProgressType.Linear创建线性样式进度条,线性样式的进度条默认水平展示,高度大于宽度的时候会自适应垂直显示:

  1. // 线性样式的进度条
  2. Progress({ value: 25, total: 100, type: ProgressType.Linear })
  3. .width('80%')

2、环形无刻度样式

    ProgressType.Ring创建环形无刻度样式进度条:

  1. // 环形无刻度进度条
  2. Progress({ value: 25, total: 100, type: ProgressType.Ring })

3、环形有刻度样式

    ProgressType.ScaleRing创建环形有刻度样式进度条,环形有刻度样式进度条需要设置style属性,否则跟环形无刻度进度条一样,看不出效果:

  1. // 环形有刻度进度条
  2. Progress({ value: 25, total: 100, type: ProgressType.ScaleRing })
  3. .style({ scaleCount: 20, scaleWidth: 3, strokeWidth: 10 }) // 20刻度,刻度宽度3,刻度长度10

4、圆形样式

    ProgressType.Eclipse创建圆形样式进度条:

  1. // 圆形进度条
  2. Progress({ value: 25, total: 100, type: ProgressType.Eclipse })

5、胶囊进度条 

    ProgressType.Capsule创建圆形样式进度条,需要设置宽高否则跟圆形样式一样,且宽>高时水平展示,高>宽时垂直展示:

  1. // 胶囊进度条
  2. Progress({ value: 25, total: 100, type: ProgressType.Capsule })
  3. .width(50)
  4. .height(100)

    实现一个demo,使用一个Button控制进度条的进度,如下完整代码:

  1. @Entry
  2. @Component
  3. struct AddWidget2 {
  4. @State progress: number = 5
  5. build() {
  6. Row() {
  7. Column() {
  8. // 线性样式的进度条
  9. Progress({ value: this.progress, total: 100, type: ProgressType.Linear })
  10. .width('80%')
  11. Row() {
  12. // 环形无刻度进度条
  13. Progress({ value: this.progress, total: 100, type: ProgressType.Ring })
  14. // 环形有刻度进度条
  15. Progress({ value: this.progress, total: 100, type: ProgressType.ScaleRing })
  16. .style({ scaleCount: 20, scaleWidth: 3, strokeWidth: 10 }) // 20刻度,刻度宽度3,刻度长度10
  17. .backgroundColor(Color.Gray) // 背景颜色灰色
  18. .color(Color.Black) // 进度颜色黑色
  19. // 圆形进度条
  20. Progress({ value: this.progress, total: 100, type: ProgressType.Eclipse })
  21. // 胶囊进度条
  22. Progress({ value: this.progress, total: 100, type: ProgressType.Capsule })
  23. .width(50)
  24. .height(100)
  25. }.width('100%').justifyContent(FlexAlign.SpaceEvenly)
  26. Button('进度+5')
  27. .onClick(() => {
  28. this.progress += 5
  29. if (this.progress > 100) {
  30. this.progress = 0
  31. }
  32. })
  33. }
  34. .width('100%')
  35. .margin({ top: 20 })
  36. }
  37. }
  38. }

     如下是上述代码的效果:

二、自定义弹窗(CustomDialog)

    自定义弹窗(CustomDialog)主要用来给用户提示或警告用的。比如删除文件的二次确认,比如即将跳转某个页面的提示等,也可以用于广告、抽奖、签到等场景。

    CustomDialog的使用与之前的控件有点区别。从名字也可以看出,既然是自定义弹窗,那么自然需要自定义一个控件,使用方式如下:

1、使用@CustomDialog装饰器装饰自定义弹窗

2、通过CustomDialogController类显示自定义弹窗

    接下来,通过实现一个小demo来看下CustomDialog如何创建,并且实现对弹窗内部事件的监听和分发。demo效果如下:

1、创建自定义弹窗

    在页面里面新建一个struct - MyDialog,创建自定义弹窗需要使用@CustomDialog注解修饰struct,如下所示:

  1. @CustomDialog
  2. struct MyDialog {
  3. controller: CustomDialogController
  4. cancel: () => void
  5. confirm: () => void
  6. build() {
  7. Column() {
  8. Text('确定要删除文件吗')
  9. .fontSize(20)
  10. .margin({ top: 20, bottom: 40 })
  11. Row() {
  12. Button('确认')
  13. .onClick(() => {
  14. this.controller.close()
  15. this.confirm()
  16. })
  17. Button('取消')
  18. .onClick(() => {
  19. this.controller.close()
  20. this.cancel()
  21. })
  22. }.width('75%').justifyContent(FlexAlign.SpaceAround).margin({ bottom: 20 })
  23. }
  24. }
  25. }

     简单解释下如上代码: 

1、CustomDialogController用来控制弹窗的展现和消失。

2、两个接口cancel和confirm,分别用来监听和分发"确认"和"取消"两个按钮的点击事件。

3、布局内容也很简单,上面一个Text,下面两个Button,整个窗体占据75%的屏幕宽度。

2、展现弹窗和监听事件

    接下来,在页面中通过点击一个按钮去展现上面自定义的弹窗,并且分别监听其确认和取消按钮的点击事件。代码如下:

  1. @Entry
  2. @Component
  3. struct AddWidget2 {
  4. @State progress: number = 5
  5. dialogController: CustomDialogController = new CustomDialogController({
  6. builder: MyDialog({
  7. cancel: this.onCancel,
  8. confirm: this.onConfirm
  9. }),
  10. alignment: DialogAlignment.Default
  11. })
  12. onCancel() {
  13. promptAction.showToast({ message: '点击了取消' })
  14. }
  15. onConfirm() {
  16. promptAction.showToast({ message: '点击了确认' })
  17. }
  18. build() {
  19. Row() {
  20. Column() {
  21. Button('弹窗')
  22. .onClick(() => {
  23. this.dialogController.open()
  24. }).margin({ top: 10 })
  25. }
  26. .width('100%')
  27. .margin({ top: 20 })
  28. }
  29. }

    最后,看下效果:

注:本篇的代码都在同一个页面AddWidget2里面写的,贴的上述代码我把上一节中进度条的代码给删掉了,但是最终的演示效果仍然是所有的代码,不要疑惑为什么我的页面上方多了那么多进度条。

三、视频(Video)

    视频的场景更为广泛,前几年短视频兴起后,抖音、快手等短视频app都用到了视频播放组件。Video组件的使用方式如下:

Video(value: {src?: string | Resource, currentProgressRate?: number | string | PlaybackSpeed, previewUri?: string | PixelMap | Resource, controller?: VideoController})

    其中,src指定视频播放源的路径,currentProgressRate用于设置视频播放倍速,previewUri指定视频的封面图路径,controller设置视频控制器,用于自定义控制视频。

1、播放本地视频

    加载本地视频时,首先在本地rawfile目录指定对应的文件,如下图所示:

    再使用资源访问符$rawfile()引用视频资源。

  1. @Component
  2. export struct VideoPlayer{
  3. private controller:VideoController;
  4. private previewUris: Resource = $r ('app.media.preview');
  5. private innerResource: Resource = $rawfile('test.mp4');
  6. build(){
  7. Column() {
  8. Video({
  9. src: this.innerResource,
  10. previewUri: this.previewUris,
  11. controller: this.controller
  12. })
  13. }
  14. }
  15. }

2、播放沙箱视频 

    支持file:///data/storage路径前缀的字符串,用于读取应用沙箱路径内的资源。需要保证应用沙箱目录路径下的文件存在并且有可读权限。

  1. @Component
  2. export struct VideoPlayer {
  3. private controller: VideoController;
  4. private videoSrc: string = 'file:///data/storage/el2/base/haps/entry/files/show.mp4'
  5. build() {
  6. Column() {
  7. Video({
  8. src: this.videoSrc,
  9. controller: this.controller
  10. })
  11. }
  12. }
  13. }

3、播放网络视频

    日常开发中最常用的应该还是播放网络视频。加载网络视频时,需要申请权限ohos.permission.INTERNET:

  1. @Component
  2. export struct VideoPlayer{
  3. private controller:VideoController;
  4. private previewUris: Resource = $r ('app.media.preview');
  5. private videoSrc: string= 'https://www.example.com/example.mp4'
  6. build(){
  7. Column() {
  8. Video({
  9. src: this.videoSrc,
  10. previewUri: this.previewUris,
  11. controller: this.controller
  12. })
  13. }
  14. }
  15. }

    通过加载以上三种路径的视频可以看出,调用的都是同样的方法,只不过videoSrc不同。接下来,通过如下代码加载一个本地视频:

  1. Video({
  2. previewUri: ($r('app.media.icon')),
  3. src: ($rawfile('test.mp4')),
  4. controller: this.controller
  5. })
  6. .autoPlay(true)
  7. .muted(true)
  8. .loop(true)
  9. .onStart(() => {
  10. promptAction.showToast({ message: '开始播放' })
  11. })
  12. .onPause(() => {
  13. promptAction.showToast({ message: '暂停播放' })
  14. })
  15. .onFinish(() => {
  16. promptAction.showToast({ message: '结束播放' })
  17. })
  18. .width('90%')
  19. .height('25%')
  20. .margin({ top: 20 })

     来看下效果(吐槽一下:鸿蒙的模拟器真的太卡了,为了录个屏模拟器重启和清数据了好几次,唉.....就这还打造屁的生态):

四、气泡(Popup)

    气泡是一个比较特殊的控件,因为它需要作为属性去绑定到其他的组件上,在组件上显示气泡弹窗提示。气泡分为两种类型,一种是系统气泡,一种是自定义气泡。

1、系统气泡

    PopupOptions为系统提供的气泡,可以通过配置primaryButton、secondaryButton来设置带按钮的气泡,跟用户做简单的交互。如下:

  1. @State bindPop: boolean = false
  2. // 气泡
  3. Text('测试气泡用的文本框')
  4. .onClick(() => {
  5. this.bindPop = !this.bindPop
  6. })
  7. .borderWidth(1)
  8. .padding(4)
  9. .margin({ top: 10 })
  10. .bindPopup(this.bindPop, { message: '这里是气泡',
  11. onStateChange: (event) => {
  12. if (event.isVisible) {
  13. promptAction.showToast({ message: '气泡可见' })
  14. } else {
  15. promptAction.showToast({ message: '气泡消失' })
  16. }
  17. },
  18. primaryButton: {
  19. value: '确定',
  20. action: () => {
  21. this.bindPop = false
  22. }
  23. },
  24. secondaryButton: {
  25. value: '取消',
  26. action: () => {
  27. this.bindPop = false
  28. }
  29. }})

 1、定义了一个@State变量bindPop,用来通过其变化即时刷新气泡显示与隐藏

2、增加了状态监听onStateChange,并且弹toast告诉我们是显示还是隐藏

3、增加了两个按钮,点击时控制气泡消失

    看下效果:

2、自定义气泡 

    可以使用构建器创建自定义气泡,@Builder中可以放自定义的内容。除此之外,还可以通过popupColor等参数控制气泡样式。

(1)创建自定义气泡

    使用@Builder注解创建自定义气泡,并且实现自定义的布局和控件,如下代码:

  1. @Builder
  2. popupBuilder() {
  3. Column() {
  4. Row() {
  5. Image($r("app.media.icon"))
  6. .width(24)
  7. .height(24)
  8. .margin({ left: 20 })
  9. Text('这是自定义气泡')
  10. .fontSize(15)
  11. .margin({ left: 20 })
  12. }.margin({ top: 20 })
  13. Column() {
  14. Button('按钮1')
  15. .margin({ top: 10 })
  16. .onClick(() => {
  17. promptAction.showToast({ message: '点击了按钮1' })
  18. })
  19. Button('按钮2')
  20. .margin({ top: 10 })
  21. .onClick(() => {
  22. promptAction.showToast({ message: '点击了按钮2' })
  23. })
  24. Button('按钮3')
  25. .margin({ top: 10 })
  26. .onClick(() => {
  27. promptAction.showToast({ message: '点击了按钮3' })
  28. })
  29. }.margin({ bottom: 20 })
  30. }.width('80%')
  31. }

(2)绑定自定义气泡

    绑定自定义气泡到控件上,实现同样跟上面系统气泡一样的显隐逻辑,代码如下:

  1. @State bindCustomPop: boolean = false
  2. // 自定义气泡
  3. Text('测试自定义气泡用的文本框')
  4. .onClick(() => {
  5. this.bindCustomPop = !this.bindCustomPop
  6. })
  7. .borderWidth(1)
  8. .padding(4)
  9. .margin({ top: 10 })
  10. .bindPopup(this.bindCustomPop, {
  11. builder: this.popupBuilder, // 气泡的内容
  12. placement: Placement.Bottom, // 气泡的弹出位置
  13. popupColor: Color.Gray, // 气泡的背景色
  14. onStateChange: (event) => {
  15. if (event.isVisible) {
  16. promptAction.showToast({ message: '气泡可见' })
  17. } else {
  18. promptAction.showToast({ message: '气泡消失' })
  19. }
  20. }
  21. })

    看下效果:

五、菜单(Menu)

1、默认菜单

    菜单需要调用bindMenu接口来实现,如下是使用系统默认菜单:

  1. // 默认菜单
  2. Text('测试菜单的文本框')
  3. .borderWidth(1)
  4. .padding(4)
  5. .margin({ top: 10 })
  6. .bindMenu([{ value: '菜单1'
  7. , action: () => {
  8. promptAction.showToast({ message: '菜单1' })
  9. } },
  10. { value: '菜单2'
  11. , action: () => {
  12. promptAction.showToast({ message: '菜单2' })
  13. } }])

2、自定义菜单

    如果系统默认的菜单样式满足不了我们的需求,可以使用@Builder自定义菜单,然后使用BindMenu(自定义Menu)的方式绑定,如下:

  1. // 自定义菜单
  2. Text('测试自定义菜单的文本框')
  3. .borderWidth(1)
  4. .padding(4)
  5. .margin({ top: 10 })
  6. .bindMenu(this.MyMenu())
  7. }
  8. /**
  9. * 自定义菜单
  10. */
  11. @Builder
  12. MyMenu() {
  13. Menu() {
  14. // 菜单选项1
  15. MenuItem({
  16. startIcon: $r("app.media.icon"),
  17. content: "菜单选项1" })
  18. .onChange(() => {
  19. promptAction.showToast({ message: "点了菜单选项1" })
  20. })
  21. // 包含两个菜单的菜单组
  22. MenuItemGroup({ header: '小标题' }) {
  23. MenuItem({ content: "菜单选项2" })
  24. .onChange((selected) => {
  25. promptAction.showToast({ message: "点了菜单选项2" })
  26. })
  27. MenuItem({ startIcon: $r("app.media.icon"), content: "菜单选项3" }).enabled(false)
  28. }
  29. }
  30. }

     分别看下以上两种菜单的效果:

3、支持长按的菜单 

    菜单默认是点击的方式弹出,比如我们上述使用bindMenu的方式。如果想长按触发呢?可以使用bindContextMenu设置菜单弹出的触发方式:右键或长按。我们把上述弹出自定义菜单的代码稍微修改下,如下:

  1. // 自定义菜单
  2. Text('测试自定义菜单的文本框')
  3. .borderWidth(1)
  4. .padding(4)
  5. .margin({ top: 10 })
  6. .bindContextMenu(this.MyMenu,ResponseType.LongPress)

    至此,本篇就介绍到这里了。这篇文章断断续续写了好几天,相比起上一篇添加基础控件,本篇的控件确实复杂了一些。用了两章的篇幅,我们把鸿蒙的基础系统控件都学习完了。下一篇,我们不妨一起来一次UI实战,把近期掌握的布局和控件一起在实战中检验下。

     最后,分享一款免费看热门电影和电视剧的app,仅限Android:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/985460
推荐阅读
相关标签
  

闽ICP备14008679号