首页 > 其他分享 >Flutter中如何计算一个Container可以完美填充多少文字

Flutter中如何计算一个Container可以完美填充多少文字

时间:2024-02-26 12:33:47浏览次数:15  
标签:文字 Container 填充 width paragraph ui override Flutter size

要想知道一个 Container 可以填满多少个文字,我们只需算出一行可以填充的文字数量,再算出可以填充的最大行数,将两者相乘就行。

遇到问题先干嘛?当然是用搜索引擎先检索一下答案。我检索到了一篇标题为《Flutter-如何计算文字宽高》的文章(因为我在站内没有搜到这篇文章,所有有兴趣的可以自己用搜索引擎检索查看),这篇文章使用了 TextPainter 来计算出文字的宽高。这里我就用 ParagraphBuilder 来完成计算。这可能并不是最好的,请根据需求酌情参考。

我们有如下一个示例:

显然,如果直接使用 Text 我们什么也做不了,所以我们得使用 CustomPaint 来显示绘制的文字。

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          width: 200,
          height: 200,
          clipBehavior: Clip.hardEdge,
          decoration: const BoxDecoration(color: Colors.green),
          child: CustomPaint(
            painter: CustomTextPainter(),
          ),
        ),
      ),
    );
  }
}

class CustomTextPainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size) {
    // ...
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => this != oldDelegate;
}

因为不是每次传入的文字大小都是一样的,所以我们需要在外部传入该值。

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          width: 200,
          height: 200,
          clipBehavior: Clip.hardEdge,
          decoration: const BoxDecoration(color: Colors.green),
          child: CustomPaint(
            painter: CustomTextPainter(
              fontSize: 16,
              lineHeight: 1,
            ),
          ),
        ),
      ),
    );
  }
}

class CustomTextPainter extends CustomPainter {

  final double fontSize;
  final double lineHeight;

  CustomTextPainter({
    super.repaint,
    required this.fontSize,
    required this.lineHeight,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // ...
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => this != oldDelegate;
}

这里我们指定需要传入两个参数:文字大小和行高,知道这两个参数我们就很容易通过 文字大小 * 文字行高 来计算出文字所占的高度。

计算出了文字所占的高度,就能计算出可以完美显示所有文字的行数。

代码如下:

@override
void paint(Canvas canvas, Size size) {
  ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(ui.ParagraphStyle());
  paragraphBuilder.pushStyle(
    ui.TextStyle(
      color: Colors.white,
      fontSize: fontSize,
      height: lineHeight,
    ),
  );
  
  double fontHeight = fontSize * lineHeight;
  int fontLine = size.height ~/ fontHeight;
  print('每个文字的高度是:$fontHeight');  // 16
  print('完美呈现的文字行数是:$fontLine');  // 12
}

我们可以显示一段文字来验证下:

@override
void paint(Canvas canvas, Size size) {
  ...
    
  paragraphBuilder.addText('海水梦悠悠' * 100);
  ui.ParagraphConstraints paragraphConstraints = ui.ParagraphConstraints(width: size.width);
  ui.Paragraph paragraph = paragraphBuilder.build();
  paragraph.layout(paragraphConstraints);
  canvas.drawParagraph(paragraph, Offset.zero);
}

一共刚好 12 行。

现在知道了行数,接下来就只要算出一行可以填充几个文字就行。

想要知道一行可以填充几个文字,我们可以先算出一个字所占的宽度。我们先让界面只显示一个字:

@override
void paint(Canvas canvas, Size size) {
  ...
    
  paragraphBuilder.addText('海');
  ui.ParagraphConstraints paragraphConstraints = ui.ParagraphConstraints(width: size.width);
  ui.Paragraph paragraph = paragraphBuilder.build();
  paragraph.layout(paragraphConstraints);
  canvas.drawParagraph(paragraph, Offset.zero);
}
674044642.png

为什么要改成显示一个字?我们虽然无法计算出一个字的宽度,但是可以用 ParagraphcomputeLineMetrics 方法算出每一行文字所占的宽度。

@override
void paint(Canvas canvas, Size size) {
  ...
    
  paragraphBuilder.addText('海');
  ui.ParagraphConstraints paragraphConstraints = ui.ParagraphConstraints(width: size.width);
  ui.Paragraph paragraph = paragraphBuilder.build();
  paragraph.layout(paragraphConstraints);
  List<ui.LineMetrics> lines = paragraph.computeLineMetrics();
  double fontWidth = lines.first.width;
  print("第一行文字所占的宽度:$fontWidth");  // 16.000030517578125
  print("一行可以显示的文字个数:${size.width ~/ fontWidth}");  // 12
  canvas.drawParagraph(paragraph, Offset.zero);
}

为了验证一下是否准确,可以数一下下图填满时的个数:

521

通过以上的内容我们可以计算出,在一个 200*200 的 Container 中,可以完整显示文字大小为 16,行高为 1 的文字共 144 个。

以下是完整代码:

import 'dart:ui' as ui;

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          width: 200,
          height: 200,
          clipBehavior: Clip.hardEdge,
          decoration: const BoxDecoration(color: Colors.green),
          child: CustomPaint(
            painter: CustomTextPainter(
              fontSize: 16,
              lineHeight: 1,
            ),
          ),
        ),
      ),
    );
  }
}

class CustomTextPainter extends CustomPainter {
  final double fontSize;
  final double lineHeight;

  CustomTextPainter({
    super.repaint,
    required this.fontSize,
    required this.lineHeight,
  });

  @override
  void paint(Canvas canvas, Size size) {
    ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(ui.ParagraphStyle());
    paragraphBuilder.pushStyle(
      ui.TextStyle(
        color: Colors.white,
        fontSize: fontSize,
        height: lineHeight,
      ),
    );
    double fontHeight = fontSize * lineHeight;
    int fontLine = size.height ~/ fontHeight;
    print('每个文字的高度是 $fontHeight');
    print('完美呈现的文字行数是 $fontLine');

    paragraphBuilder.addText('海');
    ui.ParagraphConstraints paragraphConstraints = ui.ParagraphConstraints(width: size.width);
    ui.Paragraph paragraph = paragraphBuilder.build();
    paragraph.layout(paragraphConstraints);

    List<ui.LineMetrics> lines = paragraph.computeLineMetrics();
    double fontWidth = lines.first.width;
    print("第一行文字所占的宽度:$fontWidth");
    print("一行可以显示的文字个数:${size.width ~/ fontWidth}");

    canvas.drawParagraph(paragraph, Offset.zero);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => this != oldDelegate;
}

当然,在实际应用中,我们不可能让 “海” 字显示出来,并且只能应用于中文日文之类的文字,如果插入了英文字母数字之类的可能就不准确了。

标签:文字,Container,填充,width,paragraph,ui,override,Flutter,size
From: https://www.cnblogs.com/ilgnefz/p/18029972

相关文章

  • Flutter 新建的Project Type类型对比
    FlutterApp构建一个标准FluterApp(统一管理模式)包含Dart层和平台层(iOS/Android)FlutterModule创建一个Flutter模块(三端分离模式)以模块的形式分别嵌入原生项目FlutterPackage纯Dart插件工程,不依赖Flutter仅包含Dart层的实现,通常用来定义一些公共库Flutter......
  • 取消浏览器中记住密码自动填充时弹出Windows安全中心的验证
    1、......
  • Flutter 和 RN 的iOS 打包部署
    前沿现在科技的发展,现在多端适配已经成为趋势, 关于打包和发布的文字描述进入项目目录:在终端中切换到ReactNative或者Flutter项目的根目录。打开Xcode项目:打开Xcode并在菜单中选择File->Open,然后选择ReactNative项目中的.xcworkspace文件。步骤2:配置Build......
  • containerd环境搭建指南
    目录一.container概述1.什么是containerd2.为什么要学习containerd二.基于yum方式安装containerd1.获取软件源2.查看yum源中containerd软件版本3.安装containerd的4.查看containerd的版本信息5.设置containerd开机自启动6.查看containerd的客户端和服务端的版本信息三.基于二进制......
  • 阻止浏览器自动填充input密码框
    1.最简单的方法,加一个属性autocomplete=“new-password”.<inputtype="text"placeholder="密码"autocomplete=“new-password”/>2.把inputtype=”password”改成inputtype=”text”并在后面加上οnfοcus=”this.type=’password’”.<inputtype="text"pla......
  • 踩坑小计-Android Flutter应用设置沉浸式状态栏
    之前写过一篇关于设置Flutter页面沉浸式状态栏的文章。https://www.cnblogs.com/mrhan9941/p/16482604.html主要是基于Flutterboost的原生Android项目的,那时候是在原生Android项目嵌入了FlutterModule。项目重构后已经改为纯Flutter项目,确发现一个小问题,沿用之前的设置沉浸式状......
  • flutter开发Future与Stream的理解和区别
    flutter开发Future与Stream的理解和区别Future特点Future是表示一个异步操作的单个结果,只返回一次结果。通常用于处理一次性的异步操作。Future通过then()和catchError()方法来处理异步操作的结果和异常。Future使用await关键字来等待异步操作完成。FutureBuilder:通过监听......
  • container_of宏
    玩转内核链表list_headcontainer_of是Linux内核中一个常用的宏,用于从结构体的成员指针获取包含该成员的整个结构体的指针。/***container_of-castamemberofastructureouttothecontainingstructure*@ptr:thepointertothemember.*@type:thet......
  • flutter 知识点
    前沿熟悉了下flutter,然后把一些知识点梳理下,便于记忆:其实很多布局样式和CSS差异并不大,我的理解flutter的写法就是HTML写在标签上的style,也就是内敛样式,这样好理解,你也可以有不同的看法, 完成了之前没有完成的flutterdemo哈哈哈,OK 常用的布局和用到的组件:其他可以去......
  • 使用MICE进行缺失值的填充处理
    在我们进行机器学习时,处理缺失数据是非常重要的,因为缺失数据可能会导致分析结果不准确,严重时甚至可能产生偏差。处理缺失数据是保证数据分析准确性和可靠性的重要步骤,有助于确保分析结果的可信度和可解释性。在本文中,我们讲重点介绍MICE。MICE(MultipleImputationbyChainedEq......