• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 线性布局
2
3线性布局(LinearLayout)是开发中最常用的布局。线性布局的子组件在线性方向上(水平方向和垂直方向)依次排列。
4
5通过线性容器[Row](../reference/arkui-ts/ts-container-row.md)和[Column](../reference/arkui-ts/ts-container-column.md)实现线性布局。Column容器内子组件按照垂直方向排列,Row组件中,子组件按照水平方向排列。
6
7## 线性布局的排列
8
9线性布局的排列方向由所选容器组件决定。根据不同的排列方向,选择使用Row或Column容器创建线性布局,通过调整space,alignItems,justifyContent属性调整子组件的间距,水平垂直方向的对齐方式。
101. 通过space参数设置主轴(排列方向)上子组件的间距。达到各子组件在排列方向上的等间距效果。
112. 通过alignItems属性设置子组件在交叉轴(排列方向的垂直方向)的对齐方式。且在各类尺寸屏幕中,表现一致。其中,交叉轴为垂直方向时,取值为[VerticalAlign类型](../reference/arkui-ts/ts-appendix-enums.md#verticalalign),水平方向取值为[HorizontalAlign类型](../reference/arkui-ts/ts-appendix-enums.md#horizontalalign)。
123. 通过justifyContent属性设置子组件在主轴(排列方向)上的对齐方式。实现布局的自适应均分能力。取值为[FlexAlign类型](../reference/arkui-ts/ts-appendix-enums.md#flexalign)。
13
14具体使用以及效果如下表所示:
15
16|属性名|描述|Row效果图|Column效果图|
17|------|---------------------------|----------------------------|---------------------------|
18|space |- 横向布局中各子组件的在水平方向的间距<br> - 纵向布局中个子组件垂直方向间距|   ![](figures/rowspace.png)      |   ![](figures/columnspace.png) |
19|alignItems |容器排列方向的垂直方向上,子组件在父容器中的对齐方式|![](figures/rowalign.png)            |![](figures/columnalign.png)|
20|justifyContent |容器排列方向上,子组件在父容器中的对齐方式 |![](figures/rowjustify.png)            |![](figures/columnjustify.png)|
21
22## 自适应拉伸
23
24在线性布局下,常用空白填充组件[Blank](../reference/arkui-ts/ts-basic-components-blank.md),在容器主轴方向自动填充空白空间,达到自适应拉伸效果。
25
26```ts
27@Entry
28@Component
29struct BlankExample {
30  build() {
31    Column() {
32      Row() {
33        Text('Bluetooth').fontSize(18)
34        Blank()
35        Toggle({ type: ToggleType.Switch, isOn: true })
36      }.backgroundColor(0xFFFFFF).borderRadius(15).padding({ left: 12 }).width('100%')
37    }.backgroundColor(0xEFEFEF).padding(20).width('100%')
38  }
39}
40```
41
42![](figures/blank.gif)
43
44## 自适应缩放
45
46自适应缩放是指在各种不同大小设备中,子组件按照预设的比例,尺寸随容器尺寸的变化而变化。在线性布局中有下列方法实现:
47
481. 父容器尺寸确定时,设置了layoutWeight属性的子组件与兄弟元素占主轴尺寸按照权重进行分配,忽略元素本身尺寸设置,在任意尺寸设备下,自适应占满剩余空间。
49
50    ```ts
51    @Entry
52    @Component
53    struct layoutWeightExample {
54      build() {
55        Column() {
56          Text('1:2:3').width('100%')
57          Row() {
58            Column() {
59              Text('layoutWeight(1)')
60                .textAlign(TextAlign.Center)
61            }.layoutWeight(2).backgroundColor(0xffd306).height('100%')
62
63            Column() {
64              Text('layoutWeight(2)')
65                .textAlign(TextAlign.Center)
66            }.layoutWeight(4).backgroundColor(0xffed97).height('100%')
67
68            Column() {
69              Text('layoutWeight(6)')
70                .textAlign(TextAlign.Center)
71            }.layoutWeight(6).backgroundColor(0xffd306).height('100%')
72
73          }.backgroundColor(0xffd306).height('30%')
74
75          Text('2:5:3').width('100%')
76          Row() {
77            Column() {
78              Text('layoutWeight(2)')
79                .textAlign(TextAlign.Center)
80            }.layoutWeight(2).backgroundColor(0xffd306).height('100%')
81
82            Column() {
83              Text('layoutWeight(5)')
84                .textAlign(TextAlign.Center)
85            }.layoutWeight(5).backgroundColor(0xffed97).height('100%')
86
87            Column() {
88              Text('layoutWeight(3)')
89                .textAlign(TextAlign.Center)
90            }.layoutWeight(3).backgroundColor(0xffd306).height('100%')
91          }.backgroundColor(0xffd306).height('30%')
92        }
93      }
94    }
95    ```
96
97   ![](figures/layoutWeight.gif)
98
99
1003. 父容器尺寸确定时,使用百分比设置子组件以及兄弟组件的width宽度,可以保证各自元素在任意尺寸下的自适应占比。
101
102    ```ts
103    @Entry
104    @Component
105    struct WidthExample {
106      build() {
107        Column() {
108          Row() {
109            Column() {
110              Text('left width 20%')
111                .textAlign(TextAlign.Center)
112            }.width('20%').backgroundColor(0xffd306).height('100%')
113
114            Column() {
115              Text('center width 50%')
116                .textAlign(TextAlign.Center)
117            }.width('50%').backgroundColor(0xffed97).height('100%')
118
119            Column() {
120              Text('right width 30%')
121                .textAlign(TextAlign.Center)
122            }.width('30%').backgroundColor(0xffd306).height('100%')
123          }.backgroundColor(0xffd306).height('30%')
124        }
125      }
126    }
127    ```
128
129   ![](figures/width.gif)
130
131   上例中,在任意大小的设备中,子组件的宽度占比固定。
132
133## 定位能力
134- 相对定位
135
136  使用组件的[offset属性](../reference/arkui-ts/ts-universal-attributes-location.md)可以实现相对定位,设置元素相对于自身的偏移量。设置该属性,不影响父容器布局,仅在绘制时进行位置调整。使用线性布局和offset可以实现大部分布局的开发。
137
138  ```ts
139  @Entry
140  @Component
141  struct OffsetExample {
142    @Styles eleStyle() {
143      .size({ width: 120, height: '50' })
144      .backgroundColor(0xbbb2cb)
145      .border({ width: 1 })
146    }
147
148    build() {
149      Column({ space: 20 }) {
150        Row() {
151          Text('1').size({ width: '15%', height: '50' }).backgroundColor(0xdeb887).border({ width: 1 }).fontSize(16)
152          Text('2  offset(15, 30)')
153            .eleStyle()
154            .fontSize(16)
155            .align(Alignment.Start)
156            .offset({ x: 15, y: 30 })
157          Text('3').size({ width: '15%', height: '50' }).backgroundColor(0xdeb887).border({ width: 1 }).fontSize(16)
158          Text('4 offset(-10%, 20%)')
159            .eleStyle()
160            .fontSize(16)
161            .offset({ x: '-5%', y: '20%' })
162        }.width('90%').height(150).border({ width: 1, style: BorderStyle.Dashed })
163      }
164      .width('100%')
165      .margin({ top: 25 })
166    }
167  }
168   ```
169
170  ![](figures/offset.gif)
171
172
173- 绝对定位
174
175  线性布局中可以使用组件的[positon属性](../reference/arkui-ts/ts-universal-attributes-location.md)实现绝对布局(AbsoluteLayout),设置元素左上角相对于父容器左上角偏移位置。对于不同尺寸的设备,使用绝对定位的适应性会比较差,在屏幕的适配上有缺陷。
176
177  ```ts
178  @Entry
179  @Component
180  struct PositionExample {
181    @Styles eleStyle(){
182      .backgroundColor(0xbbb2cb)
183      .border({ width: 1 })
184      .size({ width: 120, height: 50 })
185    }
186
187    build() {
188      Column({ space: 20 }) {
189        // 设置子组件左上角相对于父组件左上角的偏移位置
190        Row() {
191          Text('position(30, 10)')
192            .eleStyle()
193            .fontSize(16)
194            .position({ x: 10, y: 10 })
195
196          Text('position(50%, 70%)')
197            .eleStyle()
198            .fontSize(16)
199            .position({ x: '50%', y: '70%' })
200
201          Text('position(10%, 90%)')
202            .eleStyle()
203            .fontSize(16)
204            .position({ x: '10%', y: '80%' })
205        }.width('90%').height('100%').border({ width: 1, style: BorderStyle.Dashed })
206      }
207      .width('90%').margin(25)
208    }
209  }
210  ```
211
212  ![](figures/position.gif)
213
214
215## 自适应延伸
216
217自适应延伸是在不同尺寸设备下,当页面显示内容个数不一并延伸到屏幕外时,可通过滚动条拖动展示。适用于线性布局中内容无法一屏展示的场景。常见以下两类实现方法。
218
219
220- List组件
221
222  List子项过多一屏放不下时,未展示的子项通过滚动条拖动显示。通过scrollBar属性设置滚动条的常驻状态,edgeEffect属性设置拖动到极限的回弹效果。
223
224
225  纵向List:
226  ```ts
227    @Entry
228    @Component
229    struct ListExample1 {
230      @State arr: string[] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"]
231      @State alignListItem: ListItemAlign = ListItemAlign.Start
232
233      build() {
234        Column() {
235          List({ space: 20, initialIndex: 0 }) {
236            ForEach(this.arr, (item) => {
237              ListItem() {
238                Text('' + item)
239                  .width('100%')
240                  .height(100)
241                  .fontSize(16)
242                  .textAlign(TextAlign.Center)
243                  .borderRadius(10)
244                  .backgroundColor(0xFFFFFF)
245              }
246              .border({ width: 2, color: Color.Green })
247            }, item => item)
248          }
249          .border({ width: 2, color: Color.Red, style: BorderStyle.Dashed })
250          .scrollBar(BarState.On) // 滚动条常驻
251          .edgeEffect(EdgeEffect.Spring) // 滚动到边缘再拖动回弹效果
252
253        }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
254      }
255    }
256  ```
257
258  ![](figures/listcolumn.gif)
259
260
261  横向List:
262
263  ```ts
264    @Entry
265    @Component
266    struct ListExample2 {
267      @State arr: string[] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"]
268      @State alignListItem: ListItemAlign = ListItemAlign.Start
269
270      build() {
271        Column() {
272          List({ space: 20, initialIndex: 0 }) {
273            ForEach(this.arr, (item) => {
274              ListItem() {
275                Text('' + item)
276                  .height('100%')
277                  .width(100)
278                  .fontSize(16)
279                  .textAlign(TextAlign.Center)
280                  .borderRadius(10)
281                  .backgroundColor(0xFFFFFF)
282              }
283              .border({ width: 2, color: Color.Green })
284            }, item => item)
285          }
286          .border({ width: 2, color: Color.Red, style: BorderStyle.Dashed })
287          .scrollBar(BarState.On) // 滚动条常驻
288          .edgeEffect(EdgeEffect.Spring) // 滚动到边缘再拖动回弹效果
289          .listDirection(Axis.Horizontal)  // 列表水平排列
290        }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
291      }
292    }
293  ```
294
295  ![](figures/listrow.gif)
296
297- Scroll组件
298
299  线性布局中,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。在Column或者Row外层包裹一个可滚动的容器组件Scroll实现。
300
301  纵向Scroll:
302
303  ```ts
304  @Entry
305  @Component
306  struct ScrollExample {
307    scroller: Scroller = new Scroller();
308    private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
309
310    build() {
311      Scroll(this.scroller) {
312        Column() {
313          ForEach(this.arr, (item) => {
314            Text(item.toString())
315              .width('90%')
316              .height(150)
317              .backgroundColor(0xFFFFFF)
318              .borderRadius(15)
319              .fontSize(16)
320              .textAlign(TextAlign.Center)
321              .margin({ top: 10 })
322          }, item => item)
323        }.width('100%')
324      }
325      .backgroundColor(0xDCDCDC)
326      .scrollable(ScrollDirection.Vertical) // 滚动方向纵向
327      .scrollBar(BarState.On) // 滚动条常驻显示
328      .scrollBarColor(Color.Gray) // 滚动条颜色
329      .scrollBarWidth(30) // 滚动条宽度
330      .edgeEffect(EdgeEffect.Spring) // 滚动到边沿后回弹
331    }
332  }
333  ```
334
335  ![](figures/scrollcolumn.gif)
336
337  横向Scroll:
338
339  ```ts
340  @Entry
341  @Component
342  struct ScrollExample {
343    scroller: Scroller = new Scroller();
344    private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
345
346    build() {
347      Scroll(this.scroller) {
348        Row() {
349          ForEach(this.arr, (item) => {
350            Text(item.toString())
351              .height('90%')
352              .width(150)
353              .backgroundColor(0xFFFFFF)
354              .borderRadius(15)
355              .fontSize(16)
356              .textAlign(TextAlign.Center)
357              .margin({ left: 10 })
358          }, item => item)
359        }.height('100%')
360      }
361      .backgroundColor(0xDCDCDC)
362      .scrollable(ScrollDirection.Horizontal) // 滚动方向横向
363      .scrollBar(BarState.On) // 滚动条常驻显示
364      .scrollBarColor(Color.Gray) // 滚动条颜色
365      .scrollBarWidth(30) // 滚动条宽度
366      .edgeEffect(EdgeEffect.Spring) // 滚动到边沿后回弹
367    }
368  }
369  ```
370  ![](figures/scrollrow.gif)
371