HarmonyOS 鸿蒙Next一多开发
HarmonyOS 鸿蒙Next一多开发 媒体查询:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-media-query
响应式布局:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/responsive-layout
一多开发主要包含两个层面
一次开发,多个设备终端都能适配运行。不同设备屏幕能看到不同布局方案
一次开发,根据不同终端设备打包为不同hap,在每一种终端设备中就能下载对应的安装包
同一套代码,我们可以根据屏幕带下不一致,实现不同页面布局
一多开发需要用到的技术:
1、媒体查询:根据不同的屏幕尺寸用户自己来决定如何布局
2、栅格系统:栅格系统相当于封装好组件,可以实现在页面布局中,根据屏幕大小决定元素排列规则
媒体查询
响应式布局,可以检测当前设备的大小,根据设备大小来决定如何进行元素排列。比如手机端占100%,在屏幕宽度啊 500vp的时候。动态控制元素占50%
使用媒体查询检测屏幕显示方式:
这个的demo只是媒体查询的一个条件。只判断了横屏还是竖屏,真正要实现页面上元素的检测,尺寸的检测,可以添加更多的条件
封装媒体查询工具
可以根据屏幕大小来自动识别我们的设备类型
设备尺寸当前我们主要分为:
断点名称 | 取值范围(vp) |
---|---|
xs | [0, 320) |
sm | [320, 600) |
md | [600, 840) |
lg | [840, +∞) |
封装工具按照上面的断点来实现页面变化,检测设备的类型
媒体查询常量
开发媒体查询的时候,会用到很多数字或者一些值
有必要将代码中常用的参数封装到常量文件中,这里我创建一个BasicConstants和BreakPointConstants ,放在hsp模块中
export class BasicConstants{
static readonly FULL_WIDTH='100%'
static readonly FULL_HEIGHT='100%'
static readonly FULL_SIZE_SMALL='14vp'
static readonly FULL_SIZE_NORMAL='16vp'
static readonly FULL_SIZE_BIG='20vp'
static readonly FULL_SIZA_LARGE='30vp'
}
export class BreakPointConstants {
static readonly BREAKPOINT_SM: string = 'sm'
// 折叠屏可以用md来表示
static readonly BREAKPOINT_MD: string = 'md'
//pad可以用lg来表示
static readonly BREAKPOINT_LG: string = 'lg'
//断点的数组
static readonly BREAKPOINT_VALUE: Array<string> = ['320vp', '600vp', '840vp']
// 在水平方向占4份
static readonly COLUMN_SM: number = 4
static readonly COLUMN_MD: number = 8
static readonly COLUMN_LG: number = 12
static readonly GUTTER_X: number = 12
static readonly SPAN_SM: number = 4
static readonly SPAN_MD: number = 6
static readonly SPAN_LG: number = 8
static readonly OFFSET_MD: number = 1
static readonly OFFSET_LG: number = 2
static readonly CURRENT_BREAKPOINT: string = 'currentBreakpoint'
static readonly FONT_SIZE_SM: number = 14
static readonly FONT_SIZE_MD: number = 16
static readonly FONT_SIZE_LG: number = 18
static readonly COVER_MARGIN_SM: number = 10
static readonly COVER_MARGIN_MD: number = 30
static readonly COVER_MARGIN_LG: number = 40
static readonly RANGE_SM: string = '(320vp<=width<=600vp)'
static readonly RANGE_MD: string = '(600vp<=width<=840vp)'
static readonly RANGE_LG: string = '(840vp<=width)'
}
创建一个媒体查询公共代码
import { BreakPointConstants } from '../constants/BreakPointContants'
import { mediaquery } from '@kit.ArkUI'
export class BreakPointSystem{
// 媒体查询,得到单位要将这个sm md保存到全局,currentBreakPoint作为key
private currentBreakpoint:string=BreakPointConstants.BREAKPOINT_SM
// (1)屏幕大小条件查询
private smListener=mediaquery.matchMediaSync(BreakPointConstants.RANGE_SM)
private mdListener=mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD)
private lgListener=mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG)
// 定义一个公共函数,目的保存当前屏幕的检测结果
// sm md lg 应用状态
private updateCurrentBreakPoint(breakPoint:string){
if(this.currentBreakpoint!==breakPoint){
this.currentBreakpoint=breakPoint
// 将应用存储
AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT,this.currentBreakpoint)
}
}
//(2)给监听器绑定change事件
private isBreakPointSM=(mediaQueryResult:mediaquery.MediaQueryResult)=>{
if(mediaQueryResult.matches){
// 将sm的单位保存起来
this.updateCurrentBreakPoint(BreakPointConstants.BREAKPOINT_SM)
}
}
private isBreakPointMD=(mediaQueryResult:mediaquery.MediaQueryResult)=>{
if(mediaQueryResult.matches){
// 将MD的单位保存起来
this.updateCurrentBreakPoint(BreakPointConstants.BREAKPOINT_MD)
}
}
private isBreakPointLG=(mediaQueryResult:mediaquery.MediaQueryResult)=>{
if(mediaQueryResult.matches){
// 将LG的单位保存起来
this.updateCurrentBreakPoint(BreakPointConstants.BREAKPOINT_LG)
}
}
// 这个函数外面要调用
public register(){
this.smListener=mediaquery.matchMediaSync(BreakPointConstants.RANGE_SM)
this.smListener.on('change',this.isBreakPointSM)
this.mdListener=mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD)
this.mdListener.on('change',this.isBreakPointMD)
this.lgListener=mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG)
this.lgListener.on('change',this.isBreakPointLG)
}
// 解除事件的绑定,为了优化代码
public unregister(){
this.smListener.off('change',this.isBreakPointSM)
this.mdListener.off('change',this.isBreakPointMD)
this.lgListener.off('change',this.isBreakPointLG)
}
}
页面中使用
import { BreakPointSystem } from "common"
@Entry
@Component
struct MainIndex {
private breakPointSystem = new BreakPointSystem()
@StorageProp('currenBreakPoint') currenBreakPoint: string = 'sm'
aboutToAppear(): void {
// 进入页面想要注册监听器
this.breakPointSystem.register()
}
aboutToDisappear(): void {
this.breakPointSystem.unregister()
}
build(){
Column() {
Text(`当前的屏幕大小为${this.currenBreakPoint}`)
.fontSize(30)
}
.height('100%')
.width('100%')
}
}
Grid网格布局
网格适用于页面上规则的行列元素排列
主要涉及:日历的布局、计算器、商品等
核心知识点
@Builder grid(){
Grid(){
ForEach(this.activityTitle,(item:string,index:number)=>{
GridItem(){
Text(`${item}`)
.fontColor(Color.White)
}
.backgroundColor(Color.Blue)
},(item:string)=>item)
}
// 想让元素滚动只需要设置rowsTemplate或者columnsTemplate某一个属性,另外一遍就可以实现
.rowsTemplate('1fr 1fr')
.columnsTemplate('1fr 3fr 1fr')
.rowGap(10)
.columnsGap(10)
.width('100%')
.height(180)
.border({
width:1,
color:Color.Red
})
}
Grid:代表网格容器。里面必须存放的是GridItem元素。
GridItem:无需涉及宽和高。在Grid容器一旦设置行列过后。默认撑满这个容器
rowsTemplate:代表列元素设置的单位。fr也是代表占的大小
columnTemplate:代表列元素设置的单位。fr也是代表占的大小
rowsGap:设置行与行之间的间隙
columnsGap:设置列与列之间的间隙
layoutDirection:可以控制元素排列过程中的显示方向。row和column
网格数据合并
@Entry
@Component
struct GridExample{
@State numbers:String[]=['0','1','2','4','5','6','7','8','9']
layoutOptions:GridLayoutOptions={
// 主要控制页面中GridItem 比例1:1
regularSize:[1,1],
//[0,0,1,1]---->[rowStart,columnStart,rowSpan,columnSpan]] 其中rowStart为行起始位置,columnStart为列起始位置,无单位。rowSpan为GridItem占用的行数,columnSpan为GridItem占用的列数,无单位。
onGetRectByIndex:(index:number)=>{
if(index==0){
return [0,0,1,2]
}else if(index==1){
return [0,1,2,1]
}else{
return [0,0,1,1]
}
}
}
build(){
Column({space:5}){
Grid(null,this.layoutOptions){
ForEach(this.numbers,(item:string)=>{
GridItem(){
Text(item)
.fontSize(16)
.backgroundColor(0xF9CF93)
.textAlign(TextAlign.Center)
}.backgroundColor(Color.Pink)
},(item:string)=>item)
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width('90%')
.backgroundColor(0xFAEEE0)
.height(400)
}.width('100%').marin({top:5})
}
}
栅格系统
栅格系统是目前提供一种响应式布局方案
基础代码
@Entry
@Component
struct Index{
@State bgColors:Color[]=[Color.Red,Color.Oriange,Color.Yellow,Color.Green,Color.Pink,Color.Gray,Color.Blue,Color.Brown,Color.Pink,Color.Gray,Color.Blue,Color.Brown]
build(){
GridRow(){
FoeEach(this.bgColor,(item:Color)=>{
GridCol(){
Text(`${index}`)
.backgroundColor(item)
.width(40)
.lineHeight(50)
}
},(item:color)=>item)
}
}
}
GridRow 代表一行,里面必须存放GridCol
默认一行可以最多显示12个元素,代表12列栅格布局
栅格布局是一种涉及流程,很多框架都会采用。每一家框架设计区别:比如antd 24列
自定义设置一行最多显示多少列。Columns属性来控制
GridROw({columns:3}){}
可以指定根据不同的屏幕尺寸设计不同的元素排列个数,代表sm单位的屏幕,一行最多显示4个,md单位的屏幕一行最多显示8个
GridRow({columns:{sm:4,md:8}}){}
自定义断点
GridRow({columns:{sm:4,md:8},
breakpoints:{value:['200vp','300vp','400vp','500vp','600vp']}
}){}
breakpoints:可以允许用户根据屏幕来自定义断点值。
默认情况下:官方提供4个断点,最多可以支持6个断点。xl和xxl是允许扩展的
断点名称 | 取值范围(vp) |
---|---|
xs | [0, 320) |
sm | [320, 600) |
md | [600, 840) |
lg | [840, +∞) |
direction:可以设置容器里面子元素排列顺序,主要是Row和RowReverse
GridRow({columns:{sm:4,md:8},
breakpoints:{value:['200vp','300vp','400vp','500vp','600vp']},
direction:GridRowDirection.RowReverse
}){}
gutter:设置子元素在水平方向排列过程中,默认间距
GridRow({columns:{sm:4,md:8},
breakpoints:{value:['200vp','300vp','400vp','500vp','600vp']},
gutter:10
}){}
GridCol参数
span参数可以设置指定每一份占几个单元格
GridCol({span:{sm:2,md:3}})
{
Text(`${index}`)
.backGroundColor(item)
.height(50)
.width('100%'))
}
可以通过属性来控制当前盒子偏移份数。相当于margin-left这个属性
GridCol({
span:{sm:2,md:3}},
offset:1
){}
更多关于HarmonyOS 鸿蒙Next一多开发的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next一多开发的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
HarmonyOS Next是华为推出的新一代操作系统,支持“一多开发”理念,即一次开发,多端部署。开发者可以使用统一的开发框架和工具,编写一次代码,即可在手机、平板、智能手表、智能家居等多种设备上运行。这大大提高了开发效率,降低了维护成本。HarmonyOS Next还提供了丰富的API和开发工具,支持多种编程语言,如Java、JS、C/C++等,帮助开发者快速构建跨设备的应用。