Flutter自适应尺寸布局插件intrinsic_size_builder的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter自适应尺寸布局插件intrinsic_size_builder的使用

背景

intrinsic_size_builder 是一个小型但非常有用的包,适用于那些需要在将某些小部件添加到小部件树之前知道其固有尺寸的情况。

什么是固有尺寸? 这是当小部件可以自己确定大小时所获得的尺寸。与父级限制尺寸的情况相反。 注意 您可以通过 IntrinsicSizeBuilderconstrainedAxis 参数允许父级限制尺寸。

使用方法

IntrinsicSizeBuilder 有一个很好的用例是当你想要一个具有动态大小的灵活空间/底部的 SliverAppBar。下面是一个简单的使用示例:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Intrinsic Size Builder Demo'),
        ),
        body: Center(
          child: IntrinsicSizeBuilder(
            subject: const Text(
              'Hello world',
              style: TextStyle(fontSize: 25),
            ),
            builder: (context, subjectSize, subject) => Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                subject,
                Text('The size of subject is ${subjectSize.width}x${subjectSize.height}'),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

它是如何工作的?

在幕后,构建器将 subject(你需要获取其尺寸的小部件)以零透明度放入小部件树中仅1帧的时间,在此期间确定尺寸。之后调用构建器函数,并显示实际的小部件。

这是否意味着UI会有闪烁? 如果你发现初始(透明)1帧有问题,那么可以使用 firstFrameWidget 参数。例如,你可以延长你的加载屏幕1帧来完全消除任何闪烁。如这个例子所示。

如果主题改变了尺寸怎么办? 当主题的固有尺寸发生变化时,你需要通知 IntrinsicSizeBuilder 重新进行尺寸评估。你只需简单地调用静态方法 IntrinsicSizeBuilder.refresh(context) 即可。它会刷新所有位于 context 之上的 IntrinsicSizeBuilder。在这种情况下不会出现1帧的闪烁——当前显示的小部件会在1帧评估期间被保留。

示例代码

text_box

这是一个简单的例子,说明如何获取一些文本小部件的固有尺寸。

IntrinsicSizeBuilder(
  subject: const Text(
    'This is some text.',
    style: TextStyle(fontSize: 20),
  ),
  builder: (context, subjectSize, subject) => Text('Text size is ${subjectSize.width}x${subjectSize.height}'),
)

sliver_app_bar

一个具有动态大小的灵活空间和底部的 SliverAppBar

SliverAppBar(
  expandedHeight: 200.0,
  flexibleSpace: IntrinsicSizeBuilder(
    subject: FlexibleSpaceBar(
      title: Text('Title'),
      background: Image.network(
        'https://example.com/image.jpg',
        fit: BoxFit.cover,
      ),
    ),
    builder: (context, subjectSize, subject) => subject,
  ),
  bottom: PreferredSize(
    preferredSize: Size.fromHeight(50.0),
    child: IntrinsicSizeBuilder(
      subject: Container(
        color: Colors.blue,
        height: 50.0,
        child: Center(child: Text('Bottom')),
      ),
      builder: (context, subjectSize, subject) => subject,
    ),
  ),
)

images

将图片放入动态变化大小的 SliverAppBar 中。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          slivers: <Widget>[
            SliverAppBar(
              expandedHeight: 300.0,
              floating: false,
              pinned: true,
              flexibleSpace: IntrinsicSizeBuilder(
                subject: Stack(
                  children: [
                    Image.network(
                      'https://example.com/image.jpg',
                      fit: BoxFit.cover,
                    ),
                    Positioned.fill(
                      child: Align(
                        alignment: Alignment.bottomCenter,
                        child: Padding(
                          padding: EdgeInsets.all(16.0),
                          child: Text(
                            'Image Title',
                            style: TextStyle(
                              fontSize: 24,
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                builder: (context, subjectSize, subject) => subject,
                firstFrameWidget: Container(
                  color: Colors.red, // 红色背景作为第一帧的视觉优化
                  height: 300.0,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

通过这些示例,您可以更好地理解和使用 intrinsic_size_builder 插件来实现自适应尺寸布局。


更多关于Flutter自适应尺寸布局插件intrinsic_size_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自适应尺寸布局插件intrinsic_size_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 intrinsic_size_builder 插件来实现 Flutter 自适应尺寸布局的示例代码。intrinsic_size_builder 插件允许你根据子组件的自然大小来进行布局,这在某些复杂的 UI 场景中非常有用。

首先,确保你已经在 pubspec.yaml 文件中添加了 intrinsic_size_builder 依赖:

dependencies:
  flutter:
    sdk: flutter
  intrinsic_size_builder: ^0.0.3  # 请检查最新版本号

然后,运行 flutter pub get 来获取依赖。

接下来,在你的 Dart 文件中使用 IntrinsicSizeBuilder。以下是一个示例,展示了如何使用它来包裹一个 Text 组件,并确保 Text 组件根据其内容自适应大小:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('IntrinsicSizeBuilder Example'),
        ),
        body: Center(
          child: IntrinsicSizeBuilder(
            // 指定子组件的最大宽度和高度(可选)
            maxWidth: double.infinity,
            maxHeight: double.infinity,
            builder: (context, size) {
              // 这里 size 是子组件的自然大小
              return Container(
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.blue, width: 2),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    '这是一个自适应尺寸的文本组件,根据其内容调整大小。',
                    style: TextStyle(fontSize: 20),
                    textAlign: TextAlign.center,
                    softWrap: true,
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们导入了 intrinsic_size_builder 包。
  2. 使用 IntrinsicSizeBuilder 包装了一个 Text 组件。
  3. IntrinsicSizeBuilderbuilder 回调提供了一个 size 参数,这个参数是子组件的自然大小。
  4. 我们在这个回调中返回了一个 Container,它包裹了我们的 Text 组件,并添加了一个蓝色的边框以便观察布局效果。

通过这种方式,Text 组件会根据其内容自动调整大小,而 IntrinsicSizeBuilder 确保容器根据这个自然大小进行布局。这对于需要根据内容动态调整大小的复杂布局非常有用。

回到顶部