Flutter渲染度量插件render_metrics的使用

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

Flutter渲染度量插件render_metrics的使用

描述

render_metrics 是由 Surf 提供的 SurfGear 工具包的一部分,它可以帮助开发者获取Flutter应用程序中任何组件在组件树中的当前位置坐标。

目前支持的功能

  • 获取组件的完整位置坐标:可以随时检索所需组件的全部定位坐标。
  • 计算两个组件之间的位置差异:计算并使用两个组件之间的相对位置差异。

示例代码与用法

1. 添加依赖

首先,在您的 pubspec.yaml 文件中添加 render_metrics 的依赖:

dependencies:
  render_metrics: ^latest_version # 替换为当前最新版本

确保替换 latest_version 为实际的最新版本号。可以通过访问 Pub.dev 查看最新版本。

2. 使用示例

下面是一个完整的示例,演示了如何使用 render_metrics 来获取组件的位置信息,并计算两个不同组件之间的相对位置差异。

主文件 (main.dart)

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

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Render Metrics Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Render Metrics Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    required this.title,
    Key? key,
  }) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final renderManager = RenderParametersManager<dynamic>();

  final String _text0Id = 'text0Id';
  final String _text1Id = 'text1Id';
  final String _containerPositionedId = 'containerPositionedId';
  final String _textBlockId = 'textBlockId';

  final _scrollController = ScrollController();

  bool _isOpacity = false;
  String _text0 = '';

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_scrollListener);
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      setState(() {});
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Stack(
        children: <Widget>[
          ListView(
            controller: _scrollController,
            children: <Widget>[
              const SizedBox(height: 500),
              RenderMetricsObject(
                id: _textBlockId,
                manager: renderManager,
                onMount: (id, box) {
                  // 当创建 RenderObject 时调用的方法
                },
                onUnMount: (box) {
                  // 当 RenderObject 从树中移除时调用的方法
                },
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    RenderMetricsObject(
                      id: _text1Id,
                      manager: renderManager,
                      child: _TextContainer(
                        text:
                            'Diff metrics between the current and the blue square:'
                            '\n\n'
                            '${renderManager.getDiffById(_text1Id, _containerPositionedId) ?? ''}',
                      ),
                    ),
                    const SizedBox(height: 20),
                    RenderMetricsObject(
                      id: _text0Id,
                      manager: renderManager,
                      child: _TextContainer(
                        text: 'Metrics:\n\n$_text0',
                      ),
                    ),
                    const SizedBox(height: 1500),
                  ],
                ),
              ),
            ],
          ),
          Positioned(
            top: 50,
            left: 10,
            child: _Box(
              renderManager: renderManager,
              containerPositionedId: _containerPositionedId,
              isOpacity: _isOpacity,
            ),
          ),
        ],
      ),
    );
  }

  void _scrollListener() {
    setState(() {
      _text0 = _getRenderDataText(_text0Id, renderManager);
    });

    final diff = renderManager.getDiffById(
      _containerPositionedId,
      _textBlockId,
    );

    if (diff != null) {
      _changeBlockUi(diff.diffBottomToTop > 0);
    }
  }

  void _changeBlockUi(bool isChange) {
    if (_isOpacity == isChange) return;
    setState(() {
      _isOpacity = isChange;
    });
  }
}

class _TextContainer extends StatelessWidget {
  final String text;

  const _TextContainer({
    required this.text,
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black.withOpacity(.2),
      child: Padding(
        padding: const EdgeInsets.all(10),
        child: Text(
          text,
        ),
      ),
    );
  }
}

class _Box extends StatelessWidget {
  final RenderParametersManager renderManager;
  final String containerPositionedId;
  final bool isOpacity;

  const _Box({
    required this.renderManager,
    required this.containerPositionedId,
    required this.isOpacity,
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return RenderMetricsObject<dynamic>(
      id: containerPositionedId,
      manager: renderManager,
      child: AnimatedOpacity(
        duration: const Duration(milliseconds: 250),
        opacity: isOpacity ? .5 : 1,
        child: Container(
          width: 300,
          height: 210,
          color: Colors.blue,
          child: Padding(
            padding: const EdgeInsets.all(10),
            child: Text(
              'Blue Container widget metrics:'
              '\n\n'
              '${_getRenderDataText(containerPositionedId, renderManager)}',
              style: const TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    );
  }
}

String _getRenderDataText<T>(
  T id,
  RenderParametersManager renderManager,
) {
  final data = renderManager.getRenderData(id);
  if (data == null) return '';
  return data.toString();
}

关键点解释

  • RenderParametersManager: 创建一个管理器实例来跟踪和管理所有被监控的组件。
  • RenderMetricsObject: 包装您想要追踪位置的组件,通过指定唯一的 id 和关联的 manager 实例。
  • getRenderData(): 通过传递组件的唯一标识符(id)来获取该组件的位置信息。
  • getDiffById(): 通过传递两个组件的唯一标识符来计算它们之间的相对位置差异。

此示例展示了如何结合滚动事件动态更新组件的位置信息,并根据这些信息改变界面显示效果。希望这能帮助您更好地理解和使用 render_metrics 插件!


更多关于Flutter渲染度量插件render_metrics的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter渲染度量插件render_metrics的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,render_metrics 插件可以帮助开发者获取和监控渲染性能数据。以下是一个简单的示例,展示了如何使用 render_metrics 插件来获取和打印渲染相关的度量信息。

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

dependencies:
  flutter:
    sdk: flutter
  render_metrics: ^x.y.z  # 替换为最新版本号

然后,运行 flutter pub get 来安装依赖。

接下来,在你的 Flutter 应用中,你可以按照以下步骤使用 render_metrics

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:render_metrics/render_metrics.dart';
  1. 创建一个全局的 RenderMetricsObserver 实例
final RenderMetricsObserver metricsObserver = RenderMetricsObserver();
  1. metricsObserver 添加到 MaterialApp 的 navigatorObservers
void main() {
  runApp(MyApp(metricsObserver: metricsObserver));
}

class MyApp extends StatelessWidget {
  final RenderMetricsObserver metricsObserver;

  MyApp({required this.metricsObserver});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorObservers: [metricsObserver],
      home: HomeScreen(),
    );
  }
}
  1. 在需要的地方监听渲染度量事件
class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    super.initState();

    // 监听布局度量事件
    widget.metricsObserver.addListener(() {
      final metricsData = widget.metricsObserver.latestMetrics;
      if (metricsData != null) {
        print('Render Metrics Data:');
        print('  Frame Rate: ${metricsData.frameRate}');
        print('  Build Duration: ${metricsData.buildDuration}');
        print('  Raster Duration: ${metricsData.rasterDuration}');
        // 打印更多你感兴趣的度量信息
      }
    });
  }

  @override
  void dispose() {
    widget.metricsObserver.removeListener(() {});
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Render Metrics Demo'),
      ),
      body: Center(
        child: Text('Check the console for render metrics data.'),
      ),
    );
  }
}

在这个示例中,我们创建了一个 RenderMetricsObserver 实例,并将其添加到 MaterialAppnavigatorObservers 中。然后,我们在 HomeScreeninitState 方法中监听 metricsObserver 的事件,并在控制台中打印渲染度量数据。

请注意,render_metrics 插件提供的数据可能会因 Flutter 版本和具体设备而异。你可以根据实际需要调整监听和打印的度量信息。

此外,由于 render_metrics 插件可能是一个第三方库,其具体 API 和使用方法可能会随着版本更新而变化。因此,建议查阅最新的官方文档或源代码以获取最准确的信息。

回到顶部