Text 寻找文本的精确边界

Text 寻找文本的精确边界,text,flutter,Text,Flutter,我需要知道一段文本的确切界限——相当于Android。我意识到这在某种程度上与弗利特的设计背道而驰,但我以一种非传统的方式使用文本(比如说,文本被嵌入到艺术图片中的精确位置和大小) 我尝试了三种方法: textpainer的minintrisicwidth和高度。资料来源如下。这将生成一个四面都有空间的边界框: 我需要矩形的边正好对着“8”的黑色像素。(在这种特殊情况下,width和maxIntrinsicWidth给出的值与minIntrinsicWidth相同;preferredLine

我需要知道一段文本的确切界限——相当于Android。我意识到这在某种程度上与弗利特的设计背道而驰,但我以一种非传统的方式使用文本(比如说,文本被嵌入到艺术图片中的精确位置和大小)

我尝试了三种方法:

  • textpainer
    minintrisicwidth
    高度
    。资料来源如下。这将生成一个四面都有空间的边界框:

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

  • 段落
    getBoxesForRange
    ——与textpainer的结果基本相同

  • FittedBox
    ——无论
    BoxFit
    枚举值如何,都会留下空格。我用它作为出发点

textpainer
代码如下。(我意识到这是低效的;在得到所需的边界框之前,我不在乎。我使用场景/图片/等,希望在较低级别找到合适的功能。)


您可以使用TextPainter类来确定某些文本的宽度。 Flatter在布局期间使用它来确定文本小部件的大小


不确定TextPainter的结果是否包含少量填充,尽管如果包含,已经提出的解决方案也可能包含少量填充

要忽略该填充,您必须进行真正的低级别调用,因为
文本和空间实际上是一起绘制的。我试着在互联网上搜索是否有其他出路,但找不到任何能真正解决你问题的方法

我试着搜索flatterSDK(Widget_Library)的源代码,但我所能看到的是最终生成的Widget是一个
RichText
,其源代码消失在空气中。(我找不到这个小部件的定义,因为我刚刚在GitHub上搜索过它……在Android Studio中,你可以通过将鼠标悬停在它上面并按下
Ctrl+LeftClick
)来获得一些对它的引用……但我非常确定,它会带你到另一个未知的世界,因为字体是基于字体系列绘制的(这将是.ttf或.otf文件…无论哪种方式,它们都将和您引用的填充一起绘制)

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

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

我需要知道一段文字的确切界限

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

声明并初始化变量以存储GlobalKey

GlobalKey textKey = GlobalKey();
GlobalKey
传递给
Text
小部件的关键参数

Text(
  "hello",
   key: textKey,
 )
现在,我将使用
gesturedector
包装上述小部件,以打印上述小部件的宽度

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()
的帮助下,您可以获得该
文本所需的所有信息,并相应地绘制边界/矩形

注意:
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;

//左侧
对于(i=y1+1;ij){minR=j;break;}
//顶端
对于(i=x1+1;ij){minB=j;break;}
x1=x1+minL;
y1=y1+薄荷;
x2=x2-minR;
y2=y2-minB;

在实现上述逻辑时,确保没有其他重叠/底层小部件(Scaffold/Stack Combo)的颜色与文本颜色匹配。

您使用的是哪种字体?您确定字体本身在字形周围没有空间吗?我无法想象默认错误会像这样被窃听出来(使用ttf也可以吗?),但在任何情况下,我添加了
fontFamily:“Roboto”
,结果都是一样的。要清楚的是,Android的getTextBounds给出了矩形,这样每个边都会接触到“8”的黑色像素在链接到的图片中,我用Roboto.ok fair测试了这一点。我只是用衬线字体尝试了一下,一些字符确实碰到了框的水平边缘-但这对你没有多大帮助。似乎Flatter在内部做了一些事情来分隔字符…你可能会直接使用Flatter支持的东西。I cA.
// 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;