flutter-adaptive-ui by madteacher/mad-agents-skills
npx skills add https://github.com/madteacher/mad-agents-skills --skill flutter-adaptive-ui创建能够优雅适应任何屏幕尺寸、平台或输入设备的 Flutter 应用程序。此技能为构建响应式布局提供全面指导,布局可从手机扩展到大型桌面显示器,同时在触摸、鼠标和键盘交互中保持出色的用户体验。
核心布局规则: 约束向下传递。尺寸向上报告。父组件设置位置。
三步自适应方法:
关键断点:
遵循三步方法使您的应用程序具有自适应性。
识别需要自适应性的组件并提取通用数据。常见模式:
对于导航,创建一个共享的 Destination 类,包含 NavigationBar 和 NavigationRail 都使用的图标和标签。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
选择合适的测量工具:
MediaQuery.sizeOf(context) - 当您需要应用窗口尺寸来做顶层布局决策时使用
MediaQuery.of()LayoutBuilder - 当您需要特定组件子树的约束时使用
BoxConstraints示例:
// 用于应用级决策
final width = MediaQuery.sizeOf(context).width;
// 用于组件特定约束
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
return MobileLayout();
}
return DesktopLayout();
},
)
应用断点以选择合适的 UI。不要基于设备类型做决策 - 应使用窗口尺寸。
示例断点(来自 Material 指南):
class AdaptiveLayout extends StatelessWidget {
@override
Widget build(BuildContext context) {
final width = MediaQuery.sizeOf(context).width;
if (width >= 840) {
return DesktopLayout();
} else if (width >= 600) {
return TabletLayout();
}
return MobileLayout();
}
}
Flutter 布局遵循一个规则:约束向下传递。尺寸向上报告。父组件设置位置。
组件从父组件接收约束,确定自己的尺寸,然后将尺寸报告给父组件。父组件随后定位子组件。
关键限制:组件只能在父组件约束范围内决定尺寸。它们无法知道或控制自己的位置。
有关详细示例和边界情况,请参阅 layout-constraints.md。
Row/Column
Row 水平排列子组件Column 垂直排列子组件mainAxisAlignment 和 crossAxisAlignment 控制对齐方式Expanded 使子组件按比例填充可用空间Container
Expanded/Flexible
Expanded 强制子组件使用可用空间Flexible 允许子组件使用可用空间但可以更小flex 参数控制比例完整的组件文档,请参阅 layout-basics.md 和 layout-common-widgets.md。
分解组件
const 组件提高性能针对平台优势设计
优先解决触摸交互
切勿锁定方向
避免设备类型检查
Platform.isIOS、Platform.isAndroid 来做布局决策使用断点,而非方向
OrientationBuilder 来改变布局MediaQuery.sizeOf 或 LayoutBuilder不要填满整个宽度
GridView 或弹性模式的多列布局支持多种输入方式
完整的最佳实践,请参阅 adaptive-best-practices.md。
将代码能够做什么与应该做什么分开。
能力(代码能够做什么)
策略(代码应该做什么)
// 能力类
class Capability {
bool hasCamera() {
// 检查摄像头 API 是否可用
return Platform.isAndroid || Platform.isIOS;
}
}
// 策略类
class Policy {
bool shouldShowCameraFeature() {
// 业务逻辑 - 可能因商店策略而禁用
return hasCamera() && !Platform.isIOS;
}
}
好处:
在底部导航(小屏幕)和导航导轨(大屏幕)之间切换:
Widget build(BuildContext context) {
final width = MediaQuery.sizeOf(context).width;
return width >= 600
? _buildNavigationRailLayout()
: _buildBottomNavLayout();
}
使用带有响应式最大宽度的 GridView.extent:
LayoutBuilder(
builder: (context, constraints) {
return GridView.extent(
maxCrossAxisExtent: constraints.maxWidth < 600 ? 150 : 200,
// ...
);
},
)
此技能目前没有可执行脚本。所有指导都在参考文档中。
此技能包含完整的 Dart 示例文件,演示:
这些资源文件可以直接复制到您的 Flutter 项目中,或根据您的需求进行调整。
每周安装量
1.3K
仓库
GitHub 星标数
87
首次出现
2026 年 1 月 22 日
安全审计
安装于
codex1.1K
opencode1.1K
gemini-cli1.0K
github-copilot998
kimi-cli900
amp888
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.
Core Layout Rule: Constraints go down. Sizes go up. Parent sets position.
3-Step Adaptive Approach:
Key Breakpoints:
Follow the 3-step approach to make your app adaptive.
Identify widgets that need adaptability and extract common data. Common patterns:
For navigation, create a shared Destination class with icon and label used by both NavigationBar and NavigationRail.
Choose the right measurement tool:
MediaQuery.sizeOf(context) - Use when you need app window size for top-level layout decisions
MediaQuery.of() for size queriesLayoutBuilder - Use when you need constraints for specific widget subtree
BoxConstraintsExample:
// 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();
},
)
Apply breakpoints to select appropriate UI. Don't base decisions on device type - use window size instead.
Example breakpoints (from Material guidelines):
class AdaptiveLayout extends StatelessWidget {
@override
Widget build(BuildContext context) {
final width = MediaQuery.sizeOf(context).width;
if (width >= 840) {
return DesktopLayout();
} else if (width >= 600) {
return TabletLayout();
}
return MobileLayout();
}
}
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.
Row/Column
Row arranges children horizontallyColumn arranges children verticallymainAxisAlignment and crossAxisAlignmentExpanded to make children fill available space proportionallyContainer
Expanded/Flexible
Expanded forces child to use available spaceFlexible allows child to use available space but can be smallerflex parameter to control proportionsFor complete widget documentation, see layout-basics.md and layout-common-widgets.md.
Break down widgets
const widgetsDesign to platform strengths
Solve touch first
Never lock orientation
Avoid device type checks
Platform.isIOS, Platform.isAndroid for layout decisionsUse breakpoints, not orientation
OrientationBuilder for layout changesMediaQuery.sizeOf or LayoutBuilder with breakpointsDon't fill entire width
GridView or flex patternsSupport multiple inputs
For complete best practices, see adaptive-best-practices.md.
Separate what your code can do from what it should do.
Capabilities (what code can do)
Policies (what code should do)
// 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:
For detailed examples, see adaptive-capabilities.md and capability_policy_example.dart.
Switch between bottom navigation (small screens) and navigation rail (large screens):
Widget build(BuildContext context) {
final width = MediaQuery.sizeOf(context).width;
return width >= 600
? _buildNavigationRailLayout()
: _buildBottomNavLayout();
}
Complete example: responsive_navigation.dart
Use GridView.extent with responsive maximum width:
LayoutBuilder(
builder: (context, constraints) {
return GridView.extent(
maxCrossAxisExtent: constraints.maxWidth < 600 ? 150 : 200,
// ...
);
},
)
This skill currently has no executable scripts. All guidance is in reference documentation.
This skill includes complete Dart example files demonstrating:
These assets can be copied directly into your Flutter project or adapted to your needs.
Weekly Installs
1.3K
Repository
GitHub Stars
87
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex1.1K
opencode1.1K
gemini-cli1.0K
github-copilot998
kimi-cli900
amp888
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装