1、Image图片组件
鸿蒙内置组件Image的4种写法
// 鸿蒙内置Image图片组件案例
@Entry
@Component
struct ImagePage {
build() {
Column({space:20}){
// 1、图片的第一种写法 media文件夹下
Image($r('app.media.pig')).width(200).height(200);
// 2、图片的第二种写法 rawfile文件夹下
Image($rawfile('avatar2.jpg')).width(200).height(200);
// 3、图片的第三种写法 网络图片 (需要在module.JSON5文件中申请网络权限)
Image('https://img1.baidu.com/it/u=3621655768,3950011962&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=400').width(200).height(200);
// 4、图片的第四种写法 图片资源放在ets文件夹下
Image('images/gx5.gif').width('200').height('200');
}.width('100%').height('100%')
}
}
2、像素单位(默认):vp
鸿蒙提供的长度像素单位为:px
与 vp
● HarmonyOS中提供的长度像素单位为:px 与 vp
● px: Pixel,屏幕物理像素单位。
- 问题:相同px值在不同像素密度的手机上显示的尺寸是不同的(如下图所示)
- 注意:不同于CSS中的px,CSS中的px类似于下面的vp
● vp: Virtual Pixel,虚拟像素
- 它是屏幕像素密度相关像素
- 应用运行时,会根据屏幕像素密度转换为屏幕物理像素进行显示
- 在不同像素密度的手机上,1vp对应的像素数是不同的,像素密度越高,1vp对应的像素数就越多。从而达到:用vp作为长度单位,在尺寸相同但像素密度不同的手机上,显示大小相同。(如下图所示)
- 当数值不带单位时,默认单位为vp。
- HarmonyOS提供了针对运行设备的vp与px转换的全局计算函数
■ px2vp(val): 得到指定px值对应的vp值
■ vp2px(val): 得到指定vp值对应的px值
@Entry
@Component
struct VpExample {
build() {
Column(){
Text('我的宝宝呢').width('1080px').height('100px').backgroundColor('red')
Text('当前设备1vp=多少px'+vp2px(1)).width(200).height(200).fontSize(20)
Image($r('app.media.avatar')).width('100px').height('100px')
Image($r('app.media.avatar')).width(100).height(100)
Image($r('app.media.avatar')).width('100vp').height('100vp')
Image($r('app.media.avatar')).width(vp2px(100)+'px').height(vp2px(100)+'px')
}
}
}
3、Text文本组件
@Entry
@Component
struct TextExample {
build() {
Column(){
// 1、文本的第一种写法
Text('文本的第一种写法')
.fontSize(20) // 文字大小
.fontColor('green') // 文字颜色
// 2、文本的第二种写法
Text($r('app.string.text_example'))
.fontWeight(500) // 文字宽度
.width(100) // 文本宽度
.height(100) // 文本高度
.backgroundColor(Color.Orange) // 背景颜色
.textAlign(TextAlign.End) // 文本对齐方式
.textOverflow({
overflow:TextOverflow.Ellipsis // 文本长度溢出显示省略号
})
.maxLines(1) // 最大一行
}.width('100%')
}
}
4、Button按钮组件
@Entry
@Component
struct ButtonExample {
build() {
// 列
Column() {
Button('按钮')
.type(ButtonType.Normal) // 按钮样式
.onClick(() => { // 绑定事件
console.log('点击事件')
});
// Button放置子组件
Button() {
Image($r('app.media.icon')).width(30).height(30)
}.width(100)
.height(100)
.onClick(() => {
console.log('onClick事件')
})
}.width('100%')
}
}
5、Toggle组件
@Entry
@Component
struct ToggleExample {
build() {
Column(){
// 切换按钮
Toggle({type:ToggleType.Checkbox,isOn:false}) // 复选框
Toggle({type:ToggleType.Switch,isOn:true}) // 开关
Toggle({type:ToggleType.Button,isOn:true }){// 按钮
Text('自定义')
// Button('button')
}.selectedColor(Color.Pink).onClick((event) => {
console.log('自定义按钮')
}).onChange((isOn) => {
console.log(JSON.stringify(isOn))
})
}.width('100%')
}
}
6、TextInput文本输入框组件
@Entry
@Component
struct TextInputExample {
// 用户名
@State username: string = ''
// 密码
@State password: string = ''
// 方法
login(username: string, password: string) {
console.log(`发送登录请求~~~ username:${username} password:${password}`)
if(username != '' && password != ''){
console.log('登录成功')
}else {
console.log('登录失败')
}
}
build() {
Column() {
// 表单
TextInput({ placeholder: '请输入用户名', text: this.username })
.onChange((value) => {
this.username = value
console.log(`username:${value}`)
})
.maxLength(5)
.type(InputType.Number)
.margin({ top: 10 });
Divider().margin({top:10}); // 分割线
TextInput({ placeholder: '请输入密码', text: this.password })
.onChange((value) => {
this.password = value
console.log(`password:${value}`)
})
.maxLength(6)
.type(InputType.Password)
.margin({ top: 10 });
Button("登录")
.type(ButtonType.Normal)
.margin({ top: 10 })
.onClick(() => this.login(this.username,this.password))
}.width('100%').padding(20)
}
}
7、Progress进度条组件
@Entry
@Component
struct ProgressExample {
build() {
Column(){
// 进度条组件
Progress({value:10,total:100,type:ProgressType.ScaleRing})
Progress({value:30,total:100,type:ProgressType.Linear})
Progress({value:50,total:100,type:ProgressType.Eclipse})
Progress({value:70,total:100,type:ProgressType.Capsule})
Progress({value:100,total:100,type:ProgressType.Ring})
}.width('100%').padding(10)
}
}
8、弹窗组件之API弹窗
// 引入api弹窗
import promptAction from '@ohos.promptAction';
@Entry
@Component
struct ApiPopupExample1 {
build() {
Column() {
/**
* 弹窗分类:
* 1、API弹窗 :需要引入相关模块,只能做简单弹窗
* 2、预制弹窗 :直接使用
*/
Row() {
// 1、提示信息弹窗
Button('提示信息').onClick(() => {
promptAction.showToast({
message: '苦命后端学鸿蒙', // 弹窗内容
duration: 1000, // 弹窗显示时间
bottom: 200 // 弹窗离底部距离
})
})
}
Row() {
// 对话框
Button('对话框').onClick(() => {
promptAction.showDialog({
title: '你确定删除王者荣耀么?',
message: '玩的心累',
buttons: [
{
text: '确定',
color: '#CF539'
},
{
text: '取消',
color: '#aaa'
},
]
}).then(res => {
// 通过index区分 确定 还是 取消
console.log('res执行了'+res.index)
}).catch(err => {
console.log('err执行了'+err)
}).finally(() => {
console.log('finally执行了')
})
})
}.margin({ top: 10 })
Row(){
// 菜单弹窗
Button('菜单弹窗').onClick(() => {
promptAction.showActionMenu({
title:'你想要什么',
buttons:[
{
text:'Iphone15ProMax',
color:'8F4D68'
},
{
text:'笔记本电脑',
color:'333840'
}
]
}).then(res => {
console.log('选择的是哪个选项'+res.index)
}).catch(() => {
// 取消执行
console.log('catch')
})
})
}.margin({top:10})
}.width('100%').padding(10)
}
}
9、预制弹窗
@Entry
@Component
struct YuZhiPopupExample {
@State selectedDate: Date = new Date("2023-02-06");
@State selectTime: Date = new Date('2020-12-25T08:30:00')
@State select: number = 2
@State fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4', 'banana5']
private selectCount: number = 10
build() {
Column({ space: 20 }) {
//警告弹窗
Row() {
Button('警告弹窗').onClick((event: ClickEvent) => {
AlertDialog.show({
title: '操作提示', // 弹窗标题
message: '确认删除吗?', // 弹窗内容
autoCancel: false, //点击遮障层时,是否关闭弹窗。
alignment: DialogAlignment.Center, //弹窗位置
gridCount: 4, // 弹窗容器宽度所占用栅格数
offset: { dx: 30, dy: -20 }, //弹窗相对alignment所在位置的偏移量
/* 多个按钮 -- 开始 */
// primaryButton: { //主按钮的文本内容、文本色、按钮背景色和点击回调。
// value: '确认', //按钮文字
// action: () => { //按钮回调
// console.info('你点击了确定按钮')
// },
// fontColor:'red'
// },
// secondaryButton: { //副按钮的文本内容、文本色、按钮背景色和点击回调。
// value: '取消', //按钮文字
// action: () => { //按钮回调
// console.info('你点击了取消按钮')
// },
// fontColor:'#aaa'
// },
/* 多个按钮 -- 结束 */
/* 单个按钮 -- 开始 */
confirm: {
value: '确认',
action: () => {
console.info('xxxxxx')
}
}
})
})
}
//列表弹窗
Row() {
Button('列表弹窗').onClick(() => {
ActionSheet.show({
title: '操作提示', // 弹窗标题
message: '请选择类型', //弹窗内容
autoCancel: true, //点击遮障层时,是否关闭弹窗。
// 确认按钮的文本内容和点击回调
confirm: {
value: '确定', //文字内容
action: () => { //回调
console.log('你点击了确认按钮')
}
},
// 点击遮障层关闭dialog时的回调
cancel: () => {
console.log('弹窗关闭了')
},
// 弹窗在竖直方向上的对齐方式。
alignment: DialogAlignment.Bottom,
// 弹窗相对alignment所在位置的偏移量
offset: { dx: 0, dy: -10 },
// 设置选项内容,每个选择项支持设置图片、文本和选中的回调
sheets: [
{
title: '打折商品', // 标题
action: () => { // 回调
console.log('goods1')
}
},
{
title: '限购商品',
action: () => {
console.log('goods2')
}
},
{
title: 'VIP商品',
action: () => {
console.log('goods2')
}
},
{
title: '预售商品',
action: () => {
console.log('goods3')
}
}
]
})
})
}
// 日期滑动选择器
Row() {
Button('阳历').onClick((event: ClickEvent) => {
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('阴历').onClick((event: ClickEvent) => {
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))
}
})
})
}
//时间滑动选择器
Row() {
Button('12小时制').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('24小时').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))
}
})
})
}
//文本滑动选择器
Row() {
Button('文本滑动选择器').onClick((event: ClickEvent) => {
TextPickerDialog.show({
range: this.fruits,
selected: this.selectCount,
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%');
}
}
10、线性布局
@Entry
@Component
struct LayoutExample {
private arr: Array<number> = [1, 2, 3, 4, 5]
private colors: Array<Color> = [Color.Red, Color.Green, Color.Blue, Color.Orange, Color.Pink]
build() {
// 线性布局
Column({ space: 20 }) {
Row() {
}.width(360).height(50).backgroundColor(Color.Red)
Row() {
}.width(360).height(50).backgroundColor(Color.Orange)
Row() {
}.width(360).height(50).backgroundColor(Color.Yellow)
Row() {
}.width(360).height(50).backgroundColor(Color.Blue)
Row() {
// 遍历
ForEach(this.arr, (index) => {
Column() {
}.width('10%').height(100).backgroundColor(this.colors[index-1]).margin({ left: 10 })
}, item => JSON.stringify(item))
//
//
// Column() {
// }.width('20%').height(100).backgroundColor(Color.Pink)
//
// Column() {
// }.width('20%').height(100).backgroundColor(Color.White)
//
// Column() {
// }.width('20%').height(100).backgroundColor(Color.Gray)
//
// Column() {
// }.width('20%').height(100).backgroundColor(Color.Brown)
}
// .justifyContent(FlexAlign.Center)
.justifyContent(FlexAlign.SpaceAround).height(300).alignItems(VerticalAlign.Top)
}
}
}
11、层叠布局
@Entry
@Component
struct CascadeLayoutExample {
build() {
Stack() {
Row() {
Text('子元素1')
}.width(300)
.height(300)
.backgroundColor(Color.Red)
// 设置层叠索引
.zIndex(2)
Row(){
Text('子元素2')
}.width(150)
.height(150)
.backgroundColor(Color.Orange)
Row(){
Text('子元素3')
}.width(75)
.height(75)
.backgroundColor(Color.Blue)
}
.width('100%')
.height(400)
.backgroundColor(Color.Green)
// 设置层叠对其方式
.alignContent(Alignment.BottomStart)
}
}
层叠布局与position一起使用
@Entry
@Component
struct PositionExample {
build() {
Stack(){
Image($r('app.media.pig')).width(100).height(100)
// position:绝对定位
.position({x:100,y:100})
}.width('100%')
.height(500)
.backgroundColor(Color.Black)
}
}
12、Flex弹性布局
@Entry
@Component
struct FlexExample {
build() {
Flex({direction:FlexDirection.RowReverse,justifyContent:FlexAlign.SpaceEvenly,alignItems:ItemAlign.Stretch}) {
Row() {
}.width(60).height(60).backgroundColor(Color.Red)
Row() {
}.width(60).height(60).backgroundColor(Color.Orange)
Row() {
}.width(60).height(60).backgroundColor(Color.Yellow)
Row() {
}.width(60).height(60).backgroundColor(Color.Green)
}.width('100%')
.height(300)
.backgroundColor('#ccc')
}
}
13、网格布局
@Entry
@Component
struct GridLayoutExample {
build() {
// Grid(){
// GridItem().backgroundColor(Color.Red).rowStart(1).rowEnd(2)
// GridItem().backgroundColor(Color.Green)
// GridItem().backgroundColor(Color.Yellow)
// GridItem().backgroundColor(Color.Blue)
// GridItem().backgroundColor(Color.Pink)
// GridItem().backgroundColor(Color.Brown)
// GridItem().backgroundColor(Color.Orange)
// GridItem().backgroundColor(Color.Grey)
// GridItem().backgroundColor(Color.White)
// }.width('100%')
// .height(500)
// .backgroundColor('#ccc')
// .rowsTemplate('1fr 1fr 1fr')
// .columnsTemplate('1fr 1fr 1fr')
// .rowsGap(5)
// .columnsGap(5)
Grid(){
GridItem(){}.width('25%').height(100).backgroundColor(Color.Red)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Orange)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Yellow)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Pink)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Pink)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Yellow)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Red)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Orange)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Pink)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Yellow)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Red)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Orange)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Pink)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Yellow)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Red)
GridItem(){}.width('25%').height(100).backgroundColor(Color.Orange)
}.width('100%')
.height(300)
// 只能指定行|列 父组件空间不足则可以滚动
.backgroundColor(Color.Gray)
.columnsTemplate('1fr 1fr')
.rowsGap(10)
.columnsGap(10)
}
}
14、List列表布局
@Entry
@Component
struct ListLayoutExample {
build() {
List(){
ListItem(){
Text('周杰伦').width(100).height(40).fontSize(20)
}.backgroundColor(Color.Red).width('100%')
ListItem(){
Text('林俊杰').width(100).height(40).fontSize(20)
}.backgroundColor(Color.Red).width('100%')
ListItem(){
Text('许嵩').width(100).height(40).fontSize(20)
}.backgroundColor(Color.Red).width('100%')
ListItemGroup(){
ListItem(){
Flex({justifyContent:FlexAlign.SpaceBetween}){
Text('园游会').fontSize(30)
Text('一路向北').fontSize(30)
}
}
ListItem(){
Flex({justifyContent:FlexAlign.SpaceBetween}){
Text('断桥残血').fontSize(30)
Text('清明雨上').fontSize(30)
}
}
}
}.width('100%')
.height(300)
.listDirection(Axis.Horizontal)
}
}
List列表布局案例
@Entry
@Component
struct ListLayoutExample {
@State userArr: object[] = [
{ title: 'A', data: ['A001', 'A002', 'A003', 'A004', 'A005'] },
{ title: 'B', data: ['B001', 'B002', 'B003', 'B004', 'B005'] },
{ title: 'C', data: ['C001', 'C002', 'C003', 'C004', 'C005'] },
{ title: 'D', data: ['D001', 'D002', 'D003', 'D004', 'D005'] },
{ title: 'E', data: ['E001', 'E002', 'E003', 'E004', 'E005'] }
]
// UI组件复用 @Builder
@Builder header(item){
Text(item.title).backgroundColor(Color.Red).textAlign(TextAlign.Center)
.width('100%')
}
build() {
List(){
ForEach(this.userArr,(item,index) => {
ListItemGroup({header:this.header(item)}){
ForEach(item.data,(name,i) => {
ListItem(){
Text(name).fontSize(20).fontWeight(500)
}
},item => JSON.stringify(item))
}
},item => JSON.stringify(item))
}.width('100%')
.height(300)
}
}
标签:之内,width,Color,value,height,HarmonyOS,backgroundColor,组件,100
From: https://www.cnblogs.com/ybbit/p/18071705