flutter-adaptive-ui

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Flutter Adaptive UI

Flutter 自适应UI

Overview

概述

Create Flutter applications that adapt gracefully to any screen size, platform, or input device. This skill provides comprehensive guidance for building responsive layouts that scale from mobile phones to large desktop displays while maintaining excellent user experience across touch, mouse, and keyboard interactions.
创建可优雅适配任意屏幕尺寸、平台或输入设备的Flutter应用。本技能提供了构建响应式布局的全面指导,这些布局可从手机屏幕扩展到大屏桌面显示器,同时在触摸、鼠标和键盘交互中保持极佳的用户体验。

Quick Reference

快速参考

Core Layout Rule: Constraints go down. Sizes go up. Parent sets position.
3-Step Adaptive Approach:
  1. Abstract - Extract common data from widgets
  2. Measure - Determine available space (MediaQuery/LayoutBuilder)
  3. Branch - Select appropriate UI based on breakpoints
Key Breakpoints:
  • Compact (Mobile): width < 600
  • Medium (Tablet): 600 <= width < 840
  • Expanded (Desktop): width >= 840
核心布局规则: 约束向下传递,尺寸向上返回,父组件设置位置。
三步自适应方法:
  1. 抽象 - 从组件中提取通用数据
  2. 测量 - 确定可用空间(MediaQuery/LayoutBuilder)
  3. 分支 - 根据断点选择合适的UI
关键断点:
  • 紧凑(移动设备):宽度 < 600
  • 中等(平板):600 ≤ 宽度 < 840
  • 扩展(桌面端):宽度 ≥ 840

Adaptive Workflow

自适应工作流

Follow the 3-step approach to make your app adaptive.
遵循三步法让你的应用具备自适应能力。

Step 1: Abstract

步骤1:抽象

Identify widgets that need adaptability and extract common data. Common patterns:
  • Navigation UI (switch between bottom bar and side rail)
  • Dialogs (fullscreen on mobile, modal on desktop)
  • Content lists (reflow from single to multi-column)
For navigation, create a shared
Destination
class with icon and label used by both
NavigationBar
and
NavigationRail
.
识别需要自适应的组件并提取通用数据。常见模式:
  • 导航UI(在底部导航栏和侧边导航栏之间切换)
  • 对话框(移动端全屏显示,桌面端模态显示)
  • 内容列表(从单列重新排版为多列)
对于导航功能,创建一个共享的
Destination
类,包含
NavigationBar
NavigationRail
都要用到的图标和标签。

Step 2: Measure

步骤2:测量

Choose the right measurement tool:
MediaQuery.sizeOf(context) - Use when you need app window size for top-level layout decisions
  • Returns entire app window dimensions
  • Better performance than
    MediaQuery.of()
    for size queries
  • Rebuilds widget when window size changes
LayoutBuilder - Use when you need constraints for specific widget subtree
  • Provides parent widget's constraints as
    BoxConstraints
  • Local sizing information, not global window size
  • Returns min/max width and height ranges
Example:
dart
// For app-level decisions
final width = MediaQuery.sizeOf(context).width;

// For widget-specific constraints
LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth < 600) {
      return MobileLayout();
    }
    return DesktopLayout();
  },
)
选择合适的测量工具:
MediaQuery.sizeOf(context) - 当你需要应用窗口尺寸来做顶层布局决策时使用
  • 返回整个应用窗口的尺寸
  • 在查询尺寸时,性能优于
    MediaQuery.of()
  • 窗口尺寸变化时会重建组件
LayoutBuilder - 当你需要特定组件子树的约束条件时使用
  • 提供父组件的
    BoxConstraints
    约束
  • 局部尺寸信息,而非全局窗口尺寸
  • 返回最小/最大宽度和高度范围
示例:
dart
// For app-level decisions
final width = MediaQuery.sizeOf(context).width;

// For widget-specific constraints
LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth < 600) {
      return MobileLayout();
    }
    return DesktopLayout();
  },
)

Step 3: Branch

步骤3:分支

Apply breakpoints to select appropriate UI. Don't base decisions on device type - use window size instead.
Example breakpoints (from Material guidelines):
dart
class AdaptiveLayout extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final width = MediaQuery.sizeOf(context).width;
    
    if (width >= 840) {
      return DesktopLayout();
    } else if (width >= 600) {
      return TabletLayout();
    }
    return MobileLayout();
  }
}
应用断点来选择合适的UI。不要基于设备类型做决策——而是使用窗口尺寸。
示例断点(来自Material设计规范):
dart
class AdaptiveLayout extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final width = MediaQuery.sizeOf(context).width;
    
    if (width >= 840) {
      return DesktopLayout();
    } else if (width >= 600) {
      return TabletLayout();
    }
    return MobileLayout();
  }
}

Layout Fundamentals

布局基础

Understanding Constraints

理解约束条件

Flutter layout follows one rule: Constraints go down. Sizes go up. Parent sets position.
Widgets receive constraints from parents, determine their size, then report size up to parent. Parents then position children.
Key limitation: Widgets can only decide size within parent constraints. They cannot know or control their own position.
For detailed examples and edge cases, see layout-constraints.md.
Flutter布局遵循一个规则:约束向下传递,尺寸向上返回,父组件设置位置。
组件从父组件接收约束,确定自身尺寸,然后将尺寸上报给父组件。父组件接着定位子组件。
关键限制:组件只能在父组件的约束范围内决定自身尺寸。它们无法知晓或控制自身的位置。
如需详细示例和边缘情况,请查看layout-constraints.md

Common Layout Patterns

常见布局模式

Row/Column
  • Row
    arranges children horizontally
  • Column
    arranges children vertically
  • Control alignment with
    mainAxisAlignment
    and
    crossAxisAlignment
  • Use
    Expanded
    to make children fill available space proportionally
Container
  • Add padding, margins, borders, background
  • Can constrain size with width/height
  • Without child/size, expands to fill constraints
Expanded/Flexible
  • Expanded
    forces child to use available space
  • Flexible
    allows child to use available space but can be smaller
  • Use
    flex
    parameter to control proportions
For complete widget documentation, see layout-basics.md and layout-common-widgets.md.
Row/Column
  • Row
    水平排列子组件
  • Column
    垂直排列子组件
  • 使用
    mainAxisAlignment
    crossAxisAlignment
    控制对齐方式
  • 使用
    Expanded
    让子组件按比例填充可用空间
Container
  • 添加内边距、外边距、边框、背景
  • 可通过width/height约束尺寸
  • 没有子组件/尺寸设置时,会扩展以填充约束空间
Expanded/Flexible
  • Expanded
    强制子组件使用可用空间
  • Flexible
    允许子组件使用可用空间,但也可以更小
  • 使用
    flex
    参数控制比例
如需完整的组件文档,请查看layout-basics.mdlayout-common-widgets.md

Best Practices

最佳实践

Design Principles

设计原则

Break down widgets
  • Create small, focused widgets instead of large complex ones
  • Improves performance with
    const
    widgets
  • Makes testing and refactoring easier
  • Share common components across different layouts
Design to platform strengths
  • Mobile: Focus on capturing content, quick interactions, location awareness
  • Tablet/Desktop: Focus on organization, manipulation, detailed work
  • Web: Leverage deep linking and easy sharing
Solve touch first
  • Start with great touch UI
  • Test frequently on real mobile devices
  • Layer on mouse/keyboard as accelerators, not replacements
拆分组件
  • 创建小巧、专注的组件,而非大型复杂组件
  • 使用
    const
    组件提升性能
  • 让测试和重构更简单
  • 在不同布局中共享通用组件
针对平台优势设计
  • 移动设备:专注于内容捕捉、快速交互、位置感知
  • 平板/桌面端:专注于内容整理、操作、精细化工作
  • 网页:利用深度链接和便捷分享
优先解决触摸交互
  • 从打造出色的触摸UI开始
  • 经常在真实移动设备上测试
  • 把鼠标/键盘操作作为加速方式,而非替代方案

Implementation Guidelines

实现指南

Never lock orientation
  • Support both portrait and landscape
  • Multi-window and foldable devices require flexibility
  • Locked screens can be accessibility issues
Avoid device type checks
  • Don't use
    Platform.isIOS
    ,
    Platform.isAndroid
    for layout decisions
  • Use window size instead
  • Device type ≠ window size (windows, split screens, PiP)
Use breakpoints, not orientation
  • Don't use
    OrientationBuilder
    for layout changes
  • Use
    MediaQuery.sizeOf
    or
    LayoutBuilder
    with breakpoints
  • Orientation doesn't indicate available space
Don't fill entire width
  • On large screens, avoid full-width content
  • Use multi-column layouts with
    GridView
    or flex patterns
  • Constrain content width for readability
Support multiple inputs
  • Implement keyboard navigation for accessibility
  • Support mouse hover effects
  • Handle focus properly for custom widgets
For complete best practices, see adaptive-best-practices.md.
永远不要锁定屏幕方向
  • 同时支持竖屏和横屏
  • 多窗口和折叠屏设备需要灵活性
  • 锁定屏幕可能会导致可访问性问题
避免检查设备类型
  • 不要使用
    Platform.isIOS
    Platform.isAndroid
    来做布局决策
  • 改用窗口尺寸
  • 设备类型 ≠ 窗口尺寸(多窗口、分屏、画中画)
使用断点,而非屏幕方向
  • 不要使用
    OrientationBuilder
    来更改布局
  • 使用
    MediaQuery.sizeOf
    LayoutBuilder
    配合断点
  • 屏幕方向并不代表可用空间
不要填满整个宽度
  • 在大屏上,避免内容占满整个宽度
  • 使用
    GridView
    或弹性模式实现多列布局
  • 限制内容宽度以提升可读性
支持多种输入方式
  • 实现键盘导航以提升可访问性
  • 支持鼠标悬停效果
  • 为自定义组件正确处理焦点
如需完整的最佳实践,请查看adaptive-best-practices.md

Capabilities and Policies

Capabilities与Policies

Separate what your code can do from what it should do.
Capabilities (what code can do)
  • API availability checks
  • OS-enforced restrictions
  • Hardware requirements (camera, GPS, etc.)
Policies (what code should do)
  • App store guidelines compliance
  • Design preferences
  • Platform-specific features
  • Feature flags
将代码做什么和应该做什么分开。
Capabilities(代码能做什么)
  • API可用性检查
  • 系统强制的限制
  • 硬件要求(摄像头、GPS等)
Policies(代码应该做什么)
  • 应用商店合规性
  • 设计偏好
  • 平台特定功能
  • 功能开关

Implementation Pattern

实现模式

dart
// Capability class
class Capability {
  bool hasCamera() {
    // Check if camera API is available
    return Platform.isAndroid || Platform.isIOS;
  }
}

// Policy class
class Policy {
  bool shouldShowCameraFeature() {
    // Business logic - maybe disabled by store policy
    return hasCamera() && !Platform.isIOS;
  }
}
Benefits:
  • Clear separation of concerns
  • Easy to test (mock Capability/Policy independently)
  • Simple to update when platforms evolve
  • Business logic doesn't depend on device detection
For detailed examples, see adaptive-capabilities.md and capability_policy_example.dart.
dart
// Capability class
class Capability {
  bool hasCamera() {
    // Check if camera API is available
    return Platform.isAndroid || Platform.isIOS;
  }
}

// Policy class
class Policy {
  bool shouldShowCameraFeature() {
    // Business logic - maybe disabled by store policy
    return hasCamera() && !Platform.isIOS;
  }
}
优势:
  • 关注点清晰分离
  • 易于测试(可独立模拟Capability/Policy)
  • 平台演进时更新简单
  • 业务逻辑不依赖设备检测
如需详细示例,请查看adaptive-capabilities.mdcapability_policy_example.dart

Examples

示例

Responsive Navigation

响应式导航

Switch between bottom navigation (small screens) and navigation rail (large screens):
dart
Widget build(BuildContext context) {
  final width = MediaQuery.sizeOf(context).width;
  
  return width >= 600 
    ? _buildNavigationRailLayout()
    : _buildBottomNavLayout();
}
Complete example: responsive_navigation.dart
在底部导航(小屏)和侧边导航栏(大屏)之间切换:
dart
Widget build(BuildContext context) {
  final width = MediaQuery.sizeOf(context).width;
  
  return width >= 600 
    ? _buildNavigationRailLayout()
    : _buildBottomNavLayout();
}
完整示例:responsive_navigation.dart

Adaptive Grid

自适应网格

Use
GridView.extent
with responsive maximum width:
dart
LayoutBuilder(
  builder: (context, constraints) {
    return GridView.extent(
      maxCrossAxisExtent: constraints.maxWidth < 600 ? 150 : 200,
      // ...
    );
  },
)
使用
GridView.extent
配合响应式最大宽度:
dart
LayoutBuilder(
  builder: (context, constraints) {
    return GridView.extent(
      maxCrossAxisExtent: constraints.maxWidth < 600 ? 150 : 200,
      // ...
    );
  },
)

Resources

资源

Reference Documentation

参考文档

  • layout-constraints.md - Complete guide to Flutter's constraint system with 29 examples
  • layout-basics.md - Core layout widgets and patterns
  • layout-common-widgets.md - Container, GridView, ListView, Stack, Card, ListTile
  • adaptive-workflow.md - Detailed 3-step adaptive design approach
  • adaptive-best-practices.md - Design and implementation guidelines
  • adaptive-capabilities.md - Capability/Policy pattern for platform behavior
  • layout-constraints.md - Flutter约束系统完整指南,包含29个示例
  • layout-basics.md - 核心布局组件和模式
  • layout-common-widgets.md - Container、GridView、ListView、Stack、Card、ListTile
  • adaptive-workflow.md - 详细的三步自适应设计方法
  • adaptive-best-practices.md - 设计与实现指南
  • adaptive-capabilities.md - 处理平台行为的Capability/Policy模式

Example Code

示例代码

  • responsive_navigation.dart - NavigationBar ↔ NavigationRail switching
  • capability_policy_example.dart - Capability/Policy class examples
  • responsive_navigation.dart - NavigationBar ↔ NavigationRail 切换
  • capability_policy_example.dart - Capability/Policy 类示例

Scripts

脚本

This skill currently has no executable scripts. All guidance is in reference documentation.
本技能目前没有可执行脚本,所有指导内容都在参考文档中。

Assets

资源文件

This skill includes complete Dart example files demonstrating:
  • Responsive navigation patterns
  • Capability and Policy implementation
  • Adaptive layout strategies
These assets can be copied directly into your Flutter project or adapted to your needs.
本技能包含完整的Dart示例文件,展示了:
  • 响应式导航模式
  • Capability和Policy的实现
  • 自适应布局策略
这些资源文件可直接复制到你的Flutter项目中,或根据需求进行调整。