NativeScript 布局系统 #

布局概述 #

NativeScript 提供了多种布局容器,用于组织界面元素的排列方式。

text
┌─────────────────────────────────────────────────────────────┐
│                    布局容器                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  StackLayout        堆叠布局(垂直/水平)                    │
│  GridLayout         网格布局                                │
│  FlexboxLayout      弹性布局                                │
│  AbsoluteLayout     绝对定位                                │
│  DockLayout         停靠布局                                │
│  WrapLayout         自动换行                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

StackLayout #

最简单的布局容器,子元素按顺序堆叠。

垂直堆叠(默认) #

xml
<StackLayout orientation="vertical">
    <Label text="Item 1" height="50" backgroundColor="#3498db" />
    <Label text="Item 2" height="50" backgroundColor="#2ecc71" />
    <Label text="Item 3" height="50" backgroundColor="#e74c3c" />
</StackLayout>
text
┌─────────────────────────────────────┐
│            Item 1                   │
├─────────────────────────────────────┤
│            Item 2                   │
├─────────────────────────────────────┤
│            Item 3                   │
└─────────────────────────────────────┘

水平堆叠 #

xml
<StackLayout orientation="horizontal">
    <Label text="A" width="50" backgroundColor="#3498db" />
    <Label text="B" width="50" backgroundColor="#2ecc71" />
    <Label text="C" width="50" backgroundColor="#e74c3c" />
</StackLayout>
text
┌────────┬────────┬────────┐
│   A    │   B    │   C    │
└────────┴────────┴────────┘

常用属性 #

属性 类型 说明
orientation string 方向: vertical/horizontal

子元素间距 #

xml
<StackLayout class="p-10">
    <Label text="Item 1" class="m-b-10" />
    <Label text="Item 2" class="m-b-10" />
    <Label text="Item 3" />
</StackLayout>

GridLayout #

强大的网格布局,可以定义行和列。

基本用法 #

xml
<GridLayout rows="auto, *, auto" columns="*, *">
    <Label text="Header" row="0" col="0" colSpan="2" backgroundColor="#3498db" />
    <Label text="Left" row="1" col="0" backgroundColor="#2ecc71" />
    <Label text="Right" row="1" col="1" backgroundColor="#e74c3c" />
    <Label text="Footer" row="2" col="0" colSpan="2" backgroundColor="#9b59b6" />
</GridLayout>
text
┌─────────────────────────────────────┐
│             Header                  │
├──────────────────┬──────────────────┤
│      Left        │      Right       │
├──────────────────┴──────────────────┤
│             Footer                  │
└─────────────────────────────────────┘

行列定义 #

xml
<GridLayout rows="50, *, 2*, 100" columns="100, *, auto">
    <!-- 行定义说明 -->
    <!-- 50: 固定高度 50 -->
    <!-- *: 占用剩余空间的一份 -->
    <!-- 2*: 占用剩余空间的两份 -->
    <!-- 100: 固定高度 100 -->
    
    <!-- 列定义说明 -->
    <!-- 100: 固定宽度 100 -->
    <!-- *: 占用剩余空间 -->
    <!-- auto: 根据内容自动 -->
</GridLayout>

常用属性 #

属性 类型 说明
rows string 行定义
columns string 列定义
row number 子元素所在行
col number 子元素所在列
rowSpan number 跨行数
colSpan number 跨列数

实际应用 #

xml
<!-- 登录表单 -->
<GridLayout rows="auto, auto, auto, auto" columns="*, *">
    <Label text="Username:" row="0" col="0" colSpan="2" />
    <TextField hint="Enter username" row="1" col="0" colSpan="2" />
    
    <Label text="Password:" row="2" col="0" colSpan="2" />
    <TextField hint="Enter password" secure="true" row="3" col="0" colSpan="2" />
    
    <Button text="Login" row="4" col="0" />
    <Button text="Register" row="4" col="1" />
</GridLayout>

FlexboxLayout #

类似 CSS Flexbox 的布局容器。

基本用法 #

xml
<FlexboxLayout flexDirection="row" 
               flexWrap="wrap" 
               justifyContent="space-between" 
               alignItems="center">
    <Label text="1" width="30%" height="50" backgroundColor="#3498db" />
    <Label text="2" width="30%" height="50" backgroundColor="#2ecc71" />
    <Label text="3" width="30%" height="50" backgroundColor="#e74c3c" />
    <Label text="4" width="30%" height="50" backgroundColor="#9b59b6" />
</FlexboxLayout>

flexDirection #

xml
<!-- 水平方向 -->
<FlexboxLayout flexDirection="row">
    <Label text="A" />
    <Label text="B" />
</FlexboxLayout>

<!-- 水平反向 -->
<FlexboxLayout flexDirection="row-reverse">
    <Label text="A" />
    <Label text="B" />
</FlexboxLayout>

<!-- 垂直方向 -->
<FlexboxLayout flexDirection="column">
    <Label text="A" />
    <Label text="B" />
</FlexboxLayout>

<!-- 垂直反向 -->
<FlexboxLayout flexDirection="column-reverse">
    <Label text="A" />
    <Label text="B" />
</FlexboxLayout>

justifyContent #

xml
<!-- 起点对齐 -->
<FlexboxLayout flexDirection="row" justifyContent="flex-start">

<!-- 终点对齐 -->
<FlexboxLayout flexDirection="row" justifyContent="flex-end">

<!-- 居中对齐 -->
<FlexboxLayout flexDirection="row" justifyContent="center">

<!-- 两端对齐 -->
<FlexboxLayout flexDirection="row" justifyContent="space-between">

<!-- 等间距 -->
<FlexboxLayout flexDirection="row" justifyContent="space-around">

alignItems #

xml
<!-- 交叉轴起点对齐 -->
<FlexboxLayout alignItems="flex-start">

<!-- 交叉轴终点对齐 -->
<FlexboxLayout alignItems="flex-end">

<!-- 交叉轴居中对齐 -->
<FlexboxLayout alignItems="center">

<!-- 拉伸填充 -->
<FlexboxLayout alignItems="stretch">

子元素属性 #

xml
<FlexboxLayout flexDirection="row">
    <Label text="A" flexGrow="1" />
    <Label text="B" flexShrink="1" />
    <Label text="C" alignSelf="center" />
    <Label text="D" order="-1" />
</FlexboxLayout>
属性 说明
flexGrow 放大比例
flexShrink 缩小比例
flexWrapBefore 是否换行
alignSelf 自身对齐方式
order 排列顺序

AbsoluteLayout #

绝对定位布局,子元素使用 top/left/right/bottom 定位。

xml
<AbsoluteLayout>
    <Label text="Top Left" top="0" left="0" 
           width="100" height="50" backgroundColor="#3498db" />
    <Label text="Top Right" top="0" right="0" 
           width="100" height="50" backgroundColor="#2ecc71" />
    <Label text="Bottom Left" bottom="0" left="0" 
           width="100" height="50" backgroundColor="#e74c3c" />
    <Label text="Bottom Right" bottom="0" right="0" 
           width="100" height="50" backgroundColor="#9b59b6" />
    <Label text="Center" top="50%" left="50%" 
           width="100" height="50" backgroundColor="#f39c12" />
</AbsoluteLayout>
text
┌─────────────────────────────────────┐
│ Top Left              Top Right     │
│                                     │
│               Center                │
│                                     │
│ Bottom Left         Bottom Right    │
└─────────────────────────────────────┘

应用场景 #

xml
<!-- 图片上的标签 -->
<AbsoluteLayout>
    <Image src="~/assets/photo.jpg" 
           width="100%" height="200" stretch="aspectFill" />
    <Label text="Featured" 
           top="10" left="10" 
           class="badge" />
</AbsoluteLayout>

DockLayout #

停靠布局,子元素可以停靠在四个边缘。

xml
<DockLayout stretchLastChild="true">
    <Label text="Top" dock="top" height="50" backgroundColor="#3498db" />
    <Label text="Bottom" dock="bottom" height="50" backgroundColor="#2ecc71" />
    <Label text="Left" dock="left" width="100" backgroundColor="#e74c3c" />
    <Label text="Right" dock="right" width="100" backgroundColor="#9b59b6" />
    <Label text="Center" backgroundColor="#f39c12" />
</DockLayout>
text
┌─────────────────────────────────────┐
│              Top                    │
├─────────────────────────────────────┤
│        │                 │          │
│  Left  │     Center      │  Right   │
│        │                 │          │
├─────────────────────────────────────┤
│             Bottom                  │
└─────────────────────────────────────┘

应用场景 #

xml
<!-- 应用框架 -->
<DockLayout>
    <ActionBar dock="top" title="My App" />
    <StackLayout dock="bottom" class="footer">
        <Label text="Footer" />
    </StackLayout>
    <GridLayout>
        <!-- 主内容 -->
    </GridLayout>
</DockLayout>

WrapLayout #

自动换行布局。

xml
<WrapLayout orientation="horizontal" itemWidth="100" itemHeight="100">
    <Label text="1" backgroundColor="#3498db" />
    <Label text="2" backgroundColor="#2ecc71" />
    <Label text="3" backgroundColor="#e74c3c" />
    <Label text="4" backgroundColor="#9b59b6" />
    <Label text="5" backgroundColor="#f39c12" />
    <Label text="6" backgroundColor="#1abc9c" />
</WrapLayout>
text
┌────────┬────────┬────────┐
│   1    │   2    │   3    │
├────────┼────────┼────────┤
│   4    │   5    │   6    │
└────────┴────────┴────────┘

应用场景 #

xml
<!-- 标签云 -->
<WrapLayout class="tag-cloud">
    <Label *ngFor="let tag of tags" 
           [text]="tag" 
           class="tag" />
</WrapLayout>

布局嵌套 #

复杂布局示例 #

xml
<GridLayout rows="auto, *, auto">
    <!-- Header -->
    <StackLayout row="0" class="header">
        <Label text="My App" class="title" />
    </StackLayout>
    
    <!-- Content -->
    <ScrollView row="1">
        <FlexboxLayout flexDirection="column">
            <!-- 用户信息 -->
            <GridLayout columns="auto, *" class="user-info">
                <Image col="0" src="{{ avatar }}" />
                <StackLayout col="1">
                    <Label text="{{ name }}" />
                    <Label text="{{ email }}" />
                </StackLayout>
            </GridLayout>
            
            <!-- 内容列表 -->
            <StackLayout>
                <Label *ngFor="let item of items" [text]="item.title" />
            </StackLayout>
        </FlexboxLayout>
    </ScrollView>
    
    <!-- Footer -->
    <StackLayout row="2" class="footer">
        <Button text="Action" tap="onAction" />
    </StackLayout>
</GridLayout>

响应式布局 #

使用百分比 #

xml
<GridLayout columns="30%, 70%">
    <Label text="Sidebar" col="0" />
    <Label text="Content" col="1" />
</GridLayout>

使用星号比例 #

xml
<GridLayout columns="1*, 2*">
    <Label text="1/3" col="0" />
    <Label text="2/3" col="1" />
</GridLayout>

平台适配 #

xml
<GridLayout columns="{{ isTablet ? '200, *' : '*' }}">
    <StackLayout col="0" visibility="{{ isTablet ? 'visible' : 'collapsed' }}">
        <!-- 侧边栏(仅平板显示) -->
    </StackLayout>
    <GridLayout col="{{ isTablet ? 1 : 0 }}">
        <!-- 主内容 -->
    </GridLayout>
</GridLayout>

屏幕尺寸检测 #

typescript
import { Screen } from '@nativescript/core';

const screenWidth = Screen.mainScreen.widthDIPs;
const screenHeight = Screen.mainScreen.heightDIPs;
const isTablet = screenWidth >= 600;

布局性能 #

避免过度嵌套 #

xml
<!-- 不推荐 -->
<StackLayout>
    <StackLayout>
        <StackLayout>
            <Label text="Content" />
        </StackLayout>
    </StackLayout>
</StackLayout>

<!-- 推荐 -->
<GridLayout>
    <Label text="Content" />
</GridLayout>

使用 GridLayout 替代嵌套 #

xml
<!-- 不推荐 -->
<StackLayout orientation="horizontal">
    <StackLayout>
        <Label text="Title" />
        <Label text="Subtitle" />
    </StackLayout>
    <Button text="Action" />
</StackLayout>

<!-- 推荐 -->
<GridLayout columns="*, auto" rows="auto, auto">
    <Label text="Title" row="0" col="0" />
    <Label text="Subtitle" row="1" col="0" />
    <Button text="Action" row="0" col="1" rowSpan="2" />
</GridLayout>

常见布局模式 #

卡片布局 #

xml
<GridLayout rows="auto, auto, auto" class="card">
    <Image src="{{ image }}" row="0" height="150" stretch="aspectFill" />
    <StackLayout row="1" class="card-content">
        <Label text="{{ title }}" class="title" />
        <Label text="{{ description }}" textWrap="true" />
    </StackLayout>
    <StackLayout row="2" class="card-actions" orientation="horizontal">
        <Button text="Like" />
        <Button text="Share" />
    </StackLayout>
</GridLayout>

表单布局 #

xml
<StackLayout class="form">
    <GridLayout columns="100, *" rows="auto">
        <Label text="Name:" col="0" verticalAlignment="center" />
        <TextField col="1" hint="Enter name" />
    </GridLayout>
    
    <GridLayout columns="100, *" rows="auto">
        <Label text="Email:" col="0" verticalAlignment="center" />
        <TextField col="1" hint="Enter email" keyboardType="email" />
    </GridLayout>
    
    <Button text="Submit" class="btn-primary" />
</StackLayout>

列表项布局 #

xml
<GridLayout columns="auto, *, auto" rows="auto, auto" class="list-item">
    <Image src="{{ avatar }}" 
           col="0" row="0" rowSpan="2" 
           width="50" height="50" borderRadius="25" />
    <Label text="{{ name }}" col="1" row="0" class="name" />
    <Label text="{{ message }}" col="1" row="1" class="message" />
    <Label text="{{ time }}" col="2" row="0" class="time" />
</GridLayout>

下一步 #

现在你已经掌握了布局系统,接下来学习 导航路由,了解页面导航的实现方式!

最后更新:2026-03-29