【问题标题】:How to reliably determine the width of a multi line string?如何可靠地确定多行字符串的宽度?
【发布时间】:2012-06-01 14:45:05
【问题描述】:

我正在尝试计算多行文本段落的宽度。据我所知,在 Android 中唯一可以做到这一点的类是 StaticLayout(或 DynamicLayout)类。使用此类时,我没有得到正确的文本 sn-p 长度,而是测量的尺寸有时更小,有时更大,具体取决于文本大小。

所以我基本上是在寻找一种可靠地测量多行文本字符串宽度的方法。

下图显示了在各种文本大小下测量的宽度与实际文本长度的差异。

屏幕截图是在自定义视图中运行以下代码创建的:

@Override
protected void onDraw( Canvas canvas ) {
  for( int i = 0; i < 15; i++ ) {
    int startSize = 10;
    int curSize = i + startSize;
    paint.setTextSize( curSize );
    String text = i + startSize + " - " + TEXT_SNIPPET;
    layout = new StaticLayout( text,
                               paint,
                               Integer.MAX_VALUE,
                               Alignment.ALIGN_NORMAL,
                               1.0f,
                               0.0f,
                               true );

    float top = STEP_DISTANCE * i;
    float measuredWidth = layout.getLineMax( 0 );
    canvas.drawRect( 0, top, measuredWidth, top + curSize, bgPaint );
    canvas.drawText( text, 0, STEP_DISTANCE * i + curSize, paint );
  }
}

【问题讨论】:

  • 你试过Paint.measureText()吗?
  • @Neevek 它产生相同的结果,但最重要的是它无法测量多行文本。
  • @AljoshaBre 我知道这个问题。我很久以前在底部添加了一个帖子。不过,提出的解决方案不适用于多行文本。
  • 怎么不适用?只需将宽度相加即可。在我看来getTextBounds() 有效。查看接受的答案,测量(红色矩形)看起来正确。

标签: android


【解决方案1】:

您可以尝试使用获取文本边界。

private int calculateWidthFromFontSize(String testString, int currentSize)
{
    Rect bounds = new Rect();
    Paint paint = new Paint();
    paint.setTextSize(currentSize);
    paint.getTextBounds(testString, 0, testString.length(), bounds);

    return (int) Math.ceil( bounds.width());
}

private int calculateHeightFromFontSize(String testString, int currentSize)
{
    Rect bounds = new Rect();
    Paint paint = new Paint();
    paint.setTextSize(currentSize);
    paint.getTextBounds(testString, 0, testString.length(), bounds);

    return (int) Math.ceil( bounds.height());
}

【讨论】:

    【解决方案2】:

    我遇到了一个类似的问题,即测量的文本宽度有一点偏差,一旦你为油漆设置了字体,这就会消失。 因此,在您使用 StaticLayout 中的 paint 对象之前,只需设置字体:

    textPaint.setTypeface(Typeface.create("sans-serif", Typeface.NORMAL))
    

    或者你想要的任何字体。

    【讨论】:

      【解决方案3】:

      这是一种获取任意文本长度的多行宽度的方法。 usableButtonWidth 可以是给定的文本空间。我使用了usableButtonWidth = 按钮的宽度 - 填充。但可以使用任何默认值。

      使用StaticLayout,您可以获得usableButtonWidth 的文本高度。然后我只是尝试通过在循环中将其减小 1px 来减小可用宽度。如果高度增加,那么我们就会知道之前使用的宽度是允许的最大宽度。

      将此值作为多行文本的宽度返回。

      private int getTextWidth(){
          if(this.getText().length() != 0){
              Paint textPaint = new Paint();
              Rect bounds = new Rect();
              textPaint.setTextSize(this.getTextSize());
              if(mTypeface != null){
                  textPaint.setTypeface(mTypeface);
              }
              String buttonText = this.getText().toString();
              textPaint.getTextBounds(buttonText, 0, buttonText.length(), bounds);
      
              if(bounds.width() > usableButtonWidth){
                  TextPaint longTextPaint = new TextPaint();
                  longTextPaint.setTextSize(this.getTextSize());
                  if(mTypeface != null){
                      longTextPaint.setTypeface(mTypeface);
                  }
                  StaticLayout staticLayout = new StaticLayout(this.getText(), longTextPaint, usableButtonWidth,
                          Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
                  int textLineCount = (int)Math.ceil(staticLayout.getHeight() / bounds.height());
                  int multiLineTextWidth = usableButtonWidth;
                  while ((int)Math.ceil(staticLayout.getHeight() / bounds.height()) == textLineCount && multiLineTextWidth > 1){
                      multiLineTextWidth--;
                      staticLayout = new StaticLayout(this.getText(), longTextPaint, multiLineTextWidth,
                              Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
                  }
                  return multiLineTextWidth+1;
              } else {
                  return bounds.width();
              }
          } else {
              return 0;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多