目录
一、鸿蒙国际化配置
二、鸿蒙常用组件介绍
三、鸿蒙像素单位介绍
四、鸿蒙布局介绍
1、Row与Column线性布局
2、层叠布局-Stack
3、弹性布局
4、栅格布局
5、网格布局
一、鸿蒙国际化配置
base目录下为默认的string。en_US对应美国的。zh_CN对应中国的。新增一个string以后。这3个文件夹下必须都有相同的key和value。
二、鸿蒙常用组件介绍
@Entry
@Component
//简单的常用组件集合
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text($r("app.string.PassWord_label"))
.fontSize(50)
.fontWeight(FontWeight.Bold)
.backgroundColor($r("app.color.Color_Blue"))
Text("1111111111111111111111111").fontSize(35)
.width(200).maxLines(1).textOverflow({
overflow:TextOverflow.Ellipsis
}).backgroundColor(Color.Yellow)
Button(){
Row(){
LoadingProgress().width(50).height(50).color(Color.White)
Text("登录").fontColor(Color.White)
}.width(100)
}
TextInput({
placeholder:"请输入"
}).fontSize(18).type(InputType.Password)
Divider()
TextArea({
placeholder:"多行文本"
}).height(100).placeholderColor(Color.Brown)//多行文本
Row(){
CheckboxGroup({
group:"list"
}).onChange(v=>{
console.log("11",JSON.stringify(v))
})
Row(){
Checkbox({group:"list",name:"测试"})
Text("测试")
}
Row(){
Checkbox({group:"list",name:'跑步'})
Text("跑步")
}
}
Row(){
Row(){
Radio({
group:'11',value:'语文'
}).onChange(v=>{
v&& console.log("语文")
})
Text("语文")
}
Row(){
Radio({
group:'11',value:'数学'
}).onChange(v=>{
v&& console.log("数学")
})
Text("数学")
}
Row(){
Radio({
group:'11',value:'英语'
}).onChange(v=>{
v&& console.log("英语")
})
Text("英语")
}
}
// 开关
Toggle({
type:ToggleType.Switch,
isOn:false
}).colorBlend(Color.Red).borderColor(Color.Blue)
// 开关
Toggle({
type:ToggleType.Checkbox,
isOn:false
}).colorBlend(Color.Red).borderColor(Color.Blue)
// 开关
Toggle({
type:ToggleType.Button,
isOn:true
}){
Text("测试")
}
// ------------------------------------------------------------------------------------------
// Contain:保持宽高比进行缩小或者放大,使得图片完全显示在显示边界内。
// Cover:保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界。
// Auto:自适应显示。
// Fill:不保持宽高比进行放大缩小,使得图片充满显示边界。
// ScaleDown:保持宽高比显示,图片缩小或者保持不变。
// None:保持原有尺寸显示。
// --------------------------------------------------------------------------------------------
// Image('images/2.jpg')
// .width(300)
// .height(300).border({ width:1 }).objectFit(ImageFit.Cover)
// Image('images/2.jpg').width(300)
// Image($r("app.media.icon")).width(300).interpolation(ImageInterpolation.High)
Image($r("app.media.icon"))
.border({width:1})
.renderMode(ImageRenderMode.Original)
.objectFit(ImageFit.None)
.width(300)
.interpolation(ImageInterpolation.High)
.objectRepeat(ImageRepeat.XY)
}
.width('100%').height("100%")
}
.height('100%')
}
}
三、鸿蒙像素单位介绍
鸿蒙为开发者提供4种像素单位,框架采用vp为基准数据单位。
px:屏幕物理像素单位。
vp:屏幕密度相关像素,根据屏幕像素密度转换为屏幕物理像素,当数值不带单位时,默认单位vp。在实际宽度为1440物理像素的屏幕上,1vp约等于3px。
fp:字体像素,与vp类似适用屏幕密度变化,随系统字体大小设置变化。
lpx:视窗逻辑像素单位,lpx单位为实际屏幕宽度与逻辑宽度 (通过designWidth配置) 的比值,designWidth默认值为720。当designWidth为720时,在实际宽度为1440物理像素的屏幕上,1lpx为2px大小。
例如:
1.1vp =在160dpi中的1px,vp保证了不同分辨率下 视觉效果的等价性,比如一个图标,在不同分辨率下都是视觉效果是等价。
应用场景:适合绝大多数场景。
2.1fp=在160dpi中的1px 乘以系统的缩放比例。
应用场景:用来设定字体大小,且需要支持系统字体大小调整时使用。
3.designWidth =1440, 1lpx= 1px
应用场景:对于UI图,部分需要高度还原的场景使用。
desingnWidth在这个文件夹里设置。
四、鸿蒙布局介绍
1、Row与Column线性布局
线性布局是开发中最常用的布局,通过线性容器Row和Column构建。线性布局是其他布局的基础,其子元素在线性方向上(水平方向和垂直方向)依次排列。线性布局的排列方向由所选容器组件决定
Column容器内子元素按照垂直方向排列,Row容器内子元素按照水平方向排列。根据不同的排列方向,开发者可选择使用Row或Column容器创建线性布局。
布局容器:具有布局能力的容器组件,可以承载其他元素作为其子元素,布局容器会对其子元素进行尺寸计算和布局排列。
布局子元素:布局容器内部的元素。
主轴:线性布局容器在布局方向上的轴线,子元素默认沿主轴排列。Row容器主轴为水平方向,Column容器主轴为垂直方向。
交叉轴: 垂直于主轴方向的轴线。Row容器交叉轴为垂直方向,Column容器交叉轴为水平方向。
间距:布局子元素的间距。
@Entry
@Component
struct PageDpi {
@State message: string = 'Hello World'
build() {
// Row() {
// Text("rr").width(100).height(100).backgroundColor(Color.Red)
// Text("ff").width(100).height(100).backgroundColor(Color.Blue)
// Text("aa").width(100).height(100).backgroundColor(Color.Yellow)
// }
// // 主轴的方向————>水平
// .justifyContent(FlexAlign.SpaceEvenly)
// // 交叉轴的方向————>垂直
// .alignItems(VerticalAlign.Top)
// .height('100%').backgroundColor(Color.Pink).width("100%")
// Column() {
// Text("rr").width(100).height(100).backgroundColor(Color.Red)
// Text("ff").width(100).height(100).backgroundColor(Color.Blue)
// Text("aa").width(100).height(100).backgroundColor(Color.Yellow)
// }
// // 主轴的方向————>垂直
// .justifyContent(FlexAlign.SpaceEvenly)
// // 交叉轴的方向————>水平
// .alignItems(HorizontalAlign.Start)
// .height('100%').backgroundColor(Color.Pink).width("100%")
Row() {
Column() {
Row(){
Button("退出")
Blank()//撑满空白的组件
Text("主页")
Blank()
Button("确定")
}.width("100%").backgroundColor(Color.Gray)
Row({space:50}) {
Text("rr").layoutWeight(1).height(100).backgroundColor(Color.Red)
Text("ff").layoutWeight(1).height(100).backgroundColor(Color.Blue)
Text("aa").layoutWeight(1).height(100).backgroundColor(Color.Orange)
}.justifyContent(FlexAlign.Start)
Row({space:10}){
Text("username")
TextInput().layoutWeight(100).backgroundColor(Color.Orange)
}.margin(10)
}.width("100%").height("100%").justifyContent(FlexAlign.Start)
}.height("100%")
}
}
2、层叠布局-Stack
层叠布局(StackLayout)用于在屏幕上预留一块区域来显示组件中的元素,提供元素可以重叠的布局。层叠布局通过Stack容器组件实现位置的固定定位与层叠,容器中的子元素(子组件)依次入栈,后一个子元素覆盖前一个子元素,子元素可以叠加,也可以设置位置。
@Entry
@Component
struct PageStack1 {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Stack() {
Text("龙")
.fontSize(50)
.fontWeight(FontWeight.Bold)
.width(300)
.height(300)
.backgroundColor(Color.Orange)
Text("兔")
.fontSize(50)
.fontWeight(FontWeight.Bold)
.width(100)
.height(100)
.backgroundColor(Color.Red)
//.alignContent(Alignment.TopStart)设置显示的位置
}.alignContent(Alignment.TopStart).height(350).backgroundColor(Color.Gray).width(350)
Stack() {
Text("兔")
.fontSize(50)
.fontWeight(FontWeight.Bold)
.width(100)
.height(100)
.backgroundColor(Color.Red).zIndex(2)//zIndex优先级
Text("龙")
.fontSize(50)
.fontWeight(FontWeight.Bold)
.width(300)
.height(300)
.backgroundColor(Color.Orange)
}
}
.width('100%')
}
.height('100%')
}
}
层叠布局举例,回到顶部功能:
@Entry
@Component
struct PageStack2 {
@State message: string = 'Hello World'
@State list: string[] = ["子(鼠)", "丑(牛)", "寅(虎)", "卯(兔)"
, "辰(龙)", "巳(蛇)", "午(马)", "未(羊)", "申(猴)", "酉(鸡)", "戌(狗)", "亥(猪)"]
@State isShow: boolean = false
scrolly:Scroller=new Scroller();
build() {
Row() {
Column() {
Stack() {
List({scroller:this.scrolly}) {
ForEach(this.list, item => {
ListItem() {
Text(item).fontSize(25)
}.width("100%").height(200)
})
}.onScrollIndex((start, end) => {
if(end>4){
this.isShow=true
}else{
this.isShow=false
}
})
if (this.isShow) {
Text("回顶部")
.backgroundColor(Color.Orange)
.borderRadius(10)
.width(100)
.height(50)
.fontSize(27)
.textAlign(TextAlign.Center)
.margin(18).onClick(()=>{
this.scrolly.scrollToIndex(0)
})
}
}.alignContent(Alignment.BottomEnd)
}
.width('100%')
}
.height('100%')
}
}
3、弹性布局
弹性布局Flex 提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。容器默认存在主轴与交叉轴,子元素默认沿主轴排列,子元素在主轴方向的尺寸称为主轴尺寸,在交叉轴方向的尺寸称为交叉轴尺寸。弹性布局在开发场景中用例特别多,比如页面头部导航栏的均匀分布、页面框架的搭建、多行数据的排列等等。
@Entry
@Component
struct PageFlex {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
// Flex({
// direction:FlexDirection.Row,//方向
// justifyContent:FlexAlign.Center,//主轴
// // alignItems:ItemAlign.Baseline
// alignItems:ItemAlign.Center,
// }){
// Text("111").width(100).height(100).backgroundColor(Color.Black).
// alignSelf(ItemAlign.Start)
// Text("222").width(100).height(200).backgroundColor(Color.Red)
// Text("333").width(100).height(100).backgroundColor(Color.Orange)
// .alignSelf(ItemAlign.End)
// }.width(400).height(400).backgroundColor(Color.Gray)
// Flex({
// direction: FlexDirection.Row, //方向
// justifyContent: FlexAlign.Start, //主轴
// // alignItems:ItemAlign.Baseline
// alignItems: ItemAlign.Center,
// wrap: FlexWrap.Wrap
// }) {
// Text("111").width("50%").height(100).backgroundColor(Color.Black)
// Text("222").width("50%").height(100).backgroundColor(Color.Red)
// Text("333").width("50%").height(100).backgroundColor(Color.Orange)
// }.width(400).height(400).backgroundColor(Color.Gray)
// }
Flex({
direction: FlexDirection.Row, //方向
justifyContent: FlexAlign.Start, //主轴
// alignItems:ItemAlign.Baseline
alignItems: ItemAlign.Center
}) {
Text("111").width(100).height(100).backgroundColor(Color.Black)
.flexGrow(1)//相当于权重
Text("222").width(100).height(100).backgroundColor(Color.Red)
.flexGrow(1)
Text("333").width(100).height(100).backgroundColor(Color.Orange)
.flexGrow(1)
}.width(400).height(400).backgroundColor(Color.Gray)
}
.width('100%')
}
.height('100%')
}
}
4、栅格布局
栅格布局是一种通用的辅助定位工具,对移动设备的界面设计有较好的借鉴作用。主要优势包括:
1.提供可循的规律: 栅格布局可以为布局提供规律性的结构,解决多尺寸多设备的动态布局问题。通过将页面划分为等宽的列数和行数,可以方便地对页面元素进行定位和排版。
2.统一的定位标注:栅格布局可以为系统提供一种统一的定位标注,保证不同设备上各个模块的布局一致性。这可以减少设计和开发的复杂度,提高工作效率。
3.灵活的间距调整方法:栅格布局可以提供一种灵活的间距调整方法满足特殊场景布局调整的需求。通过调整列与列之间和行与行之间的间距,可以控制整个页面的排版效果。
4.自动换行和自适应:栅格布局可以完成一对多布局的自动换行和自适应。当页面元素的数量超出了一行或一列的容量时,他们会自动换到下一行或下一列,并且在不同的设备上自适应排版,使得页简布局更加灵活和适应性强。
5.在GridRow栅格组件中,允许开发者使用breakpoints自定义修改断点的取值范围,最多支持6个断点,除了默认的四个断点外,还可以启用xl,xxl两个断点,支持六种不同尺寸 (xs,sm,md,lg,xl,xxl)设备的布局设置。
断点名称 设备描述
xs: 最小宽度类型设备
sm: 小宽度类型设备
md: 中等宽度类型设备
lg: 大宽度类型设备
xl: 特大宽度类型设备
xxl: 超大宽度类型设备
breakpoints: [value: ['320vp','520vp','840vp',"1080vp', '2000vp']}
@Entry
@Component
struct PageGrid {
@State message: string = 'Hello World'
@State bgColors: Color[] = [Color.Gray, Color.Red, Color.Orange, Color.Black, Color.Blue, Color.Pink, Color.Brown, Color.Yellow]
build() {
Row() {
// 默认12栅格
// GridRow({
// breakpoints: { value: ["200vp", "300vp", "400vp", "500vp", "600vp"] },
// }) {
// ForEach(this.bgColors, (item, index) => {
// GridCol({
// span: { xs:12, sm:6, md:4, lg:3, xl:2 }//一个孩子占几份
// }) {
// Row() {
// Text((index+1)+"").width("100%").height("50")
// }
// }.backgroundColor(item)
// })
// }.width("100%")
// 这个方法常用
GridRow({
direction:GridRowDirection.RowReverse,//反向排列
gutter:10,
columns: { xs:1, sm:2, md:4, lg:6, xxl:8 },
breakpoints: { value: ['200vp', '300vp', '400vp', '500vp', '600vp'] },
}) {
ForEach(this.bgColors, (item, index) => {
GridCol() {
Row() {
Text(`${index+1}`).width("100%").height(50)
}
}.backgroundColor(item)
})
}.width("100%")
}
.height('100%')
}
}
5、网格布局
网格布局是由“行”和“列"“分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。网格布局具有较强的页面均分能力,子组件占比控制能力,是一种重要自适应布局,其使用场景有九宫格图片展示、日历、计算器等。
通过设置行列数量与尺寸占比可以确定网格布局的整体排列方式。Grid组件提供了rowsTemplate和columnsTemplate属性用于设置网格布局行列数量与尺寸占比。rowsTemplate和columnsTemplate属性值是一个由多个空格和数字+fr"间隔拼接的字符串,r的个数即网格布后的行或列数,fr前面的数值大小,用于计算该行或列在网格布局宽度上的占比,最终决定该行或列的宽度。
Grid() {}
.rowsTemplate('lfr 1fr 1fr')
.columnsTemplate('lfr 2fr lfr')
@Entry
@Component
struct PageGrid1 {
@State message: string = 'Hello World'
@Styles
style(){
.backgroundColor(Color.Red)
.width("33.33333%")
// .height("50%")
}
build() {
Row() {
// Column() {
// Grid(){
// GridItem(){
// Text("111")
// }.style().columnStart(0).columnEnd(1)
// GridItem(){
// Text("222")
// }.style()
// GridItem(){
// Text("333")
// }.style().columnStart(2).columnEnd(3)
// GridItem(){
// Text("444")
// }.style()
// GridItem(){
// Text("555")
// }.style()
// GridItem(){
// Text("666")
// }.style()
// }.width('100%').height(200).columnsTemplate("1fr 1fr 1fr")
// .rowsTemplate("1fr 1fr").columnsGap(10).rowsGap(10)
// }
// .width('100%')
//
Column() {
Grid() {
GridItem() {
Text("111")
}.style()
GridItem() {
Text("222")
}.style()
GridItem() {
Text("333")
}.style()
GridItem() {
Text("444")
}.style()
GridItem() {
Text("555")
}.style()
GridItem() {
Text("666")
}.style()
GridItem() {
Text("777")
}.style()
GridItem() {
Text("888")
}.style()
GridItem() {
Text("999")
}.style()
}
.width('100%')
.height(200)
// .columnsTemplate("1fr 1fr 1fr")
.rowsTemplate("1fr 1fr")
.columnsGap(10)
.rowsGap(10)
}
.width('100%')
}
.height('100%')
}
}