二、公共事件类属性
2.1.点击事件
组件被点击时触发的事件。
名称 | 支持冒泡 | 功能描述 |
---|---|---|
onClick(event: (event?: ClickEvent) => void) | 否 | 点击动作触发该方法调用 |
ClickEvent对象说明
属性名称 | 类型 | 描述 |
---|---|---|
screenX | number | 点击点相对于设备屏幕左边沿的X坐标。 |
screenY | number | 点击点相对于设备屏幕上边沿的Y坐标。 |
x | number | 点击点相对于被点击元素左边沿的X坐标。 |
y | number | 点击点相对于被点击元素上边沿的Y坐标。 |
target8+ | EventTarget | 被点击元素对象。 |
timestamp8+ | number | 事件时间戳。 |
source8+ | SourceType | 事件输入设备。 |
onClick:给组件添加点击事件的回调,设置回调后,当点击组件时会触发回调。回调参数 event
包含了点击信息,比如点击坐标等。
@Entry
@Component
struct OnclickExample {build() {Column(){Text("click text").width(120).height(40).backgroundColor("#00868B") //设置背景颜色.fontColor(Color.White) //设置字体颜色.onClick(()=>{ //设置点击事件回调console.log("click text...........") //输出日志}).textAlign(TextAlign.Center)}.width("100%").height("100%").padding(30)}
}
点击 Text
组件,控制台会打印 click text… 的日志。
2.2.触摸事件
onTouch:给组件设置触摸事件的回调,设置回调后,当手指在组件上按下、滑动、抬起时触发组件时会触发该回调。回调参数 event
包含了事件类型、点击坐标等信息。事件如下:
名称 | 是否冒泡 | 功能描述 |
---|---|---|
onTouch(event: (event?: TouchEvent) => void) | 是 | 触摸动作触发该方法调用 |
参数类型TouchEvent对象说明:
名称 | 类型 | 描述 |
---|---|---|
type | TouchType | 触摸事件的类型。 |
touches | Array | 全部手指信息。 |
changedTouches | Array | 当前发生变化的手指信息。 |
stopPropagation | () => void | 阻塞事件冒泡。 |
timestamp8+ | number | 事件时间戳。 |
target8+ | EventTarget | 触发手势事件的元素对象显示区域。 |
source8+ | SourceType | 事件输入设备。 |
预览效果如下:
@Entry
@Component
struct OntouchExample {build() {Column(){Text("click text").width(120).height(40).textAlign(TextAlign.Center).backgroundColor("#00868B") //设置背景颜色.fontColor(Color.White) //设置字体颜色.onTouch((event)=>{ //设置触摸事件回调if(event.type == TouchType.Down){ //手指按下的事件回调console.log("touch down");}else if(event.type == TouchType.Move){//手指移动的事件回调console.log("touch move");}else if(event.type == TouchType.Cancel){ //触摸事件取消时的事件回调console.log("touch cancel");}else if(event.type == TouchType.Up){ //手指抬起的事件回调console.log("touch up");}})}.width("100%").height("100%").padding(30)}
}
触摸该Text
组件,控制台输出如下:
12-25 10:16:30.427 I A0c0d0/JSApp: app Log: touch down
12-25 10:16:30.533 I A0c0d0/JSApp: app Log: touch up
12-25 10:16:32.270 I A0c0d0/JSApp: app Log: touch down
12-25 10:16:32.868 I A0c0d0/JSApp: app Log: touch move
使用触摸事件实现的通用下拉刷新和上拉加载更多的 RefreshLayout
组件,如下所示:
2.3.拖拽事件
拖拽事件指组件被长按后拖拽时触发的事件。给组件设置拖拽事件的回调,设置回调后,拖拽组件动作发生时会触发相应的拖拽回调,各拖拽方法说明如下:
- onDragStart:第一次拖拽此事件绑定的组件时,触发回调。参数
event
包含了拖拽坐标等信息,extraParams
拖拽事件的额外信息。拖拽事件注意事项:- 长按150毫秒(ms)可触发拖拽事件。
- 优先级:长按手势配置时间小于等于150毫秒时,长按手势优先触发,否则拖拽事件优先触发。
- onDragEnter:拖拽进入组件范围内时,触发回调。参数
event
包含了拖拽坐标等信息,extraParams
拖拽事件的额外信息。拖拽事件注意事项:- 当监听了
onDrop
事件时,此事件才有效。
- 当监听了
- onDragMove:拖拽在组件范围内移动时,触发回调。参数
event
包含了拖拽坐标等信息,extraParams
拖拽事件的额外信息。拖拽事件注意事项:- 当监听了
onDrop
事件时,此事件才有效。
- 当监听了
- onDragLeave:拖拽离开组件范围内时,触发回调。参数
event
包含了拖拽坐标等信息,extraParams
拖拽事件的额外信息。拖拽事件注意事项:- 当监听了
onDrop
事件时,此事件才有效。
- 当监听了
- onDrop:绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。参数
event
包含了拖拽坐标等信息,extraParams
拖拽事件的额外信息。
注意上面会用到枚举:Visibility
名称 | 描述 |
---|---|
Hidden | 隐藏,但参与布局进行占位。 |
Visible | 显示。 |
None | 隐藏,但不参与布局,不进行占位。 |
案例代码如下:
// xxx.ets
// 定义文本样式函数
@Extend(Text) function textStyle() {.width('25%') // 设置宽度为25%.height(35) // 设置高度为35.fontSize(16) // 设置字体大小为16.textAlign(TextAlign.Center) // 设置文本居中对齐.backgroundColor(0xAFEEEE) // 设置背景颜色为浅蓝色
}// 定义组件
@Entry
@Component
struct Index {// 定义状态变量@State numbers: string[] = ['1', '2', '3', '4', '5', '6'] // 定义字符串数组变量@State text: string = '' // 定义字符串变量@State bool: boolean = true // 定义布尔变量@State eventType: string = '' // 定义字符串变量/*** Visibility.Visible 隐藏,但参与布局进行占位。* 隐藏,但不参与布局,不进行占位。*/@State fruitVisible: Visibility[] = [Visibility.Visible, Visibility.Visible, Visibility.Visible] // 定义可见性枚举数组变量@State idx: number = 0 // 定义数字变量// 自定义拖拽过程中显示的内容@Builder pixelMapBuilder() {Column() {Text(this.text).width('50%') // 设置宽度为50%.height(60) // 设置高度为60.fontSize(16) // 设置字体大小为16.borderRadius(10) // 设置边框圆角半径为10.textAlign(TextAlign.Center) // 设置文本居中对齐.backgroundColor(Color.Yellow) // 设置背景颜色为黄色}}//自定义拖拽的文本框@Builder dragText(textContent:string, index:number){Text(textContent) // 在文本框中显示传入的文本内容.textStyle() // 使用自定义的文本样式.visibility(this.fruitVisible[index]) // 设置文本框的可见性为预先定义的数组中对应索引的值.onDragStart(() => { // 当开始拖拽时触发以下操作this.bool = true // 将布尔变量设置为truethis.text = textContent // 将文本内容赋值给this.textthis.fruitVisible[index] = Visibility.None // 将预先定义的数组中对应索引的值设置为不可见return this.pixelMapBuilder // 返回自定义拖拽过程中显示的内容}).onTouch((event: TouchEvent) => { // 当触摸事件发生时触发以下操作if (event.type === TouchType.Down) { // 如果触摸类型为按下this.eventType = 'Down' // 将事件类型设置为“Down”this.idx = index // 将当前索引赋值给this.idx}if (event.type === TouchType.Up) { // 如果触摸类型为抬起this.eventType = 'Up' // 将事件类型设置为“Up”if (this.bool) { // 如果布尔变量为truethis.fruitVisible[index] = Visibility.Visible // 将预先定义的数组中对应索引的值设置为可见}}})}// 构建组件build() {Column() {// 显示说明文本Text('准备三个拖拽的元素').fontSize(12) // 设置字体大小为12.fontColor(0xCCCCCC) // 设置字体颜色为灰色.width('90%') // 设置宽度为90%.textAlign(TextAlign.Start) // 设置文本左对齐.margin(5) // 设置外边距为5// 显示水果文本元素Row({ space: 15 }) {//调用组件产生文本框, 数组是上面元素是否可见的索引列表this.dragText("apple", 0)this.dragText("orange", 1)this.dragText("banana", 2)}.padding({ top: 10, bottom: 10 }).margin(10)// 显示列表元素Text('拖入后的元素列表').fontSize(12) // 设置字体大小为12.fontColor(0xCCCCCC) // 设置字体颜色为灰色.width('90%') // 设置宽度为90%.textAlign(TextAlign.Start) // 设置文本左对齐.margin(15) // 设置外边距为15List({ space: 20 }) {ForEach(this.numbers, (item) => {ListItem() {Text(item).width('100%') // 设置宽度为100%.height(80) // 设置高度为80.fontSize(16) // 设置字体大小为16.borderRadius(10) // 设置边框圆角半径为10.textAlign(TextAlign.Center) // 设置文本居中对齐.backgroundColor(0xAFEEEE) // 设置背景颜色为浅蓝色}}, item => item)}.editMode(true) // 设置编辑模式为true.height('50%') // 设置高度为50%.width('90%') // 设置宽度为90%.border({ width: 1 }) // 设置边框宽度为1.padding(15) // 设置内边距为15.divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 设置分隔线样式// 注册拖拽进入事件处理函数.onDragEnter((event: DragEvent, extraParams: string) => {console.log('List onDragEnter, ' + extraParams + 'X:' + event.getX() + 'Y:' + event.getY())})// 注册拖拽移动事件处理函数.onDragMove((event: DragEvent, extraParams: string) => {console.log('List onDragMove, ' + extraParams + 'X:' + event.getX() + 'Y:' + event.getY())})// 注册拖拽离开事件处理函数.onDragLeave((event: DragEvent, extraParams: string) => {console.log('List onDragLeave, ' + extraParams + 'X:' + event.getX() + 'Y:' + event.getY())})// 注册放置事件处理函数.onDrop((event: DragEvent, extraParams: string) => { // 当拖拽结束时触发以下操作,接受拖拽事件和额外参数let jsonString = JSON.parse(extraParams); // 将额外参数解析为JSON格式并赋值给jsonStringif (this.bool) { // 如果布尔变量为true// 通过splice方法插入元素this.numbers.splice(jsonString.insertIndex, 0, this.text) // 在numbers数组中的指定位置插入this.textthis.bool = false // 将布尔变量设置为false}this.fruitVisible[this.idx] = Visibility.None // 将预先定义的数组中对应索引的值设置为不可见})}.width('100%').height('100%').padding({ top: 20 }).margin({ top: 20 })}
}
预览效果如下:
2.4.挂载卸载事件
挂载卸载事件指组件从组件树上挂载、卸载时触发的事件。各 API 方法说明如下:
- onAppear:组件从组件树上挂载时的回调。
- onDisAppear:组件从组件树上卸载时的回到。
案例代码如下:
import promptAction from '@ohos.promptAction' // 导入名为promptAction的模块@Entry // 声明为入口组件
@Component // 声明为组件
struct AppearExample { // 定义名为AppearExample的结构体@State isShow: boolean = false // 声明一个名为isShow的状态变量,初始值为falsebuild() { // 定义一个名为build的方法Column() { // 创建一个Column组件Button(this.isShow?"卸载":"挂载") // 创建一个Button组件,并根据isShow的值显示不同的文本内容.onClick(() => { // 绑定点击事件处理函数this.isShow = !this.isShow // 切换isShow的值}).margin(15) // 设置按钮的外边距为15Column(){ // 创建一个嵌套的Column组件if(this.isShow){ // 如果isShow为trueText("挂载/卸载") // 创建一个Text组件,显示文本'挂载/卸载'.fontSize(22) // 设置字体大小为22.onAppear(()=>{ // 绑定onAppear事件处理函数console.log("------------------实现了挂载------------------") // 在控制台输出信息promptAction.showToast({ // 调用promptAction模块的showToast方法message: 'The text is shown', // 设置提示消息为'The text is shown'duration: 2000 // 设置提示持续时间为2000毫秒})}).onDisAppear(()=>{ // 绑定onDisAppear事件处理函数console.log("------------------实现了卸载------------------") // 在控制台输出信息promptAction.showToast({ // 调用promptAction模块的showToast方法message: 'The text is hidden', // 设置提示消息为'The text is hidden'duration: 2000 // 设置提示持续时间为2000毫秒})})}}}.padding(30).width('100%') // 设置Column组件的内边距为30,宽度为100%}
}
预览效果如下:
2.5.焦点事件
焦点事件指页面焦点在可获焦组件间移动时触发的事件,组件可使用焦点事件来处理相关逻辑。说明:
- 目前仅支持通过外接键盘的tab键、方向键触发。
- 存在默认交互逻辑的组件例如Button、TextInput等,默认即为可获焦,Text、Image等组件则默认状态为不可获焦,不可获焦状态下,无法触发焦点事件,需要设置focusable属性为true才可触发。
组件获取到焦点或者失去焦点时的事件回调,组件可使用焦点事件来更改内容。说明如下:
- onFocus:组件获取到焦点时的事件回调。
- onBlur:组件失去焦点时的事件回调。
案例代码如下:
@Entry
@Component
struct FocusEventExample {@State oneButtonColor: string = '#FFC0CB'@State twoButtonColor: string = '#87CEFA'@State threeButtonColor: string = '#90EE90'build() {Column({ space: 20 }) {// 通过外接键盘的上下键可以让焦点在三个按钮间移动,按钮获焦时颜色变化,失焦时变回原背景色Button("First Button").backgroundColor(this.oneButtonColor).width(260).height(80).fontColor(Color.Black).focusable(true)// 设置可获取焦点//当前组件获取焦点时触发的回调.onFocus(()=>{this.oneButtonColor = "#FF0000"})//当前组件失去焦点时触发的回调。.onBlur(()=>{this.oneButtonColor = "#FFC0CB"})Button("Second Button").backgroundColor(this.twoButtonColor).width(260).height(80).fontColor(Color.Black).focusable(true)// 设置可获取焦点//当前组件获取焦点时触发的回调.onFocus(()=>{this.twoButtonColor = "#00688B"})//当前组件失去焦点时触发的回调。.onBlur(()=>{this.twoButtonColor = "#90EE90"})Button("Third Button").backgroundColor(this.threeButtonColor).width(260).height(80).fontColor(Color.Black).focusable(true)// 设置可获取焦点//当前组件获取焦点时触发的回调.onFocus(()=>{this.threeButtonColor = "#9B30FF"})//当前组件失去焦点时触发的回调。.onBlur(()=>{this.threeButtonColor = "#AEEEEE"})}.width('100%').margin({ top: 20 })}
}
点击后,用外接键盘上下键移动,模拟获取和失去焦点后改变不同的背景颜色,预览效果如下:
2.6.区域变化事件
事件定义如下:
declare class CommonMethod<T> {// 区域变化的事件回调onAreaChange(event: (oldArea: Area, newArea: Area) => void): T;
}
//Area返回的数据类型说明
declare interface Area {width: Length; // 组件的宽度,单位为vp。height: Length; // 组件的高度,单位为vp。position: Position; // 组件左上角相对父组件左上角的位置。globalPosition: Position; // 组件左上角相对页面左上角的位置。
}
组件区域发生变化会触发该回调,比如组件尺寸或者在屏幕上的位置发生改变都会触发该回调。
- oldArea:组件变化前区域信息。
- newArea:组件变化后区域信息。
预览代码如下:
//定义一个全局样式
@Styles function btnGlobalPressedStyle(){ // 定义名为btnGlobalPressedStyle的全局样式函数.backgroundColor("#3CB371") // 设置背景颜色为"#3CB371".width(180) // 设置宽度为180.height(50) // 设置高度为50
}
//定义一个全局样式
@Styles function btnGlobalNormalStyle(){ // 定义名为btnGlobalNormalStyle的全局样式函数.backgroundColor("#CD5555") // 设置背景颜色为"#CD5555".width(180) // 设置宽度为180.height(50) // 设置高度为50
}@Entry // 声明为入口组件
@Component // 声明为组件
struct AreaExample { // 定义名为AreaExample的结构体@State text: string = ""; // 声明一个名为text的状态变量,初始值为空字符串@State area: string = ""; // 声明一个名为area的状态变量,初始值为空字符串build() { // 定义一个名为build的方法Column({space:20}){ // 创建一个Column组件,设置间距为20Button("Chang Area") // 创建一个Button组件,显示文本"Chang Area".stateStyles({ // 设置状态样式normal:btnGlobalPressedStyle, // 普通状态使用btnGlobalPressedStyle样式pressed:btnGlobalNormalStyle // 按下状态使用btnGlobalNormalStyle样式}).onClick((event: ClickEvent) => { // 绑定点击事件处理函数this.text += "Modifications"; // 在text变量后追加字符串"Modifications"})Text(this.text) // 创建一个Text组件,显示text变量的值.fontSize(18) // 设置字体大小为18//当该组件的大小或位置改变完成时,会触发该回调。//返回目标元素的宽高以及目标元素相对父元素和页面左上角的坐标位置。.onAreaChange((oldArea, newArea)=>{ // 绑定onAreaChange事件处理函数this.area = "old:\n" + JSON.stringify(oldArea) + "\n\n\nnew:\n" + JSON.stringify(newArea); // 设置area变量的值为旧区域和新区域的JSON字符串})Text(this.area).fontSize(18) // 创建一个Text组件,显示area变量的值,设置字体大小为18}.width("100%").height("100%").padding(10) // 设置Column组件的宽度、高度和内边距}
}
上面的代码点击一次,就会给拼接一段文本,这有文本元素大小就会改变,这时候就会触发onAreaChange的执行,预览效果如下:
三、公共剪切类属性
ArkUI框架提供的组件继承自 CommonMethod
,因此在 CommonMethod
中的定义的属性是组件的公共属性,用于对组件进行裁剪、遮罩处理。属性
名称 | 参数类型 | 默认值 | 描述 |
---|---|---|---|
clip | Circle | Ellipse | Path | Rect | boolean | false | 参数为相应类型的组件,按指定的形状对当前组件进行裁剪;参数为boolean类型时,设置是否按照边缘轮廓进行裁剪。 |
mask | Circle | Ellipse | Path | Rect | - | 在当前组件上加上指定形状的遮罩。 |
3.1.遮罩设置
mask:给当前组件添加指定形状的遮罩,遮罩的参考系为当前组件的左上角坐标,为了使遮罩显示还必须调用 fill()
方法添加遮罩颜色。参数说明如下:
- Circle:添加圆形遮罩,案例如下:
@Entry
@Component
struct CirleExample {build() {Column({space:20}){Image($r("app.media.Snip")) //默认加载图片.width(160).height(90)Image($r("app.media.Snip")) //居左剪切出来一个圆形.width(160).height(90)//Circle用于绘制圆形的组件:以90为直径, fill设置填充区域颜色。.mask(new Circle({width:90, height:90}).fill(Color.Pink))Image($r("app.media.Snip")) //居中裁剪出图片.width(160).height(90)//Circle用于绘制圆形的组件,如果宽和高不一致,则按照较小值为:直径.mask(new Circle({width:160, height:90}).fill(Color.Pink))Image($r("app.media.Snip")) //居右裁剪出图片.width(160).height(90)//以90为直径.mask(new Circle({width:230, height:90}).fill(Color.Pink))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
- Ellipse:添加椭圆形遮罩,样例如下:
@Entry
@Component
struct EllipseExample {build() {Column({space:20}){Image($r("app.media.Snip")) //默认加载图片.width(160).height(90)Image($r("app.media.Snip")) //居左剪切出来一个圆形.width(160).height(90)//Ellipse用于绘制椭圆的组件:如果宽和高一致,则为圆形, fill设置填充区域颜色。.mask(new Ellipse({width:90, height:90}).fill(Color.Pink))Image($r("app.media.Snip")) //居中裁剪出图片.width(160).height(90)//Ellipse用于绘制椭圆的组件,.mask(new Ellipse({width:160, height:90}).fill(Color.Pink))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
- Path:在指定路径上添加遮罩,
Path
使用commands
才生效果,
路径绘制的命令字符串,单位为px。commands支持的绘制命令如下:
commands支持的绘制命令如下:
命令 | 名称 | 参数 | 说明 |
---|---|---|---|
M | moveto | (x y) | 在给定的 (x, y) 坐标处开始一个新的子路径。例如,M 0 0 表示将(0, 0)点作为新子路径的起始点。 |
L | lineto | (x y) | 从当前点到给定的 (x, y) 坐标画一条线,该坐标成为新的当前点。例如,L 50 50 表示绘制当前点到(50, 50)点的直线,并将(50, 50)点作为新子路径的起始点。 |
H | horizontal lineto | x | 从当前点绘制一条水平线,等效于将y坐标指定为0的L命令。例如,H 50 表示绘制当前点到(50, 0)点的直线,并将(50, 0)点作为新子路径的起始点。 |
V | vertical lineto | y | 从当前点绘制一条垂直线,等效于将x坐标指定为0的L命令。例如,V 50 表示绘制当前点到(0, 50)点的直线,并将(0, 50)点作为新子路径的起始点。 |
C | curveto | (x1 y1 x2 y2 x y) | 使用 (x1, y1) 作为曲线起点的控制点, (x2, y2) 作为曲线终点的控制点,从当前点到 (x, y) 绘制三次贝塞尔曲线。例如,C100 100 250 100 250 200 表示绘制当前点到(250, 200)点的三次贝塞尔曲线,并将(250, 200)点作为新子路径的起始点。 |
S | smooth curveto | (x2 y2 x y) | (x2, y2) 作为曲线终点的控制点,绘制从当前点到 (x, y) 绘制三次贝塞尔曲线。若前一个命令是C或S,则起点控制点是上一个命令的终点控制点相对于起点的映射。 例如,C100 100 250 100 250 200 S400 300 400 200第二段贝塞尔曲线的起点控制点为(250, 300)。如果没有前一个命令或者前一个命令不是 C或S,则第一个控制点与当前点重合。 |
Q | quadratic Belzier curve | (x1 y1 x y) | 使用 (x1, y1) 作为控制点,从当前点到 (x, y) 绘制二次贝塞尔曲线。例如,Q400 50 600 300 表示绘制当前点到(600, 300)点的二次贝塞尔曲线,并将(600, 300)点作为新子路径的起始点。 |
T | smooth quadratic Belzier curveto | (x y) | 绘制从当前点到 (x, y) 绘制二次贝塞尔曲线。若前一个命令是Q或T,则控制点是上一个命令的终点控制点相对于起点的映射。 例如,Q400 50 600 300 T1000 300第二段贝塞尔曲线的控制点为(800, 350)。 如果没有前一个命令或者前一个命令不是 Q或T,则第一个控制点与当前点重合。 |
A | elliptical Arc | (rx ry x-axis-rotation large-arc-flag sweep-flag x y) | 从当前点到 (x, y) 绘制一条椭圆弧。椭圆的大小和方向由两个半径 (rx, ry) 和x-axis-rotation定义,指示整个椭圆相对于当前坐标系如何旋转(以度为单位)。 large-arc-flag 和 sweep-flag确定弧的绘制方式。 |
Z | closepath | none | 通过将当前路径连接回当前子路径的初始点来关闭当前子路径。 |
例如: commands(‘M0 20 L50 50 L50 100 Z’)定义了一个三角形,起始于位置(0,20),接着绘制点(0,20)到点(50,50)的直线,再绘制点(50,50)到点(50,100)的直线,最后绘制点(50,100)到(0,20)的直线关闭路径,形成封闭三角形。
@Entry
@Component
struct PathExample {build() {Column({space:20}){Image($r("app.media.Snip")) //默认加载图片.width(160).height(90)Image($r("app.media.Snip")) //裁剪出一个矩形.width(160).height(90)//commands路径绘制的命令字符串,单位为px, fill设置填充区域颜色。.mask(new Path({commands:"M0 0 L200 0 L200 300 L0 300 Z"}).fill(Color.Pink))Image($r("app.media.Snip")).width(160).height(90)//不使用commands不起作用,.mask(new Path({width:160, height:90}).fill(Color.Pink))Image($r("app.media.Snip")) //裁剪出一个三角形.width(160).height(90)//commands路径绘制的命令字符串,单位为px, fill设置填充区域颜色。.mask(new Path({commands:"M0 0 L200 300 L0 300 Z"}).fill(Color.Pink))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
Rect:添加矩形遮罩,样例如下:
@Entry
@Component
struct RectExample {build() {Column({space:20}){Image($r("app.media.Snip")) //默认加载图片.width(160).height(90)Image($r("app.media.Snip")) //全部遮罩.width(160).height(90)//Rect绘制矩形, fill设置填充区域颜色。.mask(new Rect({width:160,height:90}).fill(Color.Pink))Image($r("app.media.Snip")).width(160).height(90)//部分遮罩.mask(new Rect({width:90, height:90}).fill(Color.Pink))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
3.2.剪切设置
clip是按照指定形状对当前组件进行剪切,剪切的参考系为当前组件的左上角坐标,参数如下:
- boolean:表示是否按照边缘轮廓进行裁剪,案例如下:
@Entry
@Component
struct ClipExample01 {build() {Column({space:20}){Image($r("app.media.Snip")).width(160).height(90).borderRadius(10) //设置圆角Column(){Image($r("app.media.Snip")).width(160).height(90)}.borderRadius(10) //设置圆角。对子组件无效Column(){}.width(160).height(90).backgroundColor("#3CB371").borderRadius(10) //设置圆角。对子组件无效Column(){Image($r("app.media.Snip")).width(160).height(90)}.clip(true) //设置允许剪切,对所有子组件起作用.backgroundColor("#3CB371").borderRadius(10) //设置圆角。对子组件无效}.width("100%").height("100%").padding(20)}
}
预览效果如下:
ArkUI允许子组件超出父组件的绘制范围,如果不希望超出可以使用该属性做下限制,样例如下所示:
@Entry
@Component
struct ClipExample02 {build() {Row({space:10}){//没有设置clip属性,默认允许子组件超出父组件的绘制范围Column(){Text().size({width:20, height:80}).backgroundColor("#FFA07A")}.height("100%").layoutWeight(1).backgroundColor("#3CB371")Column(){Text().size({width:20, height:80}).backgroundColor("#FFA07A")}.height("100%").layoutWeight(1).backgroundColor("#3CB371").clip(true)//添加clip属性为 true,表示子组件的绘制范围不能超出父组件}.width("100%").height(60)}
}
第 1 个 Column 没有添加 clip 属性,则子组件的绘制区域可以超出父组件,第 2 个 Column 添加了 clip 并且属性值设置为true,则子组件超出父组件区域时被剪切到了。预览效果如下:
- Circle:把组件剪切成圆形,如下所示:
@Entry
@Component
struct ClipExample03 {build() {Column({space:20}){Image($r("app.media.Snip")) // 默认图片.width(160).height(90)Image($r("app.media.Snip")) // 居左裁剪出一个圆.width(160).height(90)//宽高一致,则按照90为直径.clip(new Circle({width:90, height:90}).fill("#66CDAA"))Image($r("app.media.Snip")) // 居中裁剪出一个圆.width(160).height(90)//宽高不一致,则按照小的值为直径.clip(new Circle({width:160, height:90}).fill("#66CDAA"))Image($r("app.media.Snip")) // 居右裁剪出一个圆.width(160).height(90).clip(new Circle({width:230, height:90}).fill("#66CDAA"))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
- Ellipse:把组件剪切成椭圆形,如下:
@Entry
@Component
struct ClipExample04 {build() {Column({space:20}){Image($r("app.media.Snip")) // 默认图片.width(160).height(90)Image($r("app.media.Snip")) // 裁剪出一个椭圆.width(160).height(90).clip(new Ellipse({width:160, height:90}).fill("#66CDAA"))Image($r("app.media.Snip")) // 裁剪出一个椭圆.width(160).height(90)//Ellipse裁剪出椭圆.clip(new Ellipse({width:130, height:90}).fill("#66CDAA"))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
- Path:把组件按照
Path
剪切出对应形状,Path
使用commands
才生效果,如下:
@Entry
@Component
struct ClipExample05 {build() {Column({space:20}){Image($r("app.media.Snip")) // 默认图片.width(160).height(90)Image($r("app.media.Snip")) // 使用commands参数起作用,绘制出图形.width(160).height(90).clip(new Path({commands:"M0 0 L150 0 L300 150 L0 300 Z"}).fill("#66CDAA"))Image($r("app.media.Snip")) //直接设置宽和高不起作用.width(160).height(90).clip(new Path({width:130, height:90}).fill("#66CDAA"))Image($r("app.media.Snip")) //使用commands参数起作用,绘制出图形.width(160).height(90)//vp2px(80)将vp(屏幕密度)单位的数值转换为以px(屏幕物理像素单位。)为单位的数值。.clip(new Path({width:130, height:90, commands:"M0 0 L" + vp2px(80) + " 0 L" + vp2px(80) + " " + vp2px(45) + " L0 " + vp2px(45) + " Z"}).fill("#66CDAA"))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
- Rect:把组件按照指定区域剪切出对应形状,如下:
@Entry
@Component
struct ClipExample06 {build() {Column({space:20}){Image($r("app.media.Snip")) // 默认图片.width(160).height(90)Image($r("app.media.Snip")).width(160).height(90).clip(new Rect({width:100, height:100}).fill("#66CDAA"))Image($r("app.media.Snip")).width(160).height(90).clip(new Rect({width:90, height:45}).fill("#66CDAA"))}.width("100%").height("100%").padding({top:20, bottom:20})}
}
预览效果如下:
四、公共提示类属性
为组件绑定弹出式菜单,弹出式菜单以垂直列表形式显示菜单项,可通过长按、点击或鼠标右键触发。
说明
- CustomBuilder里不支持再使用bindMenu、bindContextMenu弹出菜单。多级菜单可使用Menu组件。
- 弹出菜单的文本内容不支持长按选中。
属性
名称 | 参数类型 | 描述 |
---|---|---|
bindMenu | Array | CustomBuilder | 给组件绑定菜单,点击后弹出菜单。弹出菜单项支持文本和自定义两种功能。 |
bindContextMenu8+ | content: CustomBuilder,responseType: ResponseType | 给组件绑定菜单,触发方式为长按或者右键点击,弹出菜单项需要自定义。 |
MenuItem
名称 | 类型 | 描述 |
---|---|---|
value | string | 菜单项文本。 |
action | () => void | 点击菜单项的事件回调。 |
4.1:bindMenu
bindMenu
表示给当前组件绑定一个菜单项,用户点击组件后弹出菜单, bindMenu
如下:
- 单项文本实现:当
content
类型为{ value: string; action: () => void }
时,value
表示要显示的菜单文本,action
表示点击该文本的事件回调,如下所示:
import prompt from '@system.prompt';@Entry
@Component
struct BindMenuExample01 {build() {Column({space:20}){Button("bindMenu").width(120).height(50).onClick(()=>{prompt.showToast({message:"bindMenu"})}).bindMenu([{value:"菜单1",action:()=>{//显示文本提示框prompt.showToast({message:"菜单1"})}},{value:"菜单2",action:()=>{//显示文本提示框prompt.showToast({message:"菜单2"})}},{value:"菜单3",action:()=>{//显示文本提示框prompt.showToast({message:"菜单3"})}}])}.width("100%").height("100%").padding(20)}
}
预览效果如下:
上面使用单项文本实现一个菜单,文字太小并且样式和布局均无法修改,这种方式UI局限性太大,为了满足多样式场景需求,ArkUI框架提供了 CustomBuilder
方式允许开发者自定义 UI 描述。
- CustomBuilder方式实现:
CustomBuilder
在common.d.ts
文件中定义,源码定义如下:
CustomBuilder
可代表一个空类型也可以表示一个返回任意类型的函数,自定义 UI 描述使用 @Builder
装饰器装饰一个方法,该方法功能和语法规范和 build
函数相同,返回一个 UI 布局,语法格式如下:
@Builder function_name() { // @Builder修饰一个方法// UI布局Column() {}
}
用户自定义 UI 实现,就是使用 @Builder
修饰一个方法,该方法返回一个 UI 布局即可,案例如下:
import prompt from '@system.prompt'
@Entry
@Component
struct CustomBuilderExample {//自定义菜单组件@Builder ButtonMenuBuilder(){Column(){Text("菜单1").width("100%").height(50).fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).onClick(()=>{prompt.showToast({message:"菜单1"})})//提供分隔器组件,分隔不同内容块/内容元素。Divider().width("100%").height(1).backgroundColor(Color.White)Text("菜单2").width("100%").height(50).fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).onClick(()=>{prompt.showToast({message:"菜单2"})})//提供分隔器组件,分隔不同内容块/内容元素。Divider().width("100%").height(1).backgroundColor(Color.White)Text("菜单3").width("100%").height(50).fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).onClick(()=>{prompt.showToast({message:"菜单3"})})}.width(200).backgroundColor("#2E8B57")}build() {Column({space:10}){Button("bindMenu").width(120).height(50).onClick(() => {//同时设置onClickprompt.showToast({message:"hi Augus"})})//调用自定义的菜单组件.bindMenu(this.ButtonMenuBuilder)//绑定自定义菜单}.width("100%").height("100%").padding(20)}
}
预览效果如下:
4.2.bindContextMenu
bindContextMenu
在长按或者右键点击组件是才会触发显示菜单项,bindContextMenu
定义如下:
declare class CommonMethod<T> {bindContextMenu(content: CustomBuilder, responseType: ResponseType): T;
}
参数说明:
-
content:参数只支持使用
CustomBuilder
自定义 UI 一种方式, -
responseType:触发弹窗的响应类型,
ResponseType
定义了一下两种类型:
- LongPress:通过长按触发菜单弹出。
- RightClick:通过鼠标右键触发菜单弹出。(为了PC端 准备)
代码如下:
import prompt from '@system.prompt'
@Entry
@Component
struct CustomBuilderExample {//自定义菜单组件@Builder ButtonMenuBuilder(){Column(){Text("菜单1").width("100%").height(50).fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).onClick(()=>{prompt.showToast({message:"菜单1"})})//提供分隔器组件,分隔不同内容块/内容元素。Divider().width("100%").height(1).backgroundColor(Color.White)Text("菜单2").width("100%").height(50).fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).onClick(()=>{prompt.showToast({message:"菜单2"})})//提供分隔器组件,分隔不同内容块/内容元素。Divider().width("100%").height(1).backgroundColor(Color.White)Text("菜单3").width("100%").height(50).fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).onClick(()=>{prompt.showToast({message:"菜单3"})})}.width(200).backgroundColor("#2E8B57")}build() {Column({space:10}){Button("bindMenu").width(120).height(50).onClick(() => {//同时设置onClick和bindMenu,onClick不生效prompt.showToast({message:"hi Augus"})})//调用自定义的菜单组件.bindContextMenu(this.ButtonMenuBuilder, ResponseType.LongPress)//长按绑定菜单}.width("100%").height("100%").padding(20)}
}
预览效果如下:
4.3.bindPopup
bindPopup
和 bindMenu
类似,都是弹出一个可选项提示框, bindPopup
接口如下:
名称 | 参数类型 | 描述 |
---|---|---|
bindPopup | show: boolean,popup: PopupOptions | CustomPopupOptions8+ | 给组件绑定Popup,点击弹出弹窗。show: 创建页面弹窗提示是否默认显示,默认值为false。popup: 配置当前弹窗提示的参数。 |
参数说明如下:
- show:创建
Popup
弹窗时是否默认显示,默认值为 false 。 - popup:
Popup
的显示配置,参数支持PopupOptions
和CustomPopupOptions
两种类型,他们分别如下所示:
1)PopupOptions配置如下:
declare interface PopupOptions {message: string; // 显示的信息提示placementOnTop?: boolean; // 是否显示在组件上方,默认值为 falseprimaryButton?: { // 第一个按钮的配置value: string; // 按钮的文字action: () => void; // 按钮的点击回调};secondaryButton?: { // 第二个按钮的配置value: string; // 按钮的文字action: () => void; // 按钮的事件回调};onStateChange?: (event: { isVisible: boolean }) => void; // Popup可见性变化的回调
}
说明:
- message:
Popup
显示的提示文字。 - placementOnTop:
Popup
是否显示在组件上方。 - primaryButton:
Popup
显示按钮配置。 - secondaryButton:
Popup
显示按钮配置。 - onStateChange:
Popup
弹窗状态(是否可见性)变化事件回调
案例代码如下:
import prompt from '@system.prompt'
@Entry
@Component
struct BindPopupExample {//默认状态值@State isPopup:boolean = falsebuild() {Column({space:20}){Button("bindPopup").width(120).height(50)//this.isPopup为true的时候,才会显示.bindPopup(this.isPopup, {message: "获取摄像头权限",//显示的内容placementOnTop: true,//显示在组件上方onStateChange: ((state)=>{ // Popup可以见到菜单变化的回调prompt.showToast({message: `弹出是否可见:${state.isVisible}`})}),primaryButton:{value:"同意",action:()=>{prompt.showToast({message: "允许获取权限"})//修改状态this.isPopup = !this.isPopup}},secondaryButton:{value:"不同意",action:()=>{prompt.showToast({message: "不允许获取权限"})//修改状态this.isPopup = !this.isPopup}}}).onClick(()=>{prompt.showToast({message:"bindPopup按钮测试"})//修改状态this.isPopup = !this.isPopup})}.width("100%").height("100%").padding(20)}
}
预览效果如下:
2)CustomPopupOptions配置如下:
declare interface CustomPopupOptions {builder: CustomBuilder;placement?: Placement;maskColor?: Color | string | Resource | number;popupColor?: Color | string | Resource | number;enableArrow?: boolean;autoCancel?: boolean;onStateChange?: (event: { isVisible: boolean }) => void;
}
参数如下:
- builder:自定义
Popup
。 - placement:
Popup
的相对位置。 - maskColor:
Popup
蒙层颜色。 - popupColor:
Popup
背景颜色。 - enableArrow:
Popup
是否显示箭头。 - autoCancel:
Popup
是否自动隐藏。 - onStateChange:
Popup
弹出状态(窗口可见性)变化的回调。
案例代码如下:
import prompt from '@system.prompt'
@Entry
@Component
struct BindPopupExample02 {//默认状态值@State isPopup:boolean = false//自定义UI组件@Builder PopupButton(){Row(){Text("分享").width(80).height("100%").fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).backgroundColor("#3CB371").onClick(()=>{prompt.showToast({message:"分享"})})Divider().width(3).height("100%").backgroundColor(Color.White)Text("转发").width(80).height("100%").fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).backgroundColor("#3CB371").onClick(()=>{prompt.showToast({message:"转发"})})Divider().width(3).height("100%").backgroundColor(Color.White)Text("点赞").width(80).height("100%").fontSize(20).fontColor(Color.White).textAlign(TextAlign.Center).backgroundColor("#3CB371").onClick(()=>{prompt.showToast({message:"点赞"})})}.height(50)}build() {Column({space:20}){Button("bindPopup").width(120).height(50)//this.isPopup为true的时候,才会显示.bindPopup(this.isPopup, {builder: this.PopupButton, //使用自定义UIplacement:Placement.Bottom, //显示到下方按钮maskColor: Color.Pink, //蒙层颜色popupColor: Color.Orange, //背景颜色enableArrow: true, //显示箭头autoCancel:true, //设置自动隐藏onStateChange:((state)=>{prompt.showToast({message:`弹窗是否可见:${state.isVisible}`})})}).onClick(()=>{prompt.showToast({message:"bindPopup按钮测试"})//修改状态this.isPopup = !this.isPopup})}.width("100%").height("100%").padding(20)}
}
预览效果如下: