text - 查找文本的确切边界

标签 text flutter

我需要知道一段文本的确切边界——相当于 getTextBounds对于安卓。我意识到这与 Flutter 的设计有些背道而驰,但我以一种非传统的方式使用文本(就像文本以精确的位置和大小嵌入到艺术图片中一样)。

我试过三种方法:

  • TextPainterminIntrinsicWidthheight .来源如下。这会产生一个四面都有空间的边界框:

    enter image description here

    我需要该矩形的边正对着“8”的黑色像素。 (在这种特殊情况下, widthmaxIntrinsicWidth 给出与 minIntrinsicWidth 相同的值;此外, preferredLineHeight 给出与 height 相同的值。)
  • ParagraphgetBoxesForRange -- 与 TextPainter 的结果基本相同。
  • FittedBox -- 也会留下空格,不管 BoxFit枚举值。我用过 this answer作为起点。
  • TextPainter代码如下。 (我意识到这是低效的;在获得所需的边界框之前我不在乎。我使用场景/图片/等希望在较低级别找到合适的功能。)
    import 'dart:ui';
    import 'dart:typed_data';
    import 'package:flutter/painting.dart';
    
    const black = Color(0xff000000);
    const white = Color(0xffffffff);
    
    final identityTransform = new Float64List(16)
      ..[0] = 1.0
      ..[5] = 1.0
      ..[10] = 1.0
      ..[15] = 1.0;
    
    TextPainter createTextPainter() {
      return new TextPainter(
        text: new TextSpan(
          text: '8',
          style: new TextStyle(
            color: black,
            fontSize: 200.0,
            fontFamily: "Roboto",
          ),
        ),
        textDirection: TextDirection.ltr,
      )..layout();
    }
    
    void drawBackground(Canvas canvas, Rect screen) {
      canvas.drawRect(
          screen,
          new Paint()
            ..color = white
            ..style = PaintingStyle.fill);
    }
    
    Picture createPicture() {
      final recorder = new PictureRecorder();
      final screen = Offset.zero & window.physicalSize;
      final canvas = new Canvas(recorder, screen);
      final offset = screen.center;
      final painter = createTextPainter();
      final bounds = offset & Size(painter.minIntrinsicWidth, painter.height);
      drawBackground(canvas, screen);
      painter.paint(canvas, offset);
      canvas.drawRect(
          bounds,
          new Paint()
            ..color = black
            ..style = PaintingStyle.stroke
            ..strokeWidth = 3.0);
      return recorder.endRecording();
    }
    
    Scene createScene() {
      final builder = new SceneBuilder()
        ..pushTransform(identityTransform)
        ..addPicture(Offset.zero, createPicture())
        ..pop();
      return builder.build();
    }
    
    void beginFrame(Duration timeStamp) {
      window.render(createScene());
    }
    
    void main() {
      window.onBeginFrame = beginFrame;
      window.scheduleFrame();
    }
    

    最佳答案

    要忽略该填充,您必须制作 真的低级调用为 Text并且空间实际上是一起绘制的。我尝试在互联网上搜索是否还有其他出路,但找不到任何可以真正解决您的问题的方法。

    我尝试搜索 Flutter SDK (Widget_Library) 的源代码,但我只能看到最终生成的小部件是 RichText其源代码消失得无影无踪。 (我刚刚在 GitHub 上搜索时找不到该小部件的定义...在 Android Studio 中,您可能会通过将鼠标悬停在它上面并按 Ctrl+LeftClick 来获得对它的一些引用...但我很确定它会你进入另一个未知的世界,因为字体是根据它们的字体系列绘制的(这将是 .ttf 或 .otf 文件......无论是哪种方式,它们都会与您所指的填充一起绘制)。

    您现在所能做的就是创建我们自己的字符集小部件,它接受原始字符串并读取每个字符并使用一些自定义绘制函数绘制您已经定义的数字/字符,

    或者,如果您准备放弃填充以节省一些时间(这对您现在可能至关重要也可能不重要),您可以使用一些预定义的函数来获得空间或使用以下解决方案来获得尺寸你想要的任何小部件。

    I need to know the exact bounds a piece of text...



    了解任何小部件宽度的最简单方法是使用 GlobalKey
    声明并初始化一个变量来存储 GlobalKey,
    GlobalKey textKey = GlobalKey();
    

    通过GlobalKey到您的 Text 的关键参数小部件,
    Text(
      "hello",
       key: textKey,
     )
    

    现在我将用 GestureDetector 包裹上面的小部件打印上述小部件的宽度。
    GestureDetector(
      onTap: (){
        print(textKey.currentContext.size.width); //This is your width
        print(textKey.currentContext.size.height); //This is your height
          },
       child: Text(
         "hello",
         key: textKey,
           ),
         )
    

    正如我之前提到的,你可以在任何小部件上使用它,你也可以在 TextSpan 上使用它小部件:
    GestureDetector(
      onTap: (){
        print(textKey.currentContext.size.width); //This is your width
          },
    TextSpan(
          key: textKey,
          text: '8',
          style: new TextStyle(
            color: black,
            fontSize: 200.0,
            fontFamily: "Roboto",
          ),
        ),
      )
    

    现在在 GlobalKey() 的帮助下您可以获得有关该片段的所有信息Text并相应地绘制边界/矩形。

    注:GlobalKey()为您的小部件提供唯一标识,因此不要在多个小部件上重复使用它。

    ==================

    编辑:

    如果可以以某种方式获得应用程序/文本中每个像素的颜色,那么就有可能获得您想要实现的目标。

    注:您必须分别找到每一侧的偏移/填充。

    x1,y1 是容器起点的坐标,x2,y2 是终点。

    minL,minR,minT,minB 是您要查找的偏移量。

    基本逻辑:根据所考虑的边垂直/水平扫描每条线,直到获得颜色等于文本颜色的像素,然后对所有假想线执行此操作,直到获得最小偏移量(文本与边界的距离) ) 各方面。

    想象一下,您从容器的边界画一条线,直到遇到文本的边界之一(/满足文本颜色),然后对所有其他组(水平[左/右] 或垂直[顶部/底部])执行此操作])线,你只需要记住最短的距离。
    // Left Side
    for(i=y1+1;i<y2;i++)
     for(j=x1+1;j<x2;j++)
       if(colorof(j,i)==textcolor && minL>j) {minL = j; break;}
    
    // Right Side
    for(i=y1+1;i<y2;i++)
     for(j=x2-1;j>x1;j--)
       if(colorof(j,i)==textcolor && minR>j) {minR = j; break;}
    
    // Top Side
    for(i=x1+1;i<x2;i++)
     for(j=y1;j<y2;j++)
       if(colorof(i,j)==textcolor && minT>j) {minT = j; break;}
    
    // Bottom Side
    for(i=x1+1;i<x1;i++)
     for(j=y2;j>y1;j--)
       if(colorof(i,j)==textcolor && minB>j) {minB = j; break;}
    
    x1 = x1 + minL;
    y1 = y1 + minT;
    x2 = x2 - minR;
    y2 = y2 - minB;
    
    

    在实现上述逻辑时,确保没有其他重叠/底层小部件(脚手架/堆栈组合)的颜色以某种方式与文本颜色匹配。

    关于text - 查找文本的确切边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51882610/

    相关文章:

    android - 在 Flutter 项目的 android studio 上初始化 Gradle 将永远存在

    php - 使用 PHP 多行 HTML 表单文本安全地返回屏幕并进入 MySQL?

    java - Text-Adventure 在某一行后意外停止。

    javascript - 如何检测div中的单个单词

    php - SQL 结果作为 txt.file 由 php

    android-studio - 可以显示不带点的 flutter 项目的实际文件夹结构

    dart - 关闭 Listview.builder 的可滚动功能

    flutter - Runner设置编译Flutter iOS报错

    java - 自动完成 JTextField 和箭头键

    flutter - 堆栈位置不准确