提交 981cd436 编写于 作者: K kukixi

add component use guide

Signed-off-by: Nkukixi <kouxinxin@huawei.com>
上级 ba8ec883
# Button
Button是按钮组件,通常用于响应用户的点击操作,如提交表单,其类型包括胶囊按钮、圆形按钮、普通按钮。
## 创建按钮
Button通过调用接口来创建,接口调用有以下两种形式:
- Button(options?: {type?: ButtonType, stateEffect?: boolean})
该接口用于创建包含子组件的按钮,其中type用于设置Button类型,stateEffect属性设置Button是否开启点击效果。
```
Button({ type: ButtonType.Normal, stateEffect: true }) {
Row() {
Image($r('app.media.loading')).width(20).height(20).margin({ left: 12 })
Text('loading').fontSize(12).fontColor(0xffffff).margin({ left: 5, right: 12 })
}.alignItems(VerticalAlign.Center)
}.borderRadius(8).backgroundColor(0x317aff).width(90)
```
![zh-cn_image_0000001260555857](figures/zh-cn_image_0000001260555857.png)
- Button(label?: string, options?: { type?: ButtonType, stateEffect?: boolean })
该接口用于创建不包含子组件的按钮,其中label确定所创建的Button是否包含子组件。
```
Button('Ok', { type: ButtonType.Normal, stateEffect: true })
.borderRadius(8)
.backgroundColor(0x317aff)
.width(90)
```
![zh-cn_image_0000001215796030](figures/zh-cn_image_0000001215796030.png)
## 设置按钮类型
Button有三种可选类型,分别为Capsule(胶囊类型)、Circle(圆形按钮)和Normal(普通按钮),通过type进行设置。
- 胶囊按钮(默认类型)
```
Button('Disable', { type: ButtonType.Capsule, stateEffect: false })
.backgroundColor(0x317aff)
.width(90)
```
![zh-cn_image_0000001215645452](figures/zh-cn_image_0000001215645452.png)
- 圆形按钮
```
Button('Circle', { type: ButtonType.Circle, stateEffect: false })
.backgroundColor(0x317aff)
.width(90)
.height(90)
```
![zh-cn_image_0000001215965420](figures/zh-cn_image_0000001215965420.png)
## 自定义样式
- 设置边框弧度
一般使用通用属性来自定义按钮样式。例如通过borderRadius属性设置按钮的边框弧度。
```
Button('圆角', { type: ButtonType.Normal })
.borderRadius(20)
```
![zh-cn_image_0000001190463780](figures/zh-cn_image_0000001190463780.png)
- 设置文本样式
通过添加文本样式设置按钮文本的展示样式。
```
Button('文本样式', { type: ButtonType.Normal })
.fontSize(20)
.fontColor(Color.Red)
.fontWeight(800)
```
![zh-cn_image_0000001189744672](figures/zh-cn_image_0000001189744672.png)
- 设置背景颜色
添加backgroundColor属性设置按钮的背景颜色。
```
Button('背景颜色').backgroundColor(0xF55A42)
```
![zh-cn_image_0000001235146483](figures/zh-cn_image_0000001235146483.png)
- 用作功能型按钮
为删除操作创建一个按钮。
```
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($r('app.media.ic_public_delete_filled')).width(30).height(30)
}.width(55).height(55).margin({ left: 20 }).backgroundColor(0xF55A42)
```
![zh-cn_image_0000001260373911](figures/zh-cn_image_0000001260373911.png)
## 添加事件
Button组件通常用于触发某些操作,可以在绑定onClick事件来响应点击操作后的自定义行为。
```
Button('Ok', { type: ButtonType.Normal, stateEffect: true })
.onClick(()=>{
console.info('Button onClick')
})
```
## 场景示例
- 用于启动操作
可以将按钮用于启动操作的任何用户界面元素。按钮会根据用户的操作触发相应的事件。如,在List容器里边通过点击按钮进行页面跳转:
```
import router from '@ohos.router'
@Entry
@Component
struct ButtonExample {
build() {
List({ space: 4 }) {
ListItem() {
Button("First").onClick(() => {
router.push({ url: 'xxx' })
})
}
ListItem() {
Button("Second").onClick(() => {
router.push({ url: 'yyy' })
})
}
ListItem() {
Button("Third").onClick(() => {
router.push({ url: 'zzz' })
})
}
}
.listDirection(Axis.Vertical)
.backgroundColor(0xDCDCDC).padding(20)
}
}
```
![zh-cn_image_0000001235626467](figures/zh-cn_image_0000001235626467.png)
- 用于表单的提交
在用户登录/注册页面,用户的登录或注册的提交操作会用按钮。
```
@Entry
@Component
struct ButtonCase2 {
build() {
Column() {
TextInput({ placeholder: 'input your username' }).margin({ top: 20 })
TextInput({ placeholder: 'input your password' }).type(InputType.Password).margin({ top: 20 })
Button('注册').width(300).margin({ top: 20 })
}.padding(20)
}
}
```
![zh-cn_image_0000001190466492](figures/zh-cn_image_0000001190466492.png)
# 弹性布局
Flex组件用于创建弹性布局,开发者可以通过Flex的接口创建容器组件,进而对容器内的其他元素进行弹性布局,例如:使三个元素在容器内水平居中,垂直等间隔分散。
## 创建弹性布局
接口的调用形式如下:
Flex(options?: { direction?: FlexDirection, wrap?: FlexWrap, justifyContent?: FlexAlign, alignItems?: ItemAlign, alignContent?: FlexAlign })
通过参数direction定义弹性布局的布局方向,justifyContent定义弹性布局方向上的子组件对齐方式, alignContent定义与布局方向垂直的方向上的子组件对齐方式,wrap定义内容超过一行时是否换行。
## 弹性布局方向
弹性布局有两个方向,子组件放置的方向是主轴,与主轴垂直的方向是交叉轴。通过direction参数设置容器主轴的方向,可选值有:
- FlexDirection.Row(默认值):主轴为水平方向,子组件从起始端沿着水平方向开始排布。
```
Flex({ direction: FlexDirection.Row }) {
Text('1').width('33%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(50).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218579606](figures/zh-cn_image_0000001218579606.png)
- FlexDirection.RowReverse:主轴为水平方向,子组件从终点端沿着FlexDirection.Row相反的方向开始排布。
```
Flex({ direction: FlexDirection.RowReverse }) {
Text('1').width('33%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(50).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218739566](figures/zh-cn_image_0000001218739566.png)
- FlexDirection.Column:主轴为垂直方向,子组件从起始端沿着垂直方向开始排布。
```
Flex({ direction: FlexDirection.Column }) {
Text('1').width('100%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('100%').height(50).backgroundColor(0xD2B48C)
Text('3').width('100%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263019457](figures/zh-cn_image_0000001263019457.png)
- FlexDirection.ColumnReverse:主轴为垂直方向,子组件从终点端沿着FlexDirection.Column相反的方向开始排布。
```
Flex({ direction: FlexDirection.ColumnReverse }) {
Text('1').width('100%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('100%').height(50).backgroundColor(0xD2B48C)
Text('3').width('100%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263339459](figures/zh-cn_image_0000001263339459.png)
## 弹性布局换行
默认情况下,子组件在Flex容器中都排在一条线(又称"轴线")上。通过wrap参数设置其他换行方式,可选值有:
- FlexWrap.NoWrap : 不换行。如果子元素的宽度总和大于父元素的宽度,则子元素会被压缩宽度。
```
Flex({ wrap: FlexWrap.NoWrap }) {
Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263139409](figures/zh-cn_image_0000001263139409.png)
- FlexWrap.Wrap:换行。
```
Flex({ wrap: FlexWrap.Wrap }) {
Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
Text('3').width('50%').height(50).backgroundColor(0xD2B48C)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218419614](figures/zh-cn_image_0000001218419614.png)
- FlexWrap.WrapReverse:换行,且与行排列方向相反。
```
Flex({ wrap: FlexWrap.WrapReverse}) {
Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263259399](figures/zh-cn_image_0000001263259399.png)
## 弹性布局对齐方式
### 主轴对齐
可以通过justifyContent参数设置在主轴的对齐方式,可选值有:
- FlexAlign.Start: 元素在主轴方向首端对齐, 第一个元素与行首对齐,同时后续的元素与前一个对齐。
```
Flex({ justifyContent: FlexAlign.Start }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218259634](figures/zh-cn_image_0000001218259634.png)
- FlexAlign.Center: 元素在主轴方向中心对齐,第一个元素与行首的距离与最后一个元素与行尾距离相同。
```
Flex({ justifyContent: FlexAlign.Center }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218579608](figures/zh-cn_image_0000001218579608.png)
- FlexAlign.End: 元素在主轴方向尾部对齐, 最后一个元素与行尾对齐,其他元素与后一个对齐。
```
Flex({ justifyContent: FlexAlign.End }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218739568](figures/zh-cn_image_0000001218739568.png)
- FlexAlign. SpaceBetween: ,Flex主轴方向均匀分配弹性元素,相邻元素之间距离相同。 第一个元素与行首对齐,最后一个元素与行尾对齐。
```
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263019461](figures/zh-cn_image_0000001263019461.png)
- FlexAlign. SpaceAround: Flex主轴方向均匀分配弹性元素,相邻元素之间距离相同。 第一个元素到行首的距离和最后一个元素到行尾的距离是相邻元素之间距离的一半。
```
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263339461](figures/zh-cn_image_0000001263339461.png)
- FlexAlign. SpaceEvenly: Flex主轴方向元素等间距布局, 相邻元素之间的间距、第一个元素与行首的间距、最后一个元素到行尾的间距都完全一样。
```
Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263139411](figures/zh-cn_image_0000001263139411.png)
### 交叉轴对齐
可以通过alignItems参数设置在交叉轴的对齐方式,可选值有:
- ItemAlign.Auto: 使用Flex容器中默认配置。
```
Flex({ alignItems: ItemAlign.Auto }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({width: '90%', height: 80})
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218419616](figures/zh-cn_image_0000001218419616.png)
- ItemAlign.Start: 交叉轴方向首部对齐。
```
Flex({ alignItems: ItemAlign.Start }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({width: '90%', height: 80})
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263259401](figures/zh-cn_image_0000001263259401.png)
- ItemAlign.Center: 交叉轴方向居中对齐。
```
Flex({ alignItems: ItemAlign.Center }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({width: '90%', height: 80})
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218259636](figures/zh-cn_image_0000001218259636.png)
- ItemAlign.End:交叉轴方向底部对齐。
```
Flex({ alignItems: ItemAlign.End }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({width: '90%', height: 80})
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218579610](figures/zh-cn_image_0000001218579610.png)
- ItemAlign. Stretch:交叉轴方向拉伸填充,在未设置尺寸时,拉伸到容器尺寸。
```
Flex({ alignItems: ItemAlign.Stretch }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({width: '90%', height: 80})
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001218739570](figures/zh-cn_image_0000001218739570.png)
- ItemAlign.Baseline:交叉轴方向文本基线对齐。
```
Flex({ alignItems: ItemAlign.Baseline }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({width: '90%', height: 80})
.padding(10)
.backgroundColor(0xAFEEEE)
```
![zh-cn_image_0000001263019463](figures/zh-cn_image_0000001263019463.png)
### 内容对齐
可以通过alignContent参数设置在换行组件的行在交叉轴剩余空间内的对齐方式,可选值有:
- FlexAlign.Start: 左对齐。
- FlexAlign.Center: 居中对齐。
- FlexAlign.End: 右对齐。
- FlexAlign. SpaceBetween: flex items之间的距离相等,与main start、main end两端对齐。
- FlexAlign. SpaceAround: flex items之间的距离相等,flex items与main start、main end之间的距离等于flex items之间距离的一半。
- FlexAlign. SpaceEvenly: flex items之间的距离相等,flex items与main start、main end之间的距离等于flex items之间的距离。
## 场景示例
可使用弹性布局做出子元素排列方式为水平方向排列,且子元素的总宽度超出父元素的宽度不换行,子元素在水平方向两端对齐,中间间距由除首尾外的子元素平分,竖直方向上子元素居中的效果。
```
@Entry
@Component
struct FlexExample {
build() {
Column() {
Column({ space: 5 }) {
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
Text('1').width('30%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('30%').height(50).backgroundColor(0xD2B48C)
Text('3').width('30%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
}.width('100%').margin({ top: 5 })
}.width('100%')
}
}
```
![zh-cn_image_0000001261605867](figures/zh-cn_image_0000001261605867.png)
# 栅格布局
栅格系统作为一种辅助布局的定位工具,在平面设计和网站设计都起到了很好的作用,对移动设备的界面设计有较好的借鉴作用。总结栅格系统对于移动设备的优势主要有:
1. 给布局提供一种可循的规律,解决多尺寸多设备的动态布局问题。
2. 给系统提供一种统一的定位标注,保证各模块各设备的布局一致性。
3. 给应用提供一种灵活的间距调整方法,满足特殊场景布局调整的可能性。
为实现栅格布局效果,声明式范式提供了GridContainer栅格容器组件,配合其子组件的通用属性useSizeType来实现栅格布局。
## 栅格系统
栅格系统有Columns、Margins、Gutters三个概念。
![zh-cn_image_0000001217236574](figures/zh-cn_image_0000001217236574.png)
1. Gutters:
用来控制元素与元素之间距离关系。可以根据设备的不同尺寸,定义不同的gutter值,作为栅格布局的统一规范。为了保证较好的视觉效果,通常gutter的取值不会大于margin的取值。
2. Margins:
离栅格容器边缘的距离。可以根据设备的不同尺寸,定义不同的margin值,作为栅格布局的统一规范。
3. Columns:
栅格布局的主要定位工具。根据设备的不同尺寸,把栅格容器分割成不同的列数,在保证margin和gutter符合规范的情况下,根据总Column的个数计算每个Column列的宽度。
### 系统栅格断点
系统根据不同水平宽度设备对应Columns的数量关系,形成了一套断点规则定义。
系统以设备的水平宽度的屏幕密度像素值作为断点依据,根据当前设备水平宽度所在的断点范围,定义了设备的宽度类型。系统的栅格断点范围、设备宽度类型及其描述,以及对应的默认总列数(columns),边距(gutter),间隔(gutter)定义如下:
<a id="grid_system_define">系统栅格定义</a>
| 设备水平宽度断点范围 | 设备宽度类型 | 描述 | columns | gutter | margin |
| -------- | -------- | -------- | -------- | -------- | -------- |
| 0&lt;水平宽度&lt;320vp | XS | 最小宽度类型设备。 | 2 | 12vp | 12vp |
| 320vp&lt;=水平宽度&lt;600vp | SM | 小宽度类型设备。 | 4 | 24vp | 24vp |
| 600vp&lt;=水平宽度&lt;840vp | MD | 中等宽度类型设备。 | 8 | 24vp | 32vp |
| 840&lt;=水平分辨率 | LG | 大宽度类型设备。 | 12 | 24vp | 48vp |
## 如何使用
首先创建栅格容器组件,定义栅格布局,然后给栅格容器内的组件设置不同设备宽度类型下的占用列数。
### 创建栅格容器
通过接口:GridContainer(options?: { columns?: number | 'auto', sizeType?: SizeType, gutter?: Length, margin?: Length})创建栅格容器,栅格容器内的所有子组件可以使用栅格布局。
可以通过参数定义栅格布局的总列数(columns),间隔(gutter),两侧边距(margin)。例如栅格容器总共分为6列,列于列间隔为10vp, 两侧边距为20vp:
```
GridContainer({ columns: 6, gutter: 10, margin: 20 }) {}
```
栅格容器不设置参数,或者sizeType设置为SizeType.Auto时使用默认的栅格系统定义(参考 [系统栅格定义](#grid_system_define)),如:
```
GridContainer() {}
```
上述例子中,默认在在小宽度类型设备(SizeType.SM)上,栅格容器被分为4列,列于列的间隔为24vp, 两侧边距是24vp。在中等宽度类型设备(SizeType.MD)上,栅格容器被分为8列,列于列的间隔为24vp,两侧边距是32vp。
也可以通过参数sizeType指定此栅格容器内的组件使用此设备宽度类型的栅格设置,如:
```
GridContainer({ sizeType: SizeType.SM) {
Row() {
Text('1')
.useSizeType({
xs: { span: 2},
sm: { span: 3, offset: 1 },
md: { span: 6, offset: 2 },
lg: { span: 8, offset: 2 },
})
}
}
```
上述例子中,不管在任何宽度类型的设备上, Text组件都使用SizeType.SM类型的栅格设置即占用3列,放置在第1列。
### 栅格容器内子组件的栅格设置
栅格容器中的组件使用通用属性useSizeType设置不同的设备宽度类型的占用列数和列偏移。其中span表示栅格容器组件占据columns的数量;offest表示列偏移量,指将组件放置在哪一个columns上。 如:
```
GridContainer() {
Row() {
Text('1')
.useSizeType({
xs: { span: 2},
sm: { span: 3, offset: 1 },
md: { span: 6, offset: 2 },
lg: { span: 8, offset: 2 },
})
}
}
```
其中sm: { span: 2, offset: 0 } 指在设备宽度类型为SM的设备上,Text组件占用3列,且放在栅格容器的第1列上。
## 场景示例
使用栅格布局可以灵活地在不同的设备宽度类型下呈现合适的效果,而不必书写大量的代码兼容不同宽度类型的设备。
```
@Entry
@Component
struct GridContainerExample {
build() {
Column({ space: 5 }) {
GridContainer({ columns: 6, sizeType: SizeType.Auto, gutter: 10, margin: 20 }) {
Row() {
Text('1')
.useSizeType({
xs: { span: 2, offset: 0 },
sm: { span: 2, offset: 0 },
md: { span: 1, offset: 0 },
lg: { span: 1, offset: 0 },
})
.height(100).backgroundColor(0x4682B4).textAlign(TextAlign.Center)
Text('2')
.useSizeType({
xs: { span: 2, offset: 2 },
sm: { span: 2, offset: 2 },
md: { span: 4, offset: 1 },
lg: { span: 4, offset: 1 },
})
.height(100).backgroundColor(0x46F2B4).textAlign(TextAlign.Center)
Text('3')
.useSizeType({
xs: { span: 2, offset: 4 },
sm: { span: 2, offset: 4 },
md: { span: 1, offset: 5 },
lg: { span: 1, offset: 5 },
})
.height(100).backgroundColor(0x46A2B4).textAlign(TextAlign.Center)
}
}.width('80%').backgroundColor('gray')
}.width('100%').margin({ top: 15 })
}
}
```
小宽度类型设备(SizeType.SM)运行效果:
![zh-cn_image_0000001218108718](figures/zh-cn_image_0000001218108718.png)
中等宽度类型设备(SizeType.MD)运行效果:
![zh-cn_image_0000001262748569](figures/zh-cn_image_0000001262748569.png)
# 媒体查询
媒体查询(Media Query)在移动设备上应用十分广泛,开发者经常需要根据设备的大致类型或者特定的特征和设备参数(例如屏幕分辨率)来修改应用的样式。为此媒体查询提供了如下功能:
1. 针对设备和应用的属性信息,可以设计出相匹配的布局样式。
2. 当屏幕发生动态改变时(比如分屏、横竖屏切换),应用页面布局同步更新。
## 如何使用
通过调用媒体查询接口,设置媒体查询条件和查询结果的回调函数,在对应的条件的回调函数里更改页面布局或者实现业务逻辑。
首先导入媒体查询模块,例如:
```
import mediaquery from '@ohos.mediaquery'
```
然后通过matchMediaSync接口设置媒体查询条件,并保存返回的条件监听句柄,例如:
```
listener = mediaquery.matchMediaSync('(orientation: landscape)')
```
最后通过上面保存的条件监听句柄listener去注册回调函数,在回调函数里更改页面布局或者实现业务逻辑,当匹配到媒体查询条件时会触发此回调函数,例如:
```
onPortrait(mediaQueryResult) {
if (mediaQueryResult.matches) {
// do something here
} else {
// do something here
}
}
listener.on('change', onPortrait)
```
## 媒体查询条件语法规则
```
[media-type] [and|not|only] [(media-feature)]
```
例如:
screen and (round-screen: true) // 当设备屏幕是圆形时条件成立
(max-height: 800) // 当高度小于800时条件成立
(height &lt;= 800) // 当高度小于800时条件成立
screen and (device-type: tv) or (resolution &lt; 2) // 包含多个媒体特征的多条件复杂语句查询
### 媒体类型(media-type)
| 类型 | 说明 |
| -------- | -------- |
| screen | 按屏幕相关参数进行媒体查询。 |
### 媒体逻辑操作(and|not|only)
媒体逻辑操作符:and、or、not、only用于构成复杂媒体查询,也可以通过comma(,)将其组合起来,详细解释说明如下表。
**表1** 媒体逻辑操作符
| 类型 | 说明 |
| -------- | -------- |
| and | 将多个媒体特征(Media&nbsp;Feature)以“与”的方式连接成一个媒体查询,只有当所有媒体特征都为true,查询条件成立。另外,它还可以将媒体类型和媒体功能结合起来。<br/>例如:screen&nbsp;and&nbsp;(device-type:&nbsp;wearable)&nbsp;and&nbsp;(max-height:&nbsp;600)&nbsp;表示当设备类型是智能穿戴同时应用的最大高度小于等于600个像素单位时成立。 |
| not | 取反媒体查询结果,媒体查询结果不成立时返回true,否则返回false。在媒体查询列表中应用not,则not仅取反应用它的媒体查询。<br/>例如:not&nbsp;screen&nbsp;and&nbsp;(min-height:&nbsp;50)&nbsp;and&nbsp;(max-height:&nbsp;600)&nbsp;表示当应用高度小于50个像素单位或者大于600个像素单位时成立。<br/>>&nbsp;![icon-note.gif](public_sys-resources/icon-note.gif)&nbsp;**说明:**<br/>>&nbsp;使用not运算符时必须指定媒体类型。 |
| only | 当整个表达式都匹配时,才会应用选择的样式,可以应用在防止某些较早的版本的浏览器上产生歧义的场景。一些较早版本的浏览器对于同时包含了媒体类型和媒体特征的语句会产生歧义,比如:<br/>screen&nbsp;and&nbsp;(min-height:&nbsp;50)<br/>老版本浏览器会将这句话理解成screen,从而导致仅仅匹配到媒体类型(screen),就应用了指定样式,使用only可以很好地规避这种情况。<br/>>&nbsp;![icon-note.gif](public_sys-resources/icon-note.gif)&nbsp;**说明:**<br/>>&nbsp;使用only时必须指定媒体类型。 |
| ,(comma) | 将多个媒体特征以“或”的方式连接成一个媒体查询,如果存在结果为true的媒体特征,则查询条件成立。其效果等同于or运算符。<br/>例如:screen&nbsp;and&nbsp;(min-height:&nbsp;1000),&nbsp;&nbsp;(round-screen:true)&nbsp;表示当应用高度大于等于1000个像素单位或者设备屏幕是圆形时,条件成立。 |
| or | 将多个媒体特征以“或”的方式连接成一个媒体查询,如果存在结果为true的媒体特征,则查询条件成立。<br/>例如:screen&nbsp;and&nbsp;(max-height:&nbsp;1000)&nbsp;or&nbsp;&nbsp;(round-screen:true)表示当应用高度小于等于1000个像素单位或者设备屏幕是圆形时,条件成立。 |
在MediaQuery Level 4中引入了范围查询,使其能够使用max-,min-的同时,也支持了&lt;=,&gt;=,&lt;&gt;操作符。
**表2** 媒体逻辑范围操作符
| 类型 | 说明 |
| -------- | -------- |
| &lt;= | 小于等于,例如:screen&nbsp;and&nbsp;(50&nbsp;&lt;=&nbsp;height)。 |
| &gt;= | 大于等于,例如:screen&nbsp;and&nbsp;(600&nbsp;&gt;=&nbsp;height)。 |
| &lt; | 小于,例如:screen&nbsp;and&nbsp;(50&nbsp;&lt;&nbsp;height)。 |
| &gt; | 大于,例如:screen&nbsp;and&nbsp;(600&nbsp;&gt;&nbsp;height)。 |
### 媒体特征(media-feature)
| 类型 | 说明 |
| -------- | -------- |
| height | 应用页面显示区域的高度。 |
| min-height | 应用页面显示区域的最小高度。 |
| max-height | 应用页面显示区域的最大高度。 |
| width | 应用页面显示区域的宽度。 |
| min-width | 应用页面显示区域的最小宽度。 |
| max-width | 应用页面显示区域的最大宽度。 |
| resolution | 设备的分辨率,支持dpi,dppx和dpcm单位。其中:<br/>-&nbsp;dpi表示每英寸中物理像素个数,1dpi≈0.39dpcm;<br/>-&nbsp;dpcm表示每厘米上的物理像素个数,1dpcm&nbsp;&nbsp;2.54dpi;<br/>-&nbsp;dppx表示每个px中的物理像素数(此单位按96px=1英寸为基准,与页面中的px单位计算方式不同),1dppx&nbsp;=&nbsp;96dpi。 |
| min-resolution | 设备的最小分辨率。 |
| max-resolution | 设备的最大分辨率。 |
| orientation | 屏幕的方向。<br/>可选值:<br/>-&nbsp;orientation:&nbsp;portrait(设备竖屏)<br/>-&nbsp;orientation:&nbsp;landscape(设备横屏) |
| device-height | 设备的高度。 |
| min-device-height | 设备的最小高度。 |
| max-device-height | 设备的最大高度。 |
| device-width | 设备的宽度。 |
| min-device-width | 设备的最小宽度。 |
| max-device-width | 设备的最大宽度。 |
| round-screen | 屏幕类型,圆形屏幕为true,&nbsp;非圆形屏幕为&nbsp;false。 |
| dark-mode | 系统为深色模式时为true,否则为false。 |
## 场景示例
通过使用媒体查询实现当屏幕发生横竖屏切换,给页面文本应用不同的内容和样式。
```
import mediaquery from '@ohos.mediaquery'
let portraitFunc = null
@Entry
@Component
struct MediaQueryExample {
@State color: string = '#DB7093'
@State text: string = 'Portrait'
@State fontSize: number = 24
listener = mediaquery.matchMediaSync('(orientation: landscape)')
onPortrait(mediaQueryResult) {
if (mediaQueryResult.matches) {
this.color = '#FFD700'
this.text = 'Landscape'
} else {
this.color = '#DB7093'
this.text = 'Portrait'
}
}
aboutToAppear() {
portraitFunc = this.onPortrait.bind(this) //bind current js instance
this.listener.on('change', portraitFunc)
}
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text(this.text).fontSize(50).fontColor(this.color)
}
.width('100%').height('100%')
}
}
```
横屏下文本内容为Landscape,颜色为#FFD700。</br>
![zh-cn_image_0000001262954829](figures/zh-cn_image_0000001262954829.png)
非横屏下文本内容为Portrait,颜色为#DB7093。</br>
![zh-cn_image_0000001263074739](figures/zh-cn_image_0000001263074739.png)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册