【问题标题】:How to remove the top and bottom space on textview of Android如何在Android的textview上删除顶部和底部空间
【发布时间】:2011-09-29 10:47:01
【问题描述】:

当我将下面的XML 包含到 layout 文件中时,我可以看到下图。如果你看到它,你会意识到TextView 有顶部和底部空间。

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="E1"
android:background="#ff00ff00"/>

我想删除空格。如何删除它?这叫什么? 如果有人有线索..请告诉我。提前致谢。

【问题讨论】:

标签: android textview padding android-custom-view


【解决方案1】:

试试android:includeFontPadding="false" 看看是否有帮助。根据我的经验,这会有所帮助,但无法将 TextView 尺寸减小到精确的像素完美文本大小。

唯一的替代方法可能会或可能不会产生更好的结果,那就是作弊并硬连线尺寸以匹配文本大小,例如"24sp" 而不是 "wrap_content" 的高度。

【讨论】:

  • +1 第二!请注意,我还必须包含 includeFontPadding="false",否则文本会被裁剪。
  • 这对我有用。但是如何删除上下文本上升和下降的顶部和底部空间?
  • 第二个剪辑了我的内容。
【解决方案2】:

我遇到了同样的问题。属性android:includeFontPadding="false" 对我不起作用。我已经通过这种方式解决了这个问题:

public class TextViewWithoutPaddings extends TextView {

    private final Paint mPaint = new Paint();

    private final Rect mBounds = new Rect();

    public TextViewWithoutPaddings(Context context) {
        super(context);
    }

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

    public TextViewWithoutPaddings(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        final String text = calculateTextParams();

        final int left = mBounds.left;
        final int bottom = mBounds.bottom;
        mBounds.offset(-mBounds.left, -mBounds.top);
        mPaint.setAntiAlias(true);
        mPaint.setColor(getCurrentTextColor());
        canvas.drawText(text, -left, mBounds.bottom - bottom, mPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        calculateTextParams();
        setMeasuredDimension(mBounds.width() + 1, -mBounds.top + 1);
    }

    private String calculateTextParams() {
        final String text = getText().toString();
        final int textLength = text.length();
        mPaint.setTextSize(getTextSize());
        mPaint.getTextBounds(text, 0, textLength, mBounds);
        if (textLength == 0) {
            mBounds.right = mBounds.left;
        }
        return text;
    }
}

【讨论】:

  • 很好的解决方案!尝试了不同的文字大小,并像魅力一样工作:)
  • 更新:在上面的代码中,当我使用小写的 q、g、y、p 时,它们会从底部被切掉。因此,将setMeasuredDimension(mBounds.width() + 1, -mBounds.top + 1); 更改为setMeasuredDimension(mBounds.width() + 1, -mBounds.top + mBounds.bottom);
  • 在性能方面看起来像在 onDraw() 中调用 calculateTextParams 并不是一个好主意。
  • 有效。但是如果你指定了android:fontFamily,那么将mPaint改成getPaint(),否则fontFamily是不被应用的。
  • 对我不起作用。它修剪了填充,但字体以它为中心也切掉了大部分字体。使用大字体 (56sp) 如果有影响的话。
【解决方案3】:

android:includeFontPadding="false" 非常好,但它并没有准确地得到它。有时您需要边界线的准确性,因此您可以通过应用负边距自己弄清楚:

尝试将底部和顶部边距设置为负值。

类似这样的:

android:layout_marginTop="-5dp"
android:layout_marginBottom="-5dp"

相应地调整值。

【讨论】:

  • 这正是我需要它做的。这应该是公认的答案。适用于运行 > API 21 的设备
  • 我仍在尝试合理化答案的赞成票数:))
  • 这很好用,但它是一个可扩展的解决方案吗?
  • 如果我的记忆在最新的约束布局负边距上正确运行,如果我错了,有人告诉我
【解决方案4】:

这是拯救我们一天的代码。它是使用来自maksimko 的单声道 C# 代码改编的:

public class TopAlignedTextView extends TextView {

    public TopAlignedTextView(Context context) {
        super(context);
    }

    /*This is where the magic happens*/
    @Override
    protected void onDraw(Canvas canvas){

        float offset = getTextSize() - getLineHeight();
        canvas.translate(0, offset);
        super.onDraw(canvas);
    }
}

仍然不得不使用 textView.setIncludeFontPadding(false),因为我们将 TextViews 与不同的字体大小对齐。

【讨论】:

  • 关心显示堆栈跟踪,而不是否决对许多用户有用的答案?
【解决方案5】:

我遇到了同样的问题。 这是一个很好的答案:How to align the text to top of TextView?

但是代码有点未完成,并且不支持所有字体大小。换行

int additionalPadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getContext().getResources().getDisplayMetrics());

int additionalPadding = getTextSize() - getLineHeight();

完整的 C# 代码(单声道)移除顶部偏移:

public class TextControl : TextView {
    public TextControl (Context context) : base (context)
    {
        SetIncludeFontPadding (false);
        Gravity = GravityFlags.Top;
    }

    protected override void OnDraw (Android.Graphics.Canvas canvas)
    {
        if (base.Layout == null)
            return;

        Paint.Color = new Android.Graphics.Color (CurrentTextColor);
        Paint.DrawableState = GetDrawableState ();

        canvas.Save ();

        var offset = TextSize - LineHeight;
        canvas.Translate (0, offset);

        base.Layout.Draw (canvas);

        canvas.Restore ();
    }
}

【讨论】:

  • 引用的例子在最后时刻反转了翻译量,这段代码没有。否则解决方案是正确的。
  • 我尝试了很多技巧,包括定义任意 TypedValue.COMPLEX_UNIT_DIP, 5 的引用示例。最后,这是唯一一个可以对齐 2 个不同 textSizes 的 TextView 的方法,而无需任何幻数。如果可以的话,我会给你+10 :)
【解决方案6】:

只是想向DynamicMind's answer 补充一点,您在 TextView 周围看到间距的原因是 9-patch 背景中的填充 他们默认使用。

9-patch 技术允许您指定一个内容区域,这实际上是填充。除非您明确设置视图的填充,否则将使用该填充。例如,当您以编程方式将 9-patch 背景设置为已设置填充的视图时,它们将被覆盖。反之亦然,如果您设置填充,它们会覆盖 9-patch 背景设置的内容。

不幸的是,在 XML 布局中无法确定这些操作的顺序。我认为从 TextViews 中删除背景会有所帮助:

android:background="@null"

【讨论】:

  • 这解释了为什么我没有在我的 xml 中设置填充。必须设置 padding=5dp 来覆盖默认的 padding form 9 补丁背景。谢谢
【解决方案7】:
public class TopAlignedTextView extends TextView {

    public TopAlignedTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TopAlignedTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs);
        setIncludeFontPadding(false); //remove the font padding
        setGravity(getGravity() | Gravity.TOP);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        TextPaint textPaint = getPaint();
        textPaint.setColor(getCurrentTextColor());
        textPaint.drawableState = getDrawableState();
        canvas.save();

        //remove extra font padding
        int yOffset = getHeight() - getBaseline();
        canvas.translate(0, - yOffset / 2);

        if (getLayout() != null) {
            getLayout().draw(canvas);
        }
        canvas.restore();
    }
}

【讨论】:

    【解决方案8】:

    您是否定义了布局边距? 例如:

    android:layout_marginTop="5dp"
    

    否则,如果您的文本视图被包裹在 LinearLayout 或其他容器中,那么该冷视图也有填充或边距。

    【讨论】:

      【解决方案9】:

      修改this回答一点点使用kotlin类并扩展AppCompatTextView,修剪垂直填充。

      它允许设置android:fontFamily。方法 calculateTextParams()onDraw() 移动以提高性能。未针对多行文本进行测试:

      import android.content.Context
      import android.graphics.Canvas
      import android.graphics.Rect
      import android.util.AttributeSet
      import androidx.appcompat.widget.AppCompatTextView
      
      class NoPaddingTextView : AppCompatTextView
      {
        private val boundsRect = Rect()
        private val textParams = calculateTextParams()
      
        constructor(context : Context?)
        : super(context)
      
        constructor(context : Context?, attrs : AttributeSet?)
        : super(context, attrs)
      
        constructor(context : Context?, attrs : AttributeSet?, defStyleAttr : Int)
        : super(context, attrs, defStyleAttr)
      
        override fun onDraw(canvas : Canvas)
        {
          with(boundsRect) {
            paint.isAntiAlias = true
            paint.color = currentTextColor
            canvas.drawText(textParams,
                            -left.toFloat(),
                            (-top - bottom).toFloat(),
                            paint)
          }
        }
      
        override fun onMeasure(widthMeasureSpec : Int, heightMeasureSpec : Int)
        {
          super.onMeasure(widthMeasureSpec, heightMeasureSpec)
          calculateTextParams()
          setMeasuredDimension(boundsRect.width() + 1, -boundsRect.top + 1)
        }
      
        private fun calculateTextParams() : String
        {
          return text.toString()
          .also {text ->
            text.length.let {textLength ->
              paint.textSize = textSize
              paint.getTextBounds(text, 0, textLength, boundsRect)
              if(textLength == 0) boundsRect.right = boundsRect.left
            }
          }
        }
      }
      

      【讨论】:

        【解决方案10】:
        android:background="@android:drawable/editbox_background"
        

        使用它根据你改变它你想要editbox_background。 因为android提供了一些像上面代码一样的内置背景,可以根据您的要求进行选择。 可能对你很有帮助。

        【讨论】:

          【解决方案11】:

          在 LinearLayout 中,默认填充可能是个问题。尝试将其设置为 0dp。它对我有用。

          【讨论】:

            【解决方案12】:

            TopAlignedTextView的answer代码:TopAlignedTextView@GitHub

            按布局使用:

            <com.github.captain_miao.view.TopAlignedTextView
                android:id="@+id/text_a"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:text="@string/text_demo_a"
            />
            

            【讨论】:

              【解决方案13】:

              我解决这个问题的方法很老套,但我设法通过将文本视图的高度设置为静态并摆弄它直到它几乎不适合文本来让文本位于我想要的位置。就我而言,我使用的字体样式的高度为 64sp,所以我将 textview 的高度设置为 50sp,它工作正常。我还必须将 foreground_gravity 设置为底部。

              【讨论】:

                【解决方案14】:

                android:includeFontPadding="false"

                【讨论】: