查找文本的确切边界

2024-05-20

我需要知道一段文本的确切边界——相当于获取文本边界 https://developer.android.com/reference/android/graphics/Paint.html对于安卓。我意识到这在某种程度上与 Flutter 的设计背道而驰,但我以非传统的方式使用文本(就好像文本以精确的位置和大小嵌入到艺术图片中)。

我尝试了三种方法:

  • TextPainter's minIntrinsicWidth and height。来源如下。这会产生一个四周都有空间的边界框:

    我需要该矩形的边正好与“8”的黑色像素相对。 (在这种特殊情况下,width and maxIntrinsicWidth给出相同的值minIntrinsicWidth; also, preferredLineHeight给出相同的值height.)

  • Paragraph's getBoxesForRange-- 与 TextPainter 的结果基本相同。

  • FittedBox-- 也留有空格,无论BoxFit枚举值。我用了这个答案 https://stackoverflow.com/a/51680076/10234868作为起点。

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();
}

要忽略该填充,您必须进行really低级调用作为Text整个空间实际上是被粉刷在一起的。我尝试在互联网上搜索是否有其他方法,但找不到任何可以真正解决您的问题的方法。

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

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

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

我需要知道一段文本的确切边界......

了解任何小部件宽度的最简单方法是使用GlobalKey

声明并初始化一个变量来存储 GlobalKey,

GlobalKey textKey = GlobalKey();

通过GlobalKey到你的关键参数Text widget,

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 widget:

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并相应地绘制边界/矩形。

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

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

Edit:

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

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

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;

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查找文本的确切边界 的相关文章

随机推荐

  • C++ Exp 与 Log:哪个更快?

    我有一个 C 应用程序 需要比较两个值并决定哪个值更大 唯一的复杂之处是一个数字在对数空间中表示 而另一个则不是 例如 double log num 1 log 1 23 double num 2 1 24 如果我想比较num 1 and
  • 将正确的上下文传递给 greendao 的 OpenHelper 构造函数

    如果我理解正确的话 在使用数据库时 我必须执行以下操作 DaoMaster OpenHelper helper new DaoMaster OpenHelper this test db null Override public void
  • 在 Anko DSL 中创建自定义 View/ViewGroup 类

    我想创建一个自定义视图 它只是一些 Android 视图的包装 我考虑创建一个自定义 ViewGroup 来管理其子视图的布局 但我不需要这么复杂 我基本上想做的是 class MainActivity verticalLayout tex
  • 应用程序位于前台时的 IOS Expo 推送通知

    从博览会文档中阅读 对于 iOS 明智的做法是处理以下推送通知 当应用程序处于前台时收到 因为否则用户 永远不会见到他们 应用程序运行时到达的通知 iOS 上的前台不会显示在系统通知列表中 A 常见的解决方案是手动显示通知 为了 例如 如果
  • HTML5 历史 API

    我如何使用 HTML5 历史 api 我确实经历过https developer mozilla org en DOM Manipulated the browser history https developer mozilla org
  • Python Popen 与 psexec 挂起 - 不良结果

    我对 subprocess Popen 和我认为是管道的问题有疑问 我有以下代码块 从 cli 运行时 100 都不会出现问题 p subprocess Popen psexec serverName get cmd c ver echo
  • UML 的 XMI 有 XSD 吗?

    是否有 UML XMI 文件的 XSD 标头仅包含名称空间引用
  • Rails 的多个数据库不适用于远程数据库

    我有一个远程只读 postgres 数据库 它是通过 docker 实例维护的卡尔达诺数据库同步 https github com input output hk cardano db sync 我设法将开发数据库连接到它 它工作正常 但由
  • 使用 Java 在 BigQuery 中保存 Array

    我正在尝试使用 Spark Big Query 连接器将数据保存到 Big 查询中 假设我有一个如下所示的 Java pojo Getter Setter AllArgsConstructor ToString Builder public
  • 为什么我不能将 与 g++ 4.9.2 一起使用?

    我正在尝试使用文件系统 http en cppreference com w cpp experimental fs path 我有 std c 11 std c 1y in my CMakeLists txt 海湾合作委员会版本是4 9
  • 访问sendBeacon发送的数据

    文档表明sendBeacon通过发送其数据HTTP POST request 但在 PHP 中 POST变量似乎是一个空数组 这是我的 JavaScript 代码 navigator sendBeacon beacon log php My
  • Keycloak - 如何获取某个领域的所有用户并将其保存到应用程序数据库?

    我正在使用 Spring Boot 构建 REST API 并使用 Keycloak 进行身份验证和授权 由于用户是由Keycloak管理的 所以我的应用程序数据库没有用户的数据 但我想将 Keycloak 中的用户实体的一些属性存储在我的
  • android webview 函数 onPagefinished 被调用两次

    我的android webview功能onPageFinished被调用两次 我不知道为什么 但它在 android 2 2 上运行良好 但当我将其升级到 4 时 它就不起作用了 代码附在下面 Code Override public vo
  • 通过 ruby​​ 进程共享变量

    我正在编写一个 gem 其中我必须分叉两个进程来启动两个 webrick 服务器 我想通过基类的类方法启动该服务器 因为应该只运行这两个服务器 而不是多个服务器 在运行时 我想调用这两台服务器上的一些方法来更改变量 我的问题是 我无法通过基
  • XMPP 多用户聊天设置群聊头像

    我正在开发一个带有聊天功能的 iOS 应用程序 我正在为该应用程序使用 XMPP 在XMPP多用户聊天中 是否有功能可以像我们在whatsapp中那样为会议室设置头像或群组图像 我检查过XEP 0045 http xmpp org exte
  • 检查 PHP 中的字符串长度

    我有一个长度为 141 个字符的字符串 使用下面的代码我有一个if如果字符串大于或小于 140 则语句返回一条消息 libxml use internal errors TRUE dom new DOMDocument dom gt loa
  • Android 自定义视图不能以正确的方式处理透明度/alpha

    我正在绘制自定义视图 在此视图中 我使用两个不同的绘画和路径对象在画布上绘画 我基本上是在绘制两个重叠的形状 添加 Alpha 后 视图中重叠的部分比图像的其余部分更暗 这是不希望的 但我不知道如何解决它 这是我的代码片段 用于展示我如何在
  • django_openid_auth TypeError openid.yadis.manager.YadisServiceManager 对象不是 JSON 可序列化

    I used django openid auth在我的项目上 一段时间以来它运行得很好 但今天 我测试了该应用程序并遇到了这个异常 Environment Request Method GET Request URL http local
  • ExtJS打开窗口的最大高度

    我试图通过单击按钮 Ext Button 来打开一个窗口 Ext Window 问题是该窗口的尺寸必须为用户屏幕的 80 宽度和 100 高度 即它应该覆盖所有垂直空间 我真的无法创建一个工作示例 我使用的按钮是隐藏 显示这个窗口 它的大小
  • 查找文本的确切边界

    我需要知道一段文本的确切边界 相当于获取文本边界 https developer android com reference android graphics Paint html对于安卓 我意识到这在某种程度上与 Flutter 的设计背