mcpField
F
flutter-build-responsive-layout

flutter-build-responsive-layout

github.com/flutter设计与 UI3.1k43.1k 次安装2 天前更新
代码仓库

关于 flutter-build-responsive-layout

为 Flutter 开发者提供自适应布局设计指导,依据应用窗口可用空间而非设备类型调整界面。涵盖布局约束、大小屏适配及输入方式支持。

主要功能

  1. 01依据窗口空间构建布局
  2. 02使用 LayoutBuilder 判断宽度
  3. 03约束大屏内容宽度
  4. 04为长列表采用延迟渲染
  5. 05支持鼠标、键盘与触控

适用场景

  1. 01为可调整大小的窗口设计界面
  2. 02在小屏与大屏间切换布局
  3. 03避免大屏内容横向拉伸
  4. 04为大型列表优化渲染

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/flutter/agent-plugins --skill flutter-build-responsive-layout

安装后在 Claude Code 中输入/flutter-build-responsive-layout确认已加载。

详细介绍

实现自适应布局

目录

空间测量指南

准确确定可用空间,确保布局适应应用窗口,而不仅仅是物理设备。

  • 使用 MediaQuery.sizeOf(context) 获取整个应用窗口的尺寸。
  • 使用 LayoutBuilder 根据父级 Widget 分配的空间做出布局决策。评估 constraints.maxWidth,确定要返回的合适 Widget 树。
  • 不要在 Widget 树顶部附近使用 MediaQuery.orientationOf 或 OrientationBuilder 来切换布局。设备方向无法准确反映应用窗口的可用空间。
  • 不要检查硬件类型(例如“手机”与“平板电脑”)。Flutter 应用会在可调整大小的窗口、多窗口模式和画中画模式下运行。所有布局决策都应严格依据可用窗口空间。

Widget 尺寸与约束

理解并应用 Flutter 的核心布局规则:约束向下传递。尺寸向上传递。父级设置位置。

  • 分配空间: 在 Row、Column 或 Flex Widget 中使用 Expanded 和 Flexible。
    • 使用 Expanded 强制子级填满所有剩余可用空间(等同于 fit: FlexFit.tight 且 flex 因子为 1.0 的 Flexible)。
    • 使用 Flexible 允许子级在特定限制范围内自行调整尺寸,同时仍可扩展或收缩。使用 flex 因子定义同级 Widget 之间的空间占用比例。
  • 限制宽度: 防止 Widget 在大屏上占满所有水平空间。将 GridView 或 ListView 等 Widget 包装在 ConstrainedBox 或 Container 中,并在 BoxConstraints 中定义 maxWidth。
  • 延迟渲染: 渲染数量未知或较多的列表时,始终使用 ListView.builder 或 GridView.builder。

设备与方向行为

确保应用在各种设备形态和输入方式下都能正常运行。

  • 不要锁定屏幕方向。 锁定方向会导致折叠设备出现严重的布局问题,通常会产生黑边(应用居中显示,周围带有黑色边框)。Android 大屏设备类别要求同时支持竖屏和横屏。
  • 锁定方向时的回退方案: 如果业务需求严格要求锁定方向,请使用 Display API 获取物理屏幕尺寸,而不要使用 MediaQuery。在兼容模式下,MediaQuery 无法获取较大的窗口尺寸。
  • 支持多种输入方式: 实现对基本鼠标、触控板和键盘快捷键的支持。确保触控目标尺寸合适,并支持键盘导航。

工作流:构建自适应布局

按照此工作流实现能够适应可用 BoxConstraints 的布局。

任务进度:

  • 确定需要自适应行为的目标 Widget。
  • 使用 LayoutBuilder 包装 Widget 树。
  • 从 builder 回调中提取 constraints.maxWidth。
  • 定义自适应断点(例如,largeScreenMinWidth = 600)。
  • 如果 maxWidth > largeScreenMinWidth: 返回大屏布局(例如,使用 Row 将导航侧边栏和内容区域并排放置)。
  • 如果 maxWidth <= largeScreenMinWidth: 返回小屏布局(例如,使用 Column 或标准导航样式方案)。
  • 运行 validator -> 调整应用窗口大小 -> 检查布局切换 -> 修复溢出错误。

工作流:针对大屏幕进行优化

按照此工作流,避免 UI 元素在大屏幕上不自然地拉伸。

任务进度:

  • 识别全宽组件(例如 ListView、文本块、表单)。
  • **如果要优化列表:**使用 SliverGridDelegateWithMaxCrossAxisExtent 将 ListView.builder 转换为 GridView.builder,以便根据窗口大小自动调整列数。
  • **如果要优化表单或文本块:**将组件包裹在 ConstrainedBox 中。
  • 将 BoxConstraints(maxWidth: [optimal_width]) 应用于 ConstrainedBox。
  • 将 ConstrainedBox 包裹在 Center 组件中,使受约束的内容在大屏幕上保持居中。
  • 运行验证器 -> 在桌面/平板目标设备上测试 -> 检查水平拉伸情况 -> 调整 maxWidth 或网格范围。

示例

使用 LayoutBuilder 构建自适应布局

演示如何根据可用宽度在移动端和桌面端布局之间切换。

import 'package:flutter/material.dart';

const double largeScreenMinWidth = 600.0;

class AdaptiveLayout extends StatelessWidget {
  const AdaptiveLayout({super.key});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth > largeScreenMinWidth) {
          return _buildLargeScreenLayout();
        } else {
          return _buildSmallScreenLayout();
        }
      },
    );
  }

  Widget _buildLargeScreenLayout() {
    return Row(
      children: [
        const SizedBox(width: 250, child: Placeholder(color: Colors.blue)),
        const VerticalDivider(width: 1),
        Expanded(child: const Placeholder(color: Colors.green)),
      ],
    );
  }

  Widget _buildSmallScreenLayout() {
    return const Placeholder(color: Colors.green);
  }
}
在大屏幕上限制宽度

演示如何防止小部件占用全部水平空间。

import 'package:flutter/material.dart';

class ConstrainedContent extends StatelessWidget {
  const ConstrainedContent({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ConstrainedBox(
          constraints: const BoxConstraints(
            maxWidth: 800.0, // Maximum width for readability
          ),
          child: ListView.builder(
            itemCount: 50,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text('Item $index'),
              );
            },
          ),
        ),
      ),
    );
  }
}

评论

支持 Markdown