【问题标题】:Why does TextView have end padding when multi line?为什么TextView在多行时有结束填充?
【发布时间】:2020-10-28 23:00:45
【问题描述】:

如果您有一个带有layout_width="wrap_content" 的 TextView,并且它必须换行以包含文本,那么它将调整其宽度以用完所有可用空间(考虑边距等)。但是为什么视图的末尾有填充?我只是告诉它wrap_content,所以它应该包装那个内容!这似乎是一个错误,这在股票 Messenger 应用程序的聊天 UI 中可见。 (虽然图片来自我自己的应用程序。但额外的空间绝对不是 9 补丁中的。)

有什么解决方法吗?

更新:响应者/评论者错过了重点。也许我上传的图片具有误导性,因为它是从我的应用程序中设计的。任何 TextView 都会出现此问题,您可以通过设置背景样式来查看视图边界将不再紧密。我上传了一张不同的图片。这是图像中 TextViews 的 XML:

        <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="20dp"
    android:layout_marginStart="20dp"
    android:background="#dddddd"
    android:text="This doesn't wrap"
    android:layout_marginTop="20dp"
    android:layout_marginBottom="20dp"
    android:layout_gravity="center_horizontal"
    />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="20dp"
    android:layout_marginStart="20dp"
    android:layout_gravity="center_horizontal"
    android:background="#dddddd"
    android:text="This wraps and look, the bounds does not fit tight against the right edge of text"
    />

【问题讨论】:

  • 也许这个词不合适?也许你的 9patch 有一些内在背景?
  • 我更新了我的答案,它现在应该涵盖你的观点

标签: android textview


【解决方案1】:

我发现所选答案很有帮助,尽管它并没有完全考虑填充。我将选定的答案与this post's answer 结合起来,提出了一个适用于填充的视图。仅供参考,另一个帖子的答案有一个缺陷,即视图有时会在最后被截断几个像素。

public class TightTextView extends TextView {
  public TightTextView(Context context) {
    super(context);
  }

  public TightTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public TightTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int specModeW = MeasureSpec.getMode(widthMeasureSpec);
    if (specModeW != MeasureSpec.EXACTLY) {
      Layout layout = getLayout();
      if (layout != null) {
        int w = (int) Math.ceil(getMaxLineWidth(layout)) + getCompoundPaddingLeft() + getCompoundPaddingRight();
        if (w < getMeasuredWidth()) {
          super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST),
          heightMeasureSpec);
        }
      }
    }
  }

  private float getMaxLineWidth(Layout layout) {
    float max_width = 0.0f;
    int lines = layout.getLineCount();
    for (int i = 0; i < lines; i++) {
      if (layout.getLineWidth(i) > max_width) {
        max_width = layout.getLineWidth(i);
      }
    }
    return max_width;
  }
}

【讨论】:

  • 感谢您帮助改进解决方案,解决绝对令人讨厌的问题。
  • 如果 TightTextView 位于 ConstraintLayout 内,则并不总是有效,可能取决于 TightTextView 元素的属性。
【解决方案2】:

起初,当看到您的帖子时,我认为问题是因为标准 Android TextView 在其基本样式中定义了一些默认填充。如果要删除它,可以尝试以下方法:

android:paddingEnd="0dp"

android:paddingRight="0dp"

由于您的帖子已更新,我了解您的问题不是来自填充,而是来自自动换行。确实,当有几行要显示时,Android TextView 会在宽度上使用整个可用空间。

in this post 所述,对此没有标准解决方案,您需要自定义文本视图以在填充后固定其宽度。

覆盖你的 textView 的 onMeasure 方法,如下所示(灵感来自“天空”答案):

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int specModeW = MeasureSpec.getMode(widthMeasureSpec);
    if (specModeW != MeasureSpec.EXACTLY) {
        Layout layout = getLayout();
        int linesCount = layout.getLineCount();
        if (linesCount > 1) {
            float textRealMaxWidth = 0;
            for (int n = 0; n < linesCount; ++n) {
                textRealMaxWidth = Math.max(textRealMaxWidth, layout.getLineWidth(n));
            }
            int w = (int) Math.ceil(textRealMaxWidth);
            if (w < getMeasuredWidth()) {
                super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST),
                        heightMeasureSpec);
            }
        }
    }
}

【讨论】:

  • 谢谢 我尝试搜索相同的问题,但没有出现。肯定是同样的问题。很遗憾看到 3 年后,我们仍然需要解决这个问题。
【解决方案3】:

很确定这是因为“反对”不适合“适合”一词和右边缘之间。如果您想对此进行测试,请尝试将您的文本更改为一堆 |,每个之间有一个空格。

【讨论】:

    【解决方案4】:

    我最近在为应用程序开发聊天气泡视图时遇到了类似的问题,因此我使用了公认的解决方案中的想法以及 @hoffware 的改进,并在 Kotlin 中重新实现了它们。

    import android.content.Context
    import android.util.AttributeSet
    import android.view.View.MeasureSpec.*
    import androidx.appcompat.widget.AppCompatTextView
    import kotlin.math.ceil
    
    class TightTextView
    @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = android.R.attr.textViewStyle
    ) : AppCompatTextView(context, attrs, defStyleAttr) {
    
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    
            val lineCount = layout.lineCount
            if (lineCount > 1 && getMode(widthMeasureSpec) != EXACTLY) {
                val textWidth = (0 until lineCount).maxOf(layout::getLineWidth)
                val padding = compoundPaddingLeft + compoundPaddingRight
                val w = ceil(textWidth).toInt() + padding
    
                if (w < measuredWidth) {
                    val newWidthMeasureSpec = makeMeasureSpec(w, AT_MOST)
                    super.onMeasure(newWidthMeasureSpec, heightMeasureSpec)
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-10
      • 2011-09-23
      • 2019-07-08
      • 2013-06-21
      • 2013-06-08
      • 1970-01-01
      • 2015-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多