1. 文本输入 TextInput/TextArea
TextInput为单行输入框、TextArea为多行输入框。通过以下接口来创建。
TextArea(value?:{placeholder?: ResourceStr, text?: ResourceStr, controller?: TextAreaController})
TextInput(value?:{placeholder?: ResourceStr, text?: ResourceStr, controller?: TextInputController})
多行输入框文字超出一行时会自动折行。
1.1 TextInput
除支持通用属性外,还支持以下属性:
1.2 TextInputController
controller: TextInputController = new TextInputController()
1.3 TextArea
2. 弹窗
2.1 警告弹窗
AlertDialog.show()
// xxx.ets
@Entry
@Component
struct AlertDialogExample {
build() {
Column({ space: 5 }) {
Button('one button dialog')
.onClick(() => {
AlertDialog.show(
{
title: 'title',
message: 'text',
autoCancel: true,
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -20 },
gridCount: 3,
confirm: {
value: 'button',
action: () => {
console.info('Button-clicking callback')
}
},
cancel: () => {
console.info('Closed callbacks')
}
}
)
})
.backgroundColor(0x317aff)
Button('two button dialog')
.onClick(() => {
AlertDialog.show(
{
title: 'title',
message: 'text',
autoCancel: true,
alignment: DialogAlignment.Bottom,
gridCount: 4,
offset: { dx: 0, dy: -20 },
primaryButton: {
value: 'cancel',
action: () => {
console.info('Callback when the first button is clicked')
}
},
secondaryButton: {
value: 'ok',
action: () => {
console.info('Callback when the second button is clicked')
}
},
cancel: () => {
console.info('Closed callbacks')
}
}
)
}).backgroundColor(0x317aff)
}.width('100%').margin({ top: 5 })
}
}
2.2 列表选择弹窗
ActionSheet.show()
@Entry
@Component
struct ActionSheetExample {
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button('Click to Show ActionSheet')
.onClick(() => {
ActionSheet.show({
title: 'ActionSheet title',
message: 'message',
autoCancel: true,
confirm: {
value: 'Confirm button',
action: () => {
console.log('Get Alert Dialog handled')
}
},
cancel: () => {
console.log('actionSheet canceled')
},
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -10 },
sheets: [
{
title: 'apples',
action: () => {
console.log('apples')
}
},
{
title: 'bananas',
action: () => {
console.log('bananas')
}
},
{
title: 'pears',
action: () => {
console.log('pears')
}
}
]
})
})
}.width('100%')
.height('100%')
}
}
2.3 日期滑动选择器弹窗
DatePickerDialog.show()
// xxx.ets
@Entry
@Component
struct DatePickerDialogExample {
selectedDate: Date = new Date("2010-1-1")
build() {
Column() {
Button("DatePickerDialog")
.margin(20)
.onClick(() => {
DatePickerDialog.show({
start: new Date("2000-1-1"),
end: new Date("2100-12-31"),
selected: this.selectedDate,
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))
}
})
})
Button("Lunar DatePickerDialog")
.margin(20)
.onClick(() => {
DatePickerDialog.show({
start: new Date("2000-1-1"),
end: new Date("2100-12-31"),
selected: this.selectedDate,
lunar: true,
onAccept: (value: DatePickerResult) => {
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))
}
})
})
}.width('100%')
}
}
2.4 时间滑动选择器弹窗
TimePickerDialog.show()
// xxx.ets
@Entry
@Component
struct TimePickerDialogExample {
private selectTime: Date = new Date('2020-12-25T08:30:00')
build() {
Column() {
Button("TimePickerDialog 12小时制")
.margin(20)
.onClick(() => {
TimePickerDialog.show({
selected: this.selectTime,
onAccept: (value: TimePickerResult) => {
// 设置selectTime为按下确定按钮时的时间,这样当弹窗再次弹出时显示选中的为上一次确定的时间
this.selectTime.setHours(value.hour, value.minute)
console.info("TimePickerDialog:onAccept()" + JSON.stringify(value))
},
onCancel: () => {
console.info("TimePickerDialog:onCancel()")
},
onChange: (value: TimePickerResult) => {
console.info("TimePickerDialog:onChange()" + JSON.stringify(value))
}
})
})
Button("TimePickerDialog 24小时制")
.margin(20)
.onClick(() => {
TimePickerDialog.show({
selected: this.selectTime,
useMilitaryTime: true,
onAccept: (value: TimePickerResult) => {
this.selectTime.setHours(value.hour, value.minute)
console.info("TimePickerDialog:onAccept()" + JSON.stringify(value))
},
onCancel: () => {
console.info("TimePickerDialog:onCancel()")
},
onChange: (value: TimePickerResult) => {
console.info("TimePickerDialog:onChange()" + JSON.stringify(value))
}
})
})
}.width('100%')
}
}
2.5 文本滑动选择器弹窗
TextPickerDialog.show()
// xxx.ets
@Entry
@Component
struct TextPickerDialogExample {
private select: number | number[] = 2
private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4', 'banana5']
build() {
Row() {
Column() {
Button("TextPickerDialog")
.margin(20)
.onClick(() => {
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))
}
})
})
}.width('100%')
}.height('100%')
}
}
2.6 自定义弹窗(CustomDialog)
-
使用@CustomDialog装饰器装饰自定义弹窗。
-
@CustomDialog装饰器用于装饰自定义弹框,此装饰器内进行自定义内容(也就是弹框内容)。
-
创建构造器,与装饰器呼应相连。CustomDialogController仅在作为@CustomDialog和@Component struct的成员变量,且在@Component struct内部定义时赋值才有效,具体用法可看下方示例。CustomDialogController参数如下
// xxx.ets
@CustomDialog
struct CustomDialogExample {
@Link textValue: string
@Link inputValue: string
controller: CustomDialogController
// 若尝试在CustomDialog中传入多个其他的Controller,以实现在CustomDialog中打开另一个或另一些CustomDialog,那么此处需要将指向自己的controller放在最后
cancel: () => void
confirm: () => void
build() {
Column() {
Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 })
TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%')
.onChange((value: string) => {
this.textValue = value
})
Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 })
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('cancel')
.onClick(() => {
this.controller.close()
this.cancel()
}).backgroundColor(0xffffff).fontColor(Color.Black)
Button('confirm')
.onClick(() => {
this.inputValue = this.textValue
this.controller.close()
this.confirm()
}).backgroundColor(0xffffff).fontColor(Color.Red)
}.margin({ bottom: 10 })
}
// dialog默认的borderRadius为24vp,如果需要使用border属性,请和borderRadius属性一起使用。
}
}
@Entry
@Component
struct CustomDialogUser {
@State textValue: string = ''
@State inputValue: string = 'click me'
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({
cancel: this.onCancel,
confirm: this.onAccept,
textValue: $textValue,
inputValue: $inputValue
}),
cancel: this.existApp,
autoCancel: true,
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -20 },
gridCount: 4,
customStyle: false
})
// 在自定义组件即将析构销毁时将dialogController置空
aboutToDisappear() {
this.dialogController = undefined // 将dialogController置空
}
onCancel() {
console.info('Callback when the first button is clicked')
}
onAccept() {
console.info('Callback when the second button is clicked')
}
existApp() {
console.info('Click the callback in the blank area')
}
build() {
Column() {
Button(this.inputValue)
.onClick(() => {
if (this.dialogController != undefined) {
this.dialogController.open()
}
}).backgroundColor(0x317aff)
}.width('100%').margin({ top: 5 })
}
}
3. 视频播放 Video
3.1 组件创建
Video通过调用接口来创建,接口调用形式如下:
Video(value: {src?: string | Resource, currentProgressRate?: number | string | PlaybackSpeed, previewUri?: string | PixelMap | Resource, controller?: VideoController})
3.2 视频加载
- 加载本地视频时,首先在本地rawfile目录指定对应的文件,如下图所示。
再使用资源访问符$rawfile()引用视频资源。
@Component
export struct VideoPlayer{
private controller:VideoController;
private previewUris: Resource = $r ('app.media.preview');
private innerResource: Resource = $rawfile('videoTest.mp4');
build(){
Column() {
Video({
src: this.innerResource,
previewUri: this.previewUris,
controller: this.controller
})
}
}
}
- Data Ability提供的视频路径带有dataability://前缀,使用时确保对应视频资源存在即可。
@Component
export struct VideoPlayer{
private controller:VideoController;
private previewUris: Resource = $r ('app.media.preview');
private videoSrc: string = 'dataability://device_id/com.domainname.dataability.videodata/video/10'
build(){
Column() {
Video({
src: this.videoSrc,
previewUri: this.previewUris,
controller: this.controller
})
}
}
}
- 加载沙箱路径视频
支持file:///data/storage路径前缀的字符串,用于读取应用沙箱路径内的资源。需要保证应用沙箱目录路径下的文件存在并且有可读权限。
@Component
export struct VideoPlayer {
private controller: VideoController;
private videoSrc: string = 'file:///data/storage/el2/base/haps/entry/files/show.mp4'
build() {
Column() {
Video({
src: this.videoSrc,
controller: this.controller
})
}
}
}
- 加载网络视频
加载网络视频时,需要申请权限ohos.permission.INTERNET,具体申请方式请参考权限申请声明。此时,Video的src属性为网络视频的链接。
@Component
export struct VideoPlayer{
private controller:VideoController;
private previewUris: Resource = $r ('app.media.preview');
private videoSrc: string= 'https://www.example.com/example.mp4' // 使用时请替换为实际视频加载网址
build(){
Column() {
Video({
src: this.videoSrc,
previewUri: this.previewUris,
controller: this.controller
})
}
}
}
3.3 VideoController
一个VideoController对象可以控制一个或多个video
controller: VideoController = new VideoController()
提供了start(), stop(), pause(),setCurrentTime()指定视频播放的进度位置(单位为s), requestFullscreen(), exitFullscreen(), setCurrentTime(value: number, seekMode: SeekMode)控制方法.
// xxx.ets
@Entry
@Component
struct VideoCreateComponent {
@State videoSrc: Resource = $rawfile('video1.mp4')
@State previewUri: Resource = $r('app.media.poster1')
@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X
@State isAutoPlay: boolean = false
@State showControls: boolean = true
controller: VideoController = new VideoController()
build() {
Column() {
Video({
src: this.videoSrc,
previewUri: this.previewUri,
currentProgressRate: this.curRate,
controller: this.controller
}).width('100%').height(600)
.autoPlay(this.isAutoPlay)
.controls(this.showControls)
.onStart(() => {
console.info('onStart')
})
.onPause(() => {
console.info('onPause')
})
.onFinish(() => {
console.info('onFinish')
})
.onError(() => {
console.info('onError')
})
.onPrepared((e) => {
console.info('onPrepared is ' + e.duration)
})
.onSeeking((e) => {
console.info('onSeeking is ' + e.time)
})
.onSeeked((e) => {
console.info('onSeeked is ' + e.time)
})
.onUpdate((e) => {
console.info('onUpdate is ' + e.time)
})
Row() {
Button('src').onClick(() => {
this.videoSrc = $rawfile('video2.mp4') // 切换视频源
}).margin(5)
Button('previewUri').onClick(() => {
this.previewUri = $r('app.media.poster2') // 切换视频预览海报
}).margin(5)
Button('controls').onClick(() => {
this.showControls = !this.showControls // 切换是否显示视频控制栏
}).margin(5)
}
Row() {
Button('start').onClick(() => {
this.controller.start() // 开始播放
}).margin(5)
Button('pause').onClick(() => {
this.controller.pause() // 暂停播放
}).margin(5)
Button('stop').onClick(() => {
this.controller.stop() // 结束播放
}).margin(5)
Button('setTime').onClick(() => {
this.controller.setCurrentTime(10, SeekMode.Accurate) // 精准跳转到视频的10s位置
}).margin(5)
}
Row() {
Button('rate 0.75').onClick(() => {
this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // 0.75倍速播放
}).margin(5)
Button('rate 1').onClick(() => {
this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // 原倍速播放
}).margin(5)
Button('rate 2').onClick(() => {
this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // 2倍速播放
}).margin(5)
}
}
}
}