NativeScript 样式主题 #

样式概述 #

NativeScript 使用 CSS 子集来为原生组件设置样式,让你可以用熟悉的 Web 技术美化应用。

text
┌─────────────────────────────────────────────────────────────┐
│                    样式系统                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  样式来源                                                    │
│  ├── 内联样式    style="color: red;"                        │
│  ├── CSS 类      class="title"                              │
│  ├── 全局样式    app.css                                    │
│  └── 主题样式    @nativescript/theme                        │
│                                                             │
│  样式特性                                                    │
│  ├── CSS 选择器                                            │
│  ├── 平台特定样式                                          │
│  ├── 状态样式                                              │
│  └── 响应式设计                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

CSS 基础 #

内联样式 #

xml
<Label text="Hello" style="color: red; font-size: 20; background-color: #f0f0f0;" />

CSS 类 #

xml
<Label text="Hello" class="title primary" />
css
.title {
    font-size: 24;
    font-weight: bold;
}

.primary {
    color: #3498db;
}

全局样式 #

app.css 中定义全局样式:

css
/* app.css */

/* 页面样式 */
Page {
    background-color: #f5f5f5;
}

/* ActionBar 样式 */
ActionBar {
    background-color: #3498db;
    color: white;
}

/* 通用类 */
.text-center {
    text-align: center;
}

.text-left {
    text-align: left;
}

.text-right {
    text-align: right;
}

/* 间距 */
.p-10 { padding: 10; }
.p-20 { padding: 20; }
.m-10 { margin: 10; }
.m-20 { margin: 20; }

/* 字体大小 */
.h1 { font-size: 32; }
.h2 { font-size: 24; }
.h3 { font-size: 20; }
.h4 { font-size: 18; }

支持的 CSS 属性 #

文本样式 #

属性 说明 示例
color 文本颜色 color: #333;
font-size 字体大小 font-size: 16;
font-weight 字体粗细 font-weight: bold;
font-family 字体名称 font-family: Arial;
font-style 字体样式 font-style: italic;
text-align 文本对齐 text-align: center;
text-decoration 文本装饰 text-decoration: underline;
text-transform 文本转换 text-transform: uppercase;
letter-spacing 字母间距 letter-spacing: 1;
line-height 行高 line-height: 1.5;

盒模型 #

属性 说明 示例
width 宽度 width: 100;
height 高度 height: 50;
margin 外边距 margin: 10;
padding 内边距 padding: 10;
border-width 边框宽度 border-width: 1;
border-color 边框颜色 border-color: #ccc;
border-radius 圆角 border-radius: 8;

背景 #

属性 说明 示例
background-color 背景颜色 background-color: #fff;
background-image 背景图片 background-image: url('~/bg.png');
background-repeat 背景重复 background-repeat: no-repeat;
background-position 背景位置 background-position: center;
background-size 背景大小 background-size: cover;

布局 #

属性 说明 示例
horizontal-align 水平对齐 horizontal-align: center;
vertical-align 垂直对齐 vertical-align: center;
visibility 可见性 visibility: visible;
opacity 透明度 opacity: 0.5;
z-index 层级 z-index: 10;

选择器 #

类型选择器 #

css
/* 选择所有 Label */
Label {
    color: #333;
}

/* 选择所有 Button */
Button {
    background-color: #3498db;
    color: white;
}

类选择器 #

css
.title {
    font-size: 24;
    font-weight: bold;
}

.primary {
    color: #3498db;
}

ID 选择器 #

css
#header {
    background-color: #3498db;
}
xml
<StackLayout id="header">
    <!-- ... -->
</StackLayout>

后代选择器 #

css
/* 选择 StackLayout 内的所有 Label */
StackLayout Label {
    color: #333;
}

/* 选择 ListView 内的 Label */
ListView Label {
    font-size: 14;
}

组合选择器 #

css
/* 同时选择多个类型 */
Label, Button {
    color: #333;
}

/* 选择同时有多个类的元素 */
.title.primary {
    font-size: 24;
    color: #3498db;
}

平台特定样式 #

使用平台类 #

css
/* Android 特定样式 */
.android .title {
    font-size: 20;
}

/* iOS 特定样式 */
.ios .title {
    font-size: 24;
}

使用平台属性 #

xml
<Label text="Hello" 
       android:style="color: red;" 
       ios:style="color: blue;" />

使用 @supports #

css
@supports (font-size: 16) {
    Label {
        font-size: 16;
    }
}

状态样式 #

交互状态 #

css
/* 按下状态 */
Button:active {
    background-color: #2980b9;
}

/* 禁用状态 */
Button:disabled {
    opacity: 0.5;
}

/* 聚焦状态 */
TextField:focus {
    border-color: #3498db;
}

状态类 #

xml
<Button text="Click" class="btn" tap="onTap" />
typescript
export function onTap(args) {
    const button = args.object as Button;
    button.className = 'btn pressed';
}
css
.btn {
    background-color: #3498db;
}

.btn.pressed {
    background-color: #2980b9;
}

主题系统 #

安装主题 #

bash
npm install @nativescript/theme

引入主题 #

css
/* app.css */
@import '@nativescript/theme/css/core.css';
@import '@nativescript/theme/css/default.css';

主题变量 #

css
/* 自定义主题变量 */
@import '@nativescript/theme/css/core.css';

:root {
    --primary: #3498db;
    --secondary: #95a5a6;
    --success: #2ecc71;
    --danger: #e74c3c;
    --warning: #f39c12;
    --info: #17a2b8;
    
    --background: #ffffff;
    --text-color: #333333;
    
    --font-size-base: 16;
    --border-radius: 8;
}

使用主题类 #

xml
<!-- 按钮 -->
<Button text="Primary" class="btn btn-primary" />
<Button text="Secondary" class="btn btn-secondary" />
<Button text="Outline" class="btn btn-outline" />

<!-- 文本 -->
<Label text="Title" class="text-primary h2" />
<Label text="Subtitle" class="text-secondary" />

<!-- 卡片 -->
<StackLayout class="card">
    <Label text="Card Title" class="card-title" />
    <Label text="Card content" class="card-text" />
</StackLayout>

暗黑模式 #

检测暗黑模式 #

typescript
import { Application, Frame } from '@nativescript/core';

// 获取当前模式
const isDarkMode = Application.systemAppearance() === 'dark';

// 监听模式变化
Application.on(Application.systemAppearanceChangedEvent, (args) => {
    console.log('System appearance:', args.newValue);
    updateTheme(args.newValue);
});

实现暗黑模式 #

css
/* app.css */

/* 浅色模式(默认) */
Page {
    background-color: #ffffff;
}

Label {
    color: #333333;
}

/* 暗黑模式 */
Page.dark {
    background-color: #1a1a1a;
}

Page.dark Label {
    color: #ffffff;
}

Page.dark ActionBar {
    background-color: #2d2d2d;
    color: #ffffff;
}
typescript
// 应用主题
function updateTheme(appearance: string) {
    const page = Frame.topmost().currentPage;
    
    if (appearance === 'dark') {
        page.className = 'dark';
    } else {
        page.className = '';
    }
}

SCSS 支持 #

配置 SCSS #

bash
npm install sass --save-dev

使用 SCSS #

scss
// _variables.scss
$primary: #3498db;
$secondary: #95a5a6;
$success: #2ecc71;
$danger: #e74c3c;

$font-size-base: 16;
$border-radius: 8;

// _mixins.scss
@mixin button-variant($background, $color) {
    background-color: $background;
    color: $color;
    border-radius: $border-radius;
    padding: 12 24;
    
    &:active {
        background-color: darken($background, 10%);
    }
}

// app.scss
@import 'variables';
@import 'mixins';

Page {
    background-color: #f5f5f5;
}

.btn-primary {
    @include button-variant($primary, white);
}

.btn-danger {
    @include button-variant($danger, white);
}

响应式设计 #

屏幕尺寸 #

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

const screenWidth = Screen.mainScreen.widthDIPs;
const screenHeight = Screen.mainScreen.heightDIPs;
const scale = Screen.mainScreen.scale;

响应式类 #

typescript
// 响应式工具类
export class Responsive {
    static isPhone(): boolean {
        return Screen.mainScreen.widthDIPs < 600;
    }
    
    static isTablet(): boolean {
        return Screen.mainScreen.widthDIPs >= 600;
    }
    
    static isLandscape(): boolean {
        return Screen.mainScreen.widthDIPs > Screen.mainScreen.heightDIPs;
    }
}

响应式样式 #

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

样式最佳实践 #

组织样式文件 #

text
app/
├── app.css                    # 全局样式
├── scss/
│   ├── _variables.scss        # 变量
│   ├── _mixins.scss           # 混合宏
│   ├── _buttons.scss          # 按钮样式
│   ├── _forms.scss            # 表单样式
│   ├── _typography.scss       # 排版
│   └── app.scss               # 主样式文件
└── pages/
    ├── home/
    │   └── home.css           # 页面特定样式
    └── detail/
        └── detail.css

命名规范 #

css
/* 使用 BEM 命名 */
.card {}
.card__title {}
.card__content {}
.card--featured {}

/* 使用语义化类名 */
.header {}
.footer {}
.sidebar {}
.main-content {}

/* 使用状态类 */
.is-active {}
.is-disabled {}
.is-loading {}

性能优化 #

css
/* 避免深层嵌套 */
/* 不推荐 */
StackLayout GridLayout StackLayout Label {
    color: #333;
}

/* 推荐 */
.nested-label {
    color: #333;
}

/* 避免通配符 */
/* 不推荐 */
* {
    margin: 0;
}

/* 推荐 */
Page, StackLayout, GridLayout {
    margin: 0;
}

常用样式模式 #

按钮样式 #

css
.btn {
    padding: 12 24;
    border-radius: 8;
    font-size: 16;
    font-weight: 500;
    min-width: 100;
}

.btn-primary {
    background-color: #3498db;
    color: white;
}

.btn-secondary {
    background-color: #95a5a6;
    color: white;
}

.btn-success {
    background-color: #2ecc71;
    color: white;
}

.btn-danger {
    background-color: #e74c3c;
    color: white;
}

.btn-outline {
    background-color: transparent;
    border-width: 2;
    border-color: #3498db;
    color: #3498db;
}

.btn-block {
    width: 100%;
}

.btn-sm {
    padding: 8 16;
    font-size: 14;
}

.btn-lg {
    padding: 16 32;
    font-size: 18;
}

卡片样式 #

css
.card {
    background-color: white;
    border-radius: 12;
    margin: 10;
    padding: 15;
    
    /* 阴影效果 */
    box-shadow: 0 2 4 rgba(0,0,0,0.1);
}

.card-header {
    font-size: 18;
    font-weight: bold;
    margin-bottom: 10;
}

.card-body {
    font-size: 14;
    color: #666;
}

.card-footer {
    margin-top: 15;
    horizontal-align: right;
}

表单样式 #

css
.form-group {
    margin-bottom: 15;
}

.form-label {
    font-size: 14;
    color: #666;
    margin-bottom: 5;
}

.form-control {
    border-width: 1;
    border-color: #ddd;
    border-radius: 8;
    padding: 12;
    font-size: 16;
}

.form-control:focus {
    border-color: #3498db;
}

.form-error {
    color: #e74c3c;
    font-size: 12;
    margin-top: 5;
}

下一步 #

现在你已经掌握了样式主题,接下来学习 插件系统,扩展应用的功能!

最后更新:2026-03-29