ArkUI使用总结

ArkUI采用的声明式UI,写法类似 flutter 语法,思想和属性同 Flutter 基本一致;

常用组件

单位统一配置

在鸿蒙应用中,没有web中的 px 单位;鸿蒙采用 vp(屏幕密度单位)即所有尺寸后面追加 vp,如想撑满整个屏幕容器可以用 “100%” 字符串表示;

为了统一调整这些尺寸,官方建议使用 Resource 数据类型统一配置,定义一个 xxx.ets 文件

export default class CommonConstants {
    static readonly FULL_LENGTH: string = '100%'
}

使用

import {CommonConstants} from "./xxx"
Image("http://...").width(CommonConstants.FULL_LENGTH)

Text 文本组件

属性

属性注释
fonstSize(number)字体大小,单位 vp
fontWeight(FontWeight.Bold)字体加粗
fontColor(“十六进制”)字体颜色
opacity(number)透明度0-1
decoration({type:TextDecorationType.LineThrough})下划线

示例

Text("鸿蒙todoList")
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .padding(10)
        .opacity(0.6)
        .decoration({type:TextDecorationType.LineThrough})

Image 图片组件

语法规范 Image(src:string | PixelMap | Resource)

  1. 使用网络图片需要添加授权,在 module.json5 配置
"requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
]
  1. 使用 Resource 中需要将图片放到 AppScope / resources / base / media 的文件夹下
Image($r("app.media.xxx.png"))

Video组件

语法规范 Image(src:string | PixelMap | Resource) 和 Image 元素一致,但可以自定义播放器的控制器

属性

属性注释
previewUri:stringTS等格式
objectFit(ImageFit.Cintain)属性保持比例

TextInput 输入框组件

语法 textInput({options})

options

属性注释
placeholder文本提示

属性

属性注释
maxLength(number)最大字符长度
type(InputType.Number)设置文本类型
onChange((value:string)=>{})change事件监听

Button 按钮组件

语法 Button("文本",{options})

options

属性注释
types:ButtonType.Capsule设置按钮样式 Capsule 圆角 | Circle 圆形 | Normal 直角

容器组件

Row Column 行列容器

和 Flutter 一致,都采用了 flex 思想,属性也和 flex 保持一致

语法格式

Row({space:string | number}) /*space 表示主轴方向的间距*/

属性

属性注释
justifyConten主轴方向
dlignItems交叉轴方向

List 列表容器

滚动类容器,**必须包含子组件 ListItem ** 思想同 flutter 一致

语法

list(options){ ListItem(){}, ListItem(){} , ... }

options : Object

属性注释
space:number设置间距
initialIndex:number加载的起始位置
scroller:Scroller控制 list 组件的滚动

属性

属性注释
ListDireCtion()设置 list 组件的排列方向
divider()设置分割线

divider 分割线

属性注释
strokeWidth:number线宽
color:string颜色
startMargin:number线与侧边起始端距离
endMargin:number线与侧边结束端距离

Grid 网格容器

思想同 flutter 一致 必须包含子组件 GridItem

语法

Grid(scrder?:Scroller)

属性

属性方法
columnsTemplate()列的数量 “1fr 1fr 1fr”
rowsTemplate()行的数量 (不设置行数会出现滑动效果)
columnsGap()列间距
rowsGap()行间距

Tab页签组件

需要子组件 TabContent 一同使用

语法

Tab(options){}

options:Object

属性注释
barPosition: BarPosition.Start | End设置 tabs 的位置,与 vertical 属性强关联
index:number设置初始值
controller设置 tab 控制器, 用于控制 tabs 组件页签切换

属性

属性注释
vertical()设置 Tabs 方向是否为纵向,默认是 false
barMode()Tabbar 布局模式 Fixed 平均分,Scrllable 实际宽度
barWidth()tabbar的宽度
barHeight()tabbar的高度

自定义TabBar示例

/*引入两个页面*/
import {Index} from "./Index"
import {ListPage} from "./listPage"

@Entry
@Component
struct TabsPage {
  /*tabbar的选中索引下标*/
  @State currentIndex:number = 0;
  /*创建 tabbas 控制器*/
  private tabsController:TabsController = new TabsController();
  /*构建按钮模版组件*/
  @Builder MyTabBar(name:string,index:number,selectedImg: string, normalImg: string){
    /*上图标下文字布局*/  
    Column(){
      /*判断当前选中下标是否为当前菜单数,三目运算切换按钮颜色*/  
      Image(this.currentIndex === index?selectedImg:normalImg).width(30)
      Text(name)
        .fontColor(this.currentIndex === index?'#d81e06' : '#6B6B6B')
    }
    .width('100%')
    .height(50)
    .justifyContent(FlexAlign.Center)
    .onClick(()=>{
      /*将当前点击按钮状态同步到选中索引中,并通知 tabsController 控制器切换页面*/
      this.currentIndex = index;
      this.tabsController.changeIndex(index)
    })
  }

  build() {
    Column(){
      /*使用Tabs组件*/  
      Tabs({barPosition:BarPosition.End,controller:this.tabsController}){
        TabContent(){
          /*当前tabbar要显示的页签内容*/  
          Index()
        }.tabBar(this.MyTabBar("首页",0,"https://z1.ax1x.com/2023/11/29/piD6doV.png","https://z1.ax1x.com/2023/11/29/piD6tLn.png"))

        TabContent(){
          ListPage()
        }.tabBar(this.MyTabBar("我的",1,"https://z1.ax1x.com/2023/11/29/piD6doV.png","https://z1.ax1x.com/2023/11/29/piD6tLn.png"))

      }
      .barWidth('100%')
      .barHeight(50)
      .onChange((index:number)=>{
        /*左右滑动可以切换页签*/
        this.currentIndex = index
      })
    }
  }
}

弹窗类

警告弹窗

AlertDialog.show({
          title: '删除联系人', // 标题
          message: '是否需要删除所选联系人?', // 内容
          autoCancel: false, // 点击遮障层时,是否关闭弹窗。
          alignment: DialogAlignment.Center, // 弹窗在竖直方向的对齐方式
          primaryButton: {
            value: '取消',
            action: () => {
              console.info('取消');
            }
          },
          secondaryButton: {
            value: '删除',
            fontColor: '#D94838',
            action: () => {
              console.info('删除');
            }
          },
          cancel: () => { // 点击遮障层关闭dialog时的回调
            console.info('点击遮罩层');
          }
})

日期选择器

DatePickerDialog.show({
            start: new Date("1900-1-1"), // 设置选择器的起始日期
            end: new Date("2023-12-31"), // 设置选择器的结束日期
            selected: this.selectedDate, // 设置当前选中的日期
            lunar: false,
            onAccept: (value: DatePickerResult) => { // 点击弹窗中的“确定”按钮时触发该回调
              // 通过Date的setFullYear方法设置按下确定按钮时的日期,这样当弹窗再次弹出时显示选中的是上一次确定的日期
              this.selectedDate.setFullYear(value.year, value.month, value.day)
              console.info("DatePickerDialog:onAccept()" + JSON.stringify(value))
            },
            onCancel: () => { // 点击弹窗中的“取消”按钮时触发该回调
              console.info("DatePickerDialog:onCancel()")
            },
            onChange: (value: DatePickerResult) => { // 滑动弹窗中的滑动选择器使当前选中项改变时触发该回调
              console.info("DatePickerDialog:onChange()" + JSON.stringify(value))
            }
})

文本选择器

private fruits: string[] = ['苹果', '橘子', '香蕉', '猕猴桃', '西瓜'];
TextPickerDialog.show({
            range: this.fruits, // 设置文本选择器的选择范围
            selected: this.select, // 设置初始选中项的索引值。
            onAccept: (value: TextPickerResult) => { // 点击弹窗中的“确定”按钮时触发该回调。
              // 设置select为按下确定按钮时候的选中项index,这样当弹窗再次弹出时显示选中的是上一次确定的选项
              this.select = value.index;
              console.info("TextPickerDialog:onAccept()" + JSON.stringify(value));
            },
            onCancel: () => { // 点击弹窗中的“取消”按钮时触发该回调。
              console.info("TextPickerDialog:onCancel()");
            },
            onChange: (value: TextPickerResult) => { // 滑动弹窗中的选择器使当前选中项改变时触发该回调。
              console.info("TextPickerDialog:onChange()" + JSON.stringify(value));
            }
 })

自定义选择器(简易版)

抛开官方花里胡哨的定义,创一个 dialog.ets文件,用于定义弹出层

@CustomDialog
export default struct CustomDialogWidget {
  /*选项数据元状态*/
  @State hobbyBeans:Array<{label:string,isChecked:boolean}> = [];
  /*自定义的数据*/
  @State listData:Array<{value:string}> = [{value:"苹果"},{value:'香蕉'}]
  /*自定义弹窗的控制器*/
  private controller: CustomDialogController;
 /*格式化一下自定义数据,将格式好的对象放到 hobbyBeans 数组中,后面直接循环 hobbyBeans 数组*/
  aboutToAppear(){
    this.listData.forEach((item)=>{
      this.hobbyBeans.push({
        label:item.value,
        isChecked:false
      })
    })
  }
  /*定义页面*/
  build(){
    Column(){
      List(){
        /*循环 hobbyBeans 数组得到按钮数据*/  
        ForEach(this.hobbyBeans,
          (item,index)=>{
            ListItem(){
              Row(){
                Text(item.label)
                Toggle({ type: ToggleType.Checkbox, isOn: false })
                  .onChange((isCheck) => {
                    item.isChecked = isCheck;
                  })
              }
              .width("100%")
              .justifyContent(FlexAlign.SpaceBetween)
            }
          },
          (item,index)=>`${index}`)
      }
      /*底部的控制按钮*/
      Row() {
        Button("取消")
        .onClick(() => {
          this.controller.close();
        })
        Button("确定")
        .onClick(() => {
          this.controller.close();
        })
      }
    }
    .justifyContent(FlexAlign.SpaceBetween)
    .padding(20)
    .backgroundColor("#fff")
    .height(180)
  }

}

在组件中使用

import CustomDialogWidget from "../component/dialog"
/*创建控制器*/
customDialogController: CustomDialogController = new CustomDialogController({
    builder:CustomDialogWidget(), /*在这里构建一下 CustomDialogWidget 组件*/
    alignment: DialogAlignment.Center, /*模态框的位置*/
    customStyle: true,
})

Button("自定义弹窗"){}.onClick(()=>{this.CustomDialogController.open()})

WebView

Web组件

格式 Web(options)

options {}

属性注释
src:string网址地址
Controller:webController控制器,前进后退

webController 实例

属性注释
controller.foreard()控制 webView 的页面路由前进
controller.backward()控制 webView 的页面路由后退
controller.refresh()刷新页面
controller.stop()停止
controller.clearHistory()清除历史
runJavaScript调用页面的 js 方法

属性

属性注释
.fileAccess(true)允许访问本地文件
.javaScriptAccess(true)可以调用 JS 脚本
.imageAccess(fasle)不允许加载图片
.zoomAccess(false)禁止页面缩放

事件

事件注释
onConfirm网页通信,可接收到页面传递的信息

示例

在本地创建 html 文件 entry/src/main/resources/rawfile

index.html

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<body>

    <h1 id="h1el"></h1>
    <button onclick="htmlTest()">调用Web组件里面的方法</button>
</body>
<script type="text/javascript">
    function htmlTest() {
        h1el.innerHTML = "测试内容";
    }
</script>
</html>

webView 使用

controller: WebController = new WebController();

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

接受web端的信息 onConfirm

示例

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<body>
    <button onclick="confirmFun()">confirm事件</button>
</body>
<script type="text/javascript">
    function confirmFun(){
        confirm("来自web端的信息")
    }
</script>
</html>
Web({ src: $rawfile('index.html'), controller: this.controller })
        .javaScriptAccess(true)
        .zoomAccess(false)
        .textZoomAtio(150)
        .onConfirm((event)=>{
          console.log(event.message) /*打印出web端的消息*/
          return true
        })

web组件调用网页js方法

Web({ src: $rawfile('index.html'), controller: this.controller })
.onPageEnd((event)=>{
    this.controller.runJavaScript({
        script:"test()",
        callback:(result:string)=>{
            console.log(result) /*打印js方法返回的内容*/
        }
    })
})
<script type="text/javascript">
    function test(){
        return "鸿蒙web组件调用js方法"
    }
</script>

JS 调用 Web 组件方法

鸿蒙

@Entry
@Component
export struct WebPage {
  @State dataFromHtml: string = ''
  controller: WebController = new WebController()
  /*定义供页面调用的方法逻辑*/
  testObj = {
    test: (data) => {
      this.dataFromHtml = data;
      return '方法被js端调用了';
    },
    toString: () => {
      console.log('Web Component toString');
    }
  }

  build(){
      Column(){
           Button('将脚本注入到js页面中').onClick(() => {
              this.controller.registerJavaScriptProxy({
                object: this.testObj,
                name: 'objName',
                methodList: ['test', 'toString'],
              });
              this.controller.refresh();
            })

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

}

页面中调用

<button @click="btnFun()">按钮</button>

function btnFun(){
    let result = objName.test("调用鸿蒙的方法,传递一个信息")
    console.log(result)
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇