前言

上一篇文章我们实现选择图片选择文件拍照功能
链接这里大家有兴趣可以点击 《【鸿蒙应用ArkTS开发系列】- 选择图片、文件和拍照功能实现》

之前的效果
在这里插入图片描述
这一节我们要实现的效果
在这里插入图片描述

上一节 我们是在页面布局使用三个按钮来作为入口,但是有些场景,我们希望应用底部菜单弹窗的形式来与用户进行操作交互。那在鸿蒙原生应用中,一个自定义底部菜单列表弹窗应该怎么实现呢,这一节,我们来讲下这个基础知识

创建Demo工程

我们使用Empty Ability 模板创建一个Demo工程
在这里插入图片描述
在这里插入图片描述

创建dialog 文件夹

在这里插入图片描述

创建ListMenu 接口

src->main->ets ->dialog 文件夹下创建ListMenu.ets文件,完整代码如下

/**
 * 菜单
 */
export interface ListMenu {
  id: string;
  text: string | Resource;
  icon?: Resource;
  fontColor?: ResourceColor;
  onItemClick?: () => void;
}

这里我们对底部菜单列表的菜单选数据进行抽象抽取出通用字段

下面我们来看下自定义弹窗类的代码实现。

创建自定义弹窗 ListMenuDialog

src->main->ets ->dialog 文件夹下创建ListMenuDialog.ets文件,完整代码如下

/**
 * 自定义底部列表菜单弹窗
 */
import { ListMenu } from './ListMenu';

@CustomDialog
export struct ListMenuDialog {
  @Prop title: string = '';
  @State titleVisible: boolean = true;
  @State menuArray: ListMenu[] = [];
  controller: CustomDialogController;
  onCancel?: () => void;

  @Styles
  itemPressedStyle() {
    .backgroundColor('#e2e2e2')
  }

  @Styles
  itemNormalStyle() {
    .backgroundColor(Color.White)
  }

  build() {
    Column() {
      Text(this.title)
        .fontColor('#999999')
        .fontSize(14)
        .margin({ top: 10 })
        .maxLines(1)
        .visibility(this.titleVisible ? Visibility.Visible : Visibility.None)

      if (this.menuArray.length > 0) {

        Scroll() {
          Column() {
            ForEach(this.menuArray, (item: ListMenu, index: number) => {

              this.MenuItem(item, index)

            }, (index: number) => {
              return index.toString();
            })
          }
        }
        .backgroundColor(Color.White)
        .borderRadius(8)
        .margin({ top: 10 })
        .constraintSize({
          maxHeight: '40%'
        })
      }

      Text('取消')
        .width('100%')
        .height(50)
        .fontColor(Color.Black)
        .fontSize(16)
        .margin({ top: 15 })
        .backgroundColor(Color.White)
        .textAlign(TextAlign.Center)
        .borderRadius(8)
        .stateStyles({
          normal: this.itemNormalStyle,
          pressed: this.itemPressedStyle
        })
        .onClick(() => {
          if (this.controller) {
            this.controller.close();
          }
          if (this.onCancel) {
            this.onCancel();
          }
        })
    }
    .padding(10)
    .alignItems(HorizontalAlign.Center)
    .width('100%')
    .backgroundColor('#f8f8f8')
    .borderRadius({
      topLeft: 15,
      topRight: 15
    })

  }

  @Builder
  MenuItem(item: ListMenu, index: number) {
    Row() {

      Image(item.icon)
        .width(30)
        .height(30)
        .visibility(item.icon ? Visibility.Visible : Visibility.None)

      Text(item.text)
        .fontColor(item.fontColor ? item.fontColor : Color.Black)
        .fontSize(16)
        .textAlign(TextAlign.Center)
        .margin({ left: 5 })
    }
    .width('100%')
    .height(50)
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .borderStyle({ bottom: BorderStyle.Solid })
    .borderColor('#f8f8f8')
    .borderWidth({
      bottom: index === this.menuArray.length - 1 ? 0 : 1
    })
    .stateStyles({
      normal: this.itemNormalStyle,
      pressed: this.itemPressedStyle
    })
    .onClick(() => {
      if (this.controller) {
        this.controller.close();
      }
      if (item.onItemClick) {
        item.onItemClick();
      }
    })
  }
}


下面我们对这个定义弹窗代码进行一些讲解

  1. 首先我们定义一个ListMenuDialog 的结构体;
    export struct ListMenuDialog 。

  2. 使用@CustomDialog装饰
    我们使用@CustomDialog装饰这个ListMenuDialog 结构体,表明我们这个结构体是一个自定义对话框

  3. 定义定义弹窗控制器CustomDialogController
    通过定义CustomDialogController,在弹窗内部可以触发弹窗的打开关闭

  4. title
    弹窗标题这里定义为Prop, 可以与页面进行状态同步,对于有弹窗标题动态修改场景,可以使用到

  5. titleVisible
    控制标题是否显示,如果弹窗没有标题通过传递false进行设置标题不显示

  6. menuArray
    列表菜单数据源通过使用ForEach进行遍历调用 我们MenuItem子项 绘制列表UI。

  7. MenuItem
    这个是菜单项UI布局方法,我们使用@Builder装饰

  8. 分隔线
    通过给Item设置 border,绘制底部边框来实现分隔线的效果。

  9. 菜单按下点击
    通过设置 stateStyles,给Item配置两个@Style装饰样式itemNormalStyle 跟itemPressedStyle,来实现按下Item显示一个点击效果。

这样我们就完成了一个自定义底部菜单列表弹窗,下面我们在页面中来进行实际使用

使用自定义弹窗

我们在Index.ets添加如下代码

import { ListMenu } from '../dialog/ListMenu';
import { ListMenuDialog } from '../dialog/ListMenuDialog';

@Entry
@Component
struct Index {
  @State message: string = '点击弹窗';
  private customDialogController: CustomDialogController;

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(this.showBottomDialog.bind(this))
      }
      .width('100%')
    }
    .height('100%')
  }

  showBottomDialog() {
    const menuList: ListMenu[] = [
      {
        id: '1',
        text: '选择图片',
        fontColor: $r("app.color.blue_089ed9"),
        onItemClick: () => {
          console.log('点击了选择图片');
        }
      },
      {
        id: '2',
        text: '选择文件',
        fontColor: $r("app.color.blue_089ed9"),
        onItemClick: () => {
          console.log('点击了选择文件');
        }
      },
      {
        id: '3',
        text: '拍照',
        fontColor: $r("app.color.blue_089ed9"),
        onItemClick: () => {
          console.log('点击了拍照');
        }
      },
    ];

    this.customDialogController = new CustomDialogController({
      builder: ListMenuDialog(
        {
          title: '多媒体操作',
          menuArray: menuList,
          controller: this.customDialogController
        }),
      cancel: () => {
        console.log('点击了取消');
      },
      autoCancel: true,
      alignment: DialogAlignment.Bottom,
      customStyle: true
    });
    this.customDialogController.open();
  }

  hideBottomDialog() {
    this.customDialogController.close();
  }
}

我们定义了一个CustomDialogController 弹窗控制器这里我们对CustomDialogController的一些属性进行下讲解

我们通过构建一个弹窗控制器控制弹窗的显示关闭通过构建ListMenuDialog对象配置弹窗数据源显示样式,包括标题,标题是否显示,弹窗菜单的样式。 那接下来我们直接运行demo看下效果。

打包测试

打包安装真机上,需要我们给项目配置签名信息。我们点击File -> Project Structure ->Project ,选择 Signing Configs面板勾选 Support HarmonyOS 跟Automatically generate signature自动生成调试签名生成完毕后,运行安装到手机上

效果演示

默认效果

const menuList: ListMenu[] = [
      {
        id: '1',
        text: '选择图片',
        fontColor: $r("app.color.blue_089ed9")
      },

在这里插入图片描述

菜单带图标效果

const menuList: ListMenu[] = [
      {
        id: '1',
        text: '选择图片',
        icon: $r('app.media.ic_picture'),
        onItemClick: () => {
          console.log('点击了选择图片');
        }
      },
      {
        id: '2',
        text: '选择文件',
        icon: $r('app.media.ic_file'),
        onItemClick: () => {
          console.log('点击了选择文件');
        }
      }
 ]

在这里插入图片描述

设置文本颜色效果

在这里插入图片描述

const menuList: ListMenu[] = [
      {
        id: '1',
        text: '选择图片',
        fontColor: $r("app.color.blue_089ed9"),
        onItemClick: () => {
          console.log('点击了选择图片');
        }
      },
      {
        id: '2',
        text: '选择文件',
        fontColor: $r("app.color.blue_089ed9"),
        onItemClick: () => {
          console.log('点击了选择文件');
        }
      }
]

不同文本颜色效果

const menuList: ListMenu[] = [
      {
        id: '1',
        text: '选择图片',
        fontColor: $r("app.color.blue_089ed9"),
        onItemClick: () => {
          console.log('点击了选择图片');
        }
      },
      {
        id: '2',
        text: '选择文件',
        fontColor: $r("app.color.green_2f7e04"),
        onItemClick: () => {
          console.log('点击了选择文件');
        }
      }
]

在这里插入图片描述

无标题效果

 builder: ListMenuDialog(
        {
          menuArray: menuList,
          controller: this.customDialogController
        }),

在这里插入图片描述

大家也可以 在 ListMenu中增加一些其他的字段属性拓展弹窗样式比如图标的大小文本对齐方式等等。

那本章内容就到此结束,谢谢大家阅读! 有疑问的可以在评论留言交流

原文地址:https://blog.csdn.net/q919233914/article/details/134727458

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_46572.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注