Flutter响应式布局插件flutter_gehry的使用

Flutter响应式布局插件flutter_gehry的使用

flutter_gehry 是一个Flutter包,它提供了一种实现响应式布局的方法。该包采用移动优先的断点方法,允许开发者根据屏幕宽度的不同来调整UI布局。以下是关于 flutter_gehry 的详细使用说明和一个完整的示例Demo。

1. 使用方法

为了使用 flutter_gehry,你需要将你的应用程序包裹在 ResponsiveBreakpointsProvider 中。这将为应用程序提供不同的断点。断点是基于最小窗口宽度来工作的。

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return ResponsiveBreakpointsProvider(
      child: MaterialApp(
        title: "响应式应用",
        home: Text("首页"),
      ),
    );
  }
}

默认情况下,flutter_gehry 提供了5个断点:xssmmdlgxl,对应的最小宽度分别为:

  • xs: 0 (不可配置)
  • sm: 640
  • md: 768
  • lg: 1024
  • xl: 1280

你可以通过传递一个 ResponsiveBreakpoints 实例给 ResponsiveBreakpointsProviderbreakpoints 属性来更改这些默认值。

依赖于 ResponsiveBreakpointsProvider 的小部件只有在当前断点发生变化时才会重新构建,而不是每次窗口大小变化时都重新构建。

如果你需要根据当前断点获取一些任意值,可以使用 ResponsiveBreakpointsProvider.of(context).maybePick(...)ResponsiveBreakpointsProvider.of(context).pick(...)。两者的区别在于 pick 必须提供 xs 值,而 maybePick 在没有匹配当前断点的数据时会返回 null

例如,如果你想根据断点改变一个字符串:

const value = ResponsiveBreakpointsProvider.of(context).pick(
  xs: "这个字符串将在 xs 和 sm 断点显示",
  md: "这个字符串将在 md 和 lg 断点显示",
  xl: "这个字符串将在 xl 断点显示",
);

2. 响应式小部件

flutter_gehry 提供了多个响应式小部件,它们都继承自 BaseResponsiveWidget,并提供了 buildResponsive 方法。这些小部件通常为每个断点提供数据。如果未为当前断点提供数据,则会使用下一个较小的非空断点的数据。

2.1 ResponsiveBuilder

ResponsiveBuilder 类似于 ResponsiveWidget,但它接受的是 WidgetBuilder,即 Widget Function(BuildContext context),而不是直接的 Widget

ResponsiveBuilder(
  xs: (context) => const Text("这个将在 xs、sm 和 md 断点显示"),
  lg: (context) => const Text("这个将在 lg 和 xl 断点显示"),
);
2.2 ResponsiveConstrainedBox

ResponsiveConstrainedBoxConstrainedBox 的包装器。如果没有为当前断点提供约束条件,则直接返回子组件;如果子组件也为 null,则返回 SizedBox.shrink()

ResponsiveConstrainedBox(
  xs: const BoxConstraints.tightFor(width: 100),
  lg: const BoxConstraints.tightFor(width: 200),
  child: const Text("这段文本将根据断点进行约束"),
);
2.3 ResponsiveDecoratedBox

ResponsiveDecoratedBoxDecoratedBox 的包装器。如果没有为当前断点提供装饰数据,则直接返回子组件;如果子组件也为 null,则返回 SizedBox.shrink()

ResponsiveDecoratedBox(
  xs: const BoxDecoration(color: Colors.red),
  lg: const BoxDecoration(color: Colors.blue),
  child: const Text("背景颜色将根据断点变化"),
);
2.4 ResponsiveFlex

ResponsiveFlexFlex 的包装器,用于在不同断点下显示小部件列表,并根据断点改变方向(垂直或水平)。

ResponsiveFlex(
  direction: const BreakpointsData(
    xs: Axis.vertical,
    lg: Axis.horizontal,
  ),
  children: const [
    Text("子组件将在 xs、sm 和 md 断点垂直显示"),
    Text("子组件将在 lg 和 xl 断点水平显示"),
  ],
);
2.5 ResponsiveFlexible

ResponsiveFlexibleFlexible 的包装器,通常作为 Flex 小部件的子组件使用。它接受 ResponsiveFlexibleData 实例,表示 Flexible 小部件的行为。ResponsiveExpandedData 继承自 ResponsiveFlexibleData,表示 Expanded 小部件的行为。

如果没有为当前断点提供数据,则返回 SizedBox.shrink()

2.6 ResponsiveGridView

ResponsiveGridViewGridView 的包装器,用于在不同断点下显示网格布局。

2.7 ResponsiveListView

ResponsiveListViewListView 的包装器,用于在不同断点下显示列表布局。

2.8 ResponsivePadding

ResponsivePaddingPadding 的包装器,用于在不同断点下为子组件添加不同的内边距。

ResponsivePadding(
  xs: const EdgeInsets.all(8),
  md: const EdgeInsets.all(24),
  lg: const EdgeInsets.all(42),
  child: Text("这段文本将根据断点增加更多的内边距"),
);
2.9 ResponsiveSizedBox

ResponsiveSizedBoxSizedBox 的包装器,用于在不同断点下设置不同的宽度和高度。

ResponsiveSizedBox(
  xs: const ResponsiveSizedBoxData(height: 20),
  md: const ResponsiveSizedBoxData(height: 32),
  xl: const ResponsiveSizedBoxData(height: 52),
  child: Text("这段文本将根据断点占据更多的垂直空间"),
);
2.10 ResponsiveText

ResponsiveTextText 的包装器,允许你在不同断点下使用不同的文本样式或内容。

const ResponsiveText(
  "这是默认显示的文本",
  text: BreakpointsData(
    xl: "这段文本将在 xl 断点覆盖默认文本",
  ),
  style: BreakpointsData(
    xs: TextStyle(fontSize: 12),
    md: TextStyle(fontSize: 16),
    xl: TextStyle(fontSize: 20),
  ),
);
2.11 ResponsiveWidget

ResponsiveWidget 是一个简单的响应式小部件,它为每个断点提供一个小部件,并返回当前断点对应的小部件。

如果没有为当前断点提供数据,则返回 SizedBox.shrink()

ResponsiveWidget(
  xs: const SizedBox.square(dimension: 12),
  md: const Text("这段文本将在 md 和 lg 断点显示"),
  xl: const Center(
    child: Text("这段文本将在 xl 断点显示"),
  ),
);

3. 完整示例Demo

以下是一个完整的示例,展示了如何使用 flutter_gehry 创建一个响应式页面:

import 'package:flutter/material.dart';
import 'package:flutter_gehry/flutter_gehry.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return ResponsiveBreakpointsProvider(
      child: MaterialApp(
        title: "响应式应用",
        theme: ThemeData(
          primarySwatch: Colors.blue,
          canvasColor: Colors.white.withOpacity(0.9),
        ),
        debugShowCheckedModeBanner: false,
        home: const Scaffold(
          body: ResponsivePage(),
        ),
      ),
    );
  }
}

class ResponsivePage extends StatelessWidget {
  const ResponsivePage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return ResponsivePadding(
      xs: const EdgeInsets.all(8),  // 小屏幕时的内边距
      md: const EdgeInsets.all(12), // 中等屏幕时的内边距
      child: ResponsiveFlex(
        direction: const BreakpointsData(
          xs: Axis.vertical,  // 小屏幕时垂直排列
          md: Axis.horizontal, // 中等屏幕时水平排列
        ),
        crossAxisAlignment: const BreakpointsData(md: CrossAxisAlignment.stretch),
        children: [
          ResponsiveFlexible(
            md: const ResponsiveExpandedData(),  // 中等屏幕时扩展
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                const ColoredBox(
                  color: Colors.deepPurpleAccent,
                  child: Padding(
                    padding: EdgeInsets.all(16),
                    child: Text(
                      "响应式应用标题",
                      style: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ),
                ResponsiveSizedBox(
                  xs: const ResponsiveSizedBoxData(height: 16),  // 小屏幕时的高度
                  md: const ResponsiveSizedBoxData(height: 20),  // 中等屏幕时的高度
                ),
                for (int i = 0; i < 4; i++)
                  ResponsivePadding(
                    xs: const EdgeInsets.symmetric(vertical: 4),  // 小屏幕时的内边距
                    md: const EdgeInsets.symmetric(vertical: 8),  // 中等屏幕时的内边距
                    child: ColoredBox(
                      color: Colors.deepPurpleAccent.withOpacity(0.5),
                      child: const Padding(
                        padding: EdgeInsets.all(16),
                        child: Text(
                          "卡片标题",
                          style: TextStyle(
                            fontSize: 15,
                          ),
                        ),
                      ),
                    ),
                  ),
              ],
            ),
          ),
          ResponsiveSizedBox(
            xs: const ResponsiveSizedBoxData(height: 16),  // 小屏幕时的高度
            md: const ResponsiveSizedBoxData(width: 12),   // 中等屏幕时的宽度
          ),
          ColoredBox(
            color: Colors.deepPurple.withOpacity(0.75),
            child: ResponsivePadding(
              xs: const EdgeInsets.all(12),  // 小屏幕时的内边距
              md: const EdgeInsets.all(20),  // 中等屏幕时的内边距
              child: ResponsiveFlex(
                direction: const BreakpointsData.all(Axis.vertical),
                crossAxisAlignment: const BreakpointsData(
                  xs: CrossAxisAlignment.stretch,  // 小屏幕时的对齐方式
                  md: CrossAxisAlignment.center,   // 中等屏幕时的对齐方式
                ),
                children: [
                  Text(
                    ResponsiveBreakpointsProvider.of(context).pick(
                      xs: "xs 侧边栏标题",
                      md: "md 侧边栏标题",
                      xl: "xl 侧边栏标题",
                    ),
                    style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter响应式布局插件flutter_gehry的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

回到顶部