fl_responsive_guide

Pub Package Star on GitHub style: effective dart MIT License

Demo

基础

为了理解响应式构建,我们需要回顾一下 Material Design 提到的一些概念,例如:布局解剖:https://material.io/design/layout/understanding-layout.html 在本节中,我们将了解...的定义

应用栏:https://material.io/design/layout/understanding-layout.html

设备断点:https://material.io/design/layout/responsive-layout-grid.html

导航区域:https://material.io/design/layout/understanding-layout.html

列、间隙、边距:https://material.io/design/layout/responsive-layout-grid.html

在研究了以上信息后,我们会发现构建响应式界面需要基于以上参数进行工作。在这里,我们将有一个名为*ResponsiveGuide*的类。*ResponsiveGuide*是一个*InheritedWidget*,它允许其下方的 widget 能够接收到关于*FlDesignConfig*构建配置的更改信息。

每个断点都有一个单独的配置来确定需要时的渲染类型。UI 渲染参数如下。

  final FlSize margin; -> Dùng xác định cho margin của Body
  final FlSize body; -> Dùng xác định width của body
  final int layoutColumns; -> config cho số column trong body
  final double gutters; -> 
  final DeviceTarget deviceTarget; -> config xem giao diện của breakpoint này sẽ render cho device nào.
  final double? navigationRailWidth;
  final double appbarHeight;
  final double drawerWidth;
  final double tabBarHeight;

其中,我们需要注意*FlSize*。这个类将允许我们确定何时需要声明特定大小,何时需要让它根据屏幕自动缩放。

abstract class FlSize {
  FlSize();

  factory FlSize.size(double size) {
    return FlSizeNumber(size);
  }

  factory FlSize.scale() {
    return FlSizeScale();
  }
}

class FlSizeNumber extends FlSize {
  final double number;

  FlSizeNumber(this.number);
}

class FlSizeScale extends FlSize {}

实现

应用程序的断点系统

Scaffold 1:*应用栏* 2:*导航/抽屉* 3:*主体*

Breakpoints 1:*列* 2:*间隙* 3:*边距*

基本上,构建响应式应用程序就是确定屏幕类型(由断点确定)。根据当前断点决定要构建的界面。因此,我们需要为应用程序确定断点。

以下是 Material Design 的断点划分指南

屏幕尺寸 外边距 主体 布局列
0-599dp 16dp 缩放 4
600-904 32dp 缩放 8
905-1239 缩放 840dp 12
1240-1439 200dp 缩放 12
1440+ 缩放 1040 12

应用示例

      breakpointSystems: {
        600: FlDesignConfig(
            body: FlSize.scale(),
            margin: FlSize.size(0),
            appbarHeight: 56,
            deviceTarget: DeviceTarget.mobile),
        900: FlDesignConfig(
            body: FlSize.scale(),
            margin: FlSize.size(0),
            gutters: 12,
            appbarHeight: 56,
            deviceTarget: DeviceTarget.tablet),
        double.maxFinite: FlDesignConfig(
            body: FlSize.size(621),
            margin: FlSize.scale(),
            gutters: 24,
            appbarHeight: 80,
            deviceTarget: DeviceTarget.desktop)
      }

有了这个*breakpointSystems*,我们可以看到应用程序被划分为三种屏幕类型:

1:0 < 宽度 < 600 => 此类型被设备识别为*移动设备*,*应用栏*的高度为 56dp

2:600 <= 宽度 < 900 => 此类型被设备识别为*平板电脑*,*应用栏*的高度为 56dp,间隙为 12dp

3:宽度 >= 900 => 此类型被设备识别为*桌面设备*,*应用栏*的高度为 80dp,间隙为 24dp

创建支持响应式构建的包装器 widget

确定应用程序的断点后,widget 在渲染时将根据哪个断点来确定它们需要渲染的 UI。

为了实现这一点,我们将需要两个类:

  1. *ResponsiveGuideWrapper*它就像一个响应式布局的 Provider。它允许其子 widget 确定当前用于渲染的断点是什么。

  2. *ResponsiveGuideConsumerWidget*一个 Consumer Widget,允许子 widget 知道当前渲染的参数是什么。

示例

  Widget build(BuildContext context) {
    return ResponsiveGuideWrapper(
      breakpointSystems: {
        600: FlDesignConfig(
            body: FlSize.scale(),
            margin: FlSize.size(0),
            appbarHeight: 56,
            deviceTarget: DeviceTarget.mobile),
        900: FlDesignConfig(
            body: FlSize.scale(),
            margin: FlSize.size(0),
            gutters: 12,
            appbarHeight: 56,
            deviceTarget: DeviceTarget.tablet),
        double.maxFinite: FlDesignConfig(
            body: FlSize.size(621),
            margin: FlSize.scale(),
            gutters: 12,
            appbarHeight: 56,
            deviceTarget: DeviceTarget.desktop)
      },
      child: Application(),
    );
  }
}

使用

      body: ResponsiveGuideConsumerWidget(
        builder: (context, designInfo) {
          switch (designInfo.deviceTarget) {
            case DeviceTarget.mobile:
              return Center(
                child: Text('Mobile App'),
              );
            case DeviceTarget.tablet:
              return Center(
                child: Text('Tablet App'),
              );
            case DeviceTarget.desktop:
              return Center(
                child: Text('Desktop App'),
              );
          }
        },
      )

GitHub

查看 Github