简体   繁体   English

Android:TextView:删除顶部和底部的间距和填充

[英]Android: TextView: Remove spacing and padding on top and bottom

When I have a TextView with a \n in the text,, on the right I have two singleLine TextView s, one below the other with no spacing in between.当我有一个TextView在文本中有一个\n时,在右边我有两个singleLine TextView s,一个在另一个下面,中间没有间距。 I have set the following for all three TextView s.我为所有三个TextView设置了以下内容。

android:lineSpacingMultiplier="1" 
android:lineSpacingExtra="0pt" 
android:paddingTop="0pt" 
android:paddingBottom="0pt"

The first line of the left TextView lines up perfectly with the top right TextView .左边的第一行TextView与右上角的TextView完美对齐。

The second line of the left TextView is a little higher than the second line of the bottom right TextView .左边第二行TextView比右下第二行TextView高一点。

It seems that there is some kind of hidden padding on the top and the bottom of the TextView s.似乎在TextView的顶部和底部有某种隐藏的填充。 How can I remove that?我怎样才能删除它?

setIncludeFontPadding (boolean includepad)

or in XML this would be:或者在XML中,这将是:

android:includeFontPadding="false"

Set whether the TextView includes extra top and bottom padding to make room for accents that go above the normal ascent and descent.设置TextView是否包含额外的顶部和底部填充,以便为超出正常上升和下降的重音腾出空间。 The default is true.默认值为真。

I searched a lot for proper answer but no where I could find an Answer which could exactly remove all the padding from the TextView , but finally after going through the official doc got a work around for Single Line Texts我搜索了很多正确的答案,但没有找到可以从TextView中完全删除所有填充的答案,但最终在通过官方文档后,解决了单行文本

android:includeFontPadding="false"
android:lineSpacingExtra="0dp"

Adding these two lines to TextView xml will do the work.将这两行添加到TextView xml 就可以了。
First attribute removes the padding reserved for accents and second attribute removes the spacing reserved to maintain proper space between two lines of text.第一个属性删除为重音保留的填充,第二个属性删除保留的间距以保持两行文本之间的适当间距。

Make sure not to add lineSpacingExtra="0dp" in multiline TextView as it might make the appearance clumsy确保不要在多行 TextView 中添加lineSpacingExtra="0dp"因为它可能会使外观笨拙

I feel your pain.我感觉到你的痛苦。 I've tried every answer above, including the setIncludeFontPadding to false, which did nothing for me.我已经尝试了上面的每个答案,包括将setIncludeFontPadding为 false,这对我没有任何帮助。

My solution?我的解决方案? layout_marginBottom="-3dp" on the TextView gives you a solution for the bottom, BAM! TextView上的layout_marginBottom="-3dp"为您提供了底部的解决方案,BAM!

Although, -3dp on layout_marginTop fails....ugh.虽然, layout_marginTop 上的layout_marginTop失败了......呃。

You can try to use this attribute(ConstraintLayout): layout_constraintBaseline_toBaselineOf你可以尝试使用这个属性(ConstraintLayout): layout_constraintBaseline_toBaselineOf

Like this:像这样:

app:layout_constraintBaseline_toBaselineOf="@+id/textView"应用程序:layout_constraintBaseline_toBaselineOf="@+id/textView"

在此处输入图像描述

在此处输入图像描述

Updated XML更新的 XML

android:fontFamily="monospace"
android:includeFontPadding="false"

If you use AppCompatTextView ( or from API 28 onward ) you can use the combination of those 2 attributes to remove the spacing on the first line:如果您使用AppCompatTextView (或从API 28开始),您可以使用这两个属性的组合来删除第一行的间距:

XML XML

android:firstBaselineToTopHeight="0dp"
android:includeFontPadding="false"

Kotlin科特林

text.firstBaselineToTopHeight = 0
text.includeFontPadding = false

添加 android:includeFontPadding="false" 看看是否有帮助。并使文本视图大小与文本大小相同,而不是“包装内容”。它肯定会工作。

I remove the spacing in my custom view -- NoPaddingTextView.我删除了自定义视图中的间距——NoPaddingTextView。

https://github.com/SenhLinsh/NoPaddingTextView https://github.com/SenhLinsh/NoPaddingTextView

在此处输入图像描述

package com.linsh.nopaddingtextview;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.TextView;

/**
 * Created by Senh Linsh on 17/3/27.
 */

public class NoPaddingTextView extends TextView {

    private int mAdditionalPadding;

    public NoPaddingTextView(Context context) {
        super(context);
        init();
    }


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

    private void init() {
        setIncludeFontPadding(false);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int yOff = -mAdditionalPadding / 6;
        canvas.translate(0, yOff);
        super.onDraw(canvas);
    }

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

        int mode = MeasureSpec.getMode(heightMeasureSpec);
        if (mode != MeasureSpec.EXACTLY) {
            int measureHeight = measureHeight(getText().toString(), widthMeasureSpec);

            int height = measureHeight - mAdditionalPadding;
            height += getPaddingTop() + getPaddingBottom();
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private int measureHeight(String text, int widthMeasureSpec) {
        float textSize = getTextSize();

        TextView textView = new TextView(getContext());
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        textView.setText(text);
        textView.measure(widthMeasureSpec, 0);
        return textView.getMeasuredHeight();
    }

    private int getAdditionalPadding() {
        float textSize = getTextSize();

        TextView textView = new TextView(getContext());
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        textView.setLines(1);
        textView.measure(0, 0);
        int measuredHeight = textView.getMeasuredHeight();
        if (measuredHeight - textSize > 0) {
            mAdditionalPadding = (int) (measuredHeight - textSize);
            Log.v("NoPaddingTextView", "onMeasure: height=" + measuredHeight + " textSize=" + textSize + " mAdditionalPadding=" + mAdditionalPadding);
        }
        return mAdditionalPadding;
    }
}

This annoyed me too, and the answer I found was that there is actually additional space in the font itself, not the TextView.这也让我很恼火,我发现的答案是字体本身实际上有额外的空间,而不是 TextView。 It is rather irritating, coming from a document publishing background, the limited amount of control you have with Android over typographic elements.这是相当恼人的,来自文档发布背景,您对 Android 对排版元素的控制量有限。 I'd recommend using a custom typeface (such as Bitstream Vera Sans, which is licensed for redistribution) that may not have this issue.我建议使用可能没有此问题的自定义字体(例如 Bitstream Vera Sans,它已获得再分发许可)。 I'm not sure specifically whether or not it does, though.不过,我不确定它是否确实如此。

Since my requirement is override the existing textView get from findViewById(getResources().getIdentifier("xxx", "id", "android"));由于我的要求是覆盖现有的 textView 从findViewById(getResources().getIdentifier("xxx", "id", "android")); , so I can't simply try onDraw() of other answer. ,所以我不能简单地尝试其他答案的onDraw()

But I just figure out the correct steps to fixed my problem, here is the final result from Layout Inspector:但我只是想出了解决问题的正确步骤,这是 Layout Inspector 的最终结果:

在此处输入图像描述

Since what I wanted is merely remove the top spaces, so I don't have to choose other font to remove bottom spaces.由于我想要的只是删除顶部空格,所以我不必选择其他字体来删除底部空格。

Here is the critical code to fixed it:这是修复它的关键代码:

Typeface mfont = Typeface.createFromAsset(getResources().getAssets(), "fonts/myCustomFont.otf");
myTextView.setTypeface(mfont);

myTextView.setPadding(0, 0, 0, 0);

myTextView.setIncludeFontPadding(false);

The first key is set custom font "fonts/myCustomFont.otf" which has the space on bottom but not on the top, you can easily figure out this by open otf file and click any font in android Studio:第一个键是设置自定义字体“fonts/myCustomFont.otf”,它在底部有空间但在顶部没有空间,您可以通过打开 otf 文件并单击 android Studio 中的任何字体轻松找出这一点:

在此处输入图像描述

As you can see, the cursor on the bottom has extra spacing but not on the top, so it fixed my problem.如您所见,底部的光标有额外的间距,但顶部没有,所以它解决了我的问题。

The second key is you can't simply skip any of the code , otherwise it might not works.第二个关键是你不能简单地跳过任何代码,否则它可能不起作用。 That's the reason you can found some people comment that an answer is working and some other people comment that it's not working.这就是为什么您会发现有些人评论说答案有效,而其他人评论说答案无效。

Let's illustrated what will happen if I remove one of them.让我们说明如果我删除其中一个会发生什么。

Without setTypeface(mfont);没有setTypeface(mfont); :

在此处输入图像描述

Without setPadding(0, 0, 0, 0);没有setPadding(0, 0, 0, 0); :

在此处输入图像描述

Without setIncludeFontPadding(false);没有setIncludeFontPadding(false); :

在此处输入图像描述

Without 3 of them (ie the original):没有其中的 3 个(即原件):

在此处输入图像描述

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/baselineImage"
        android:includeFontPadding="false" />

    <ImageView
        android:id="@+id/baselineImage"
        android:layout_width="1dp"
        android:layout_height="1dp"
        android:baselineAlignBottom="true"
        android:layout_alignParentBottom="true" />

    <!-- This view will be exactly 10dp below the baseline of textView -->
    <View
        android:id="@+id/view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/baselineImage" />

</RelativeLayout>

With an extra ImageView we can set the TextView to be baseline aligned with the ImageView and set the android:baselineAlignBottom on the ImageView to true, which will make the baseline of ImageView to bottom.使用额外的 ImageView,我们可以将 TextView 设置为与 ImageView 对齐的基线,并将 ImageView 上的android:baselineAlignBottom设置为 true,这将使 ImageView 的基线位于底部。 Other views can align itself using the bottom of the ImageView which itself is the same as the TextView's baseline.其他视图可以使用 ImageView 的底部对齐自身,该底部本身与 TextView 的基线相同。

This however only fixes the padding bottom not the top.然而,这只修复了填充底部而不是顶部。

I think this problem can be solved in this way:我认为这个问题可以这样解决:

 <TextView
        android:id="@+id/leftText"
        android:includeFontPadding="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30dp"
        android:text="Hello World!\nhello world" />

 <TextView
        android:id="@+id/rightUpperText"
        android:includeFontPadding="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/leftText"
        android:layout_alignTop="@+id/leftText"
        android:textSize="30dp"
        android:text="Hello World!" />

 <TextView
        android:id="@+id/rightLowerText"
        android:includeFontPadding="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/leftText"
        android:layout_below="@+id/rightUpperText"
        android:textSize="30dp"
        android:text="hello world" />

Those are the results:这些是结果:

ScreenShot-1截图-1

ScreenShot-3截图 3

Though the line of special characters in rightLowerText looks a little bit higher than the second line of leftText, their baselines are stilled aligned.尽管 rightLowerText 中的特殊字符行看起来比 leftText 的第二行高一点,但它们的基线仍然对齐。

Simple method worked:简单的方法有效:

setSingleLine();
setIncludeFontPadding(false);

If it not worked, then try to add this above that code:如果它不起作用,请尝试在该代码上方添加此代码:

setLineSpacing(0f,0f);
// and set padding and margin to 0

If you need multi line, maybe you'll need to calculate exactly the height of padding top and bottom via temp single line TextView (before and after remove padding) , then apply decrease height result with negative padding or some Ghost Layout with translate Y. Lol如果您需要多行,也许您需要通过临时单行 TextView(删除填充之前和之后)精确计算填充顶部和底部的高度,然后使用负填充或一些带有平移 Y 的幽灵布局应用降低高度结果。哈哈

唯一有效的是

android:lineSpacingExtra="-8dp"

您可能想尝试将左侧文本视图的底部与第二个右侧文本视图的底部对齐。

To my knowledge this is inherent to most widgets and the amount of "padding" differs among phone manufacturers.据我所知,这是大多数小部件所固有的,并且手机制造商之间的“填充”量不同。 This padding is really white space between the image border and the image in the 9 patch image file.这个填充实际上是图像边框和 9 补丁图像文件中的图像之间的空白。

For example on my Droid X, spinner widgets get extra white space than buttons, which makes it look awkward when you have a spinner inline with a button, yet on my wife's phone the same application doesn't have the same problem and looks great!例如,在我的 Droid X 上,微调器小部件比按钮获得更多的空白,这使得当你有一个与按钮内联的微调器时看起来很尴尬,但在我妻子的手机上,相同的应用程序没有同样的问题,而且看起来很棒!

The only suggestion I would have is to create your own 9 patch files and use them in your application.我唯一的建议是创建您自己的 9 个补丁文件并在您的应用程序中使用它们。

Ahhh the pains that are Android.啊,Android的痛苦。

Edited: Clarify padding vs white space.编辑:澄清填充与空白。

This trick worked for me (for min-sdk >= 18 ).这个技巧对我有用(对于min-sdk >= 18 )。

I used android:includeFontPadding="false" and a negative margin like android:layout_marginTop="-11dp" and put my TextView inside a FrameLayout ( or any ViewGroup... )我使用了android:includeFontPadding="false"负边距,如android:layout_marginTop="-11dp"并将我的TextView放入FrameLayout或任何 ViewGroup...

在此处输入图像描述

and finally sample codes:最后是示例代码:

<LinearLayout
    android:layout_width="60dp"
    android:layout_height="wrap_content"
    >

    <TextView
        style="@style/MyTextViews.Bold"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/yellow"
        android:textSize="48sp"
        android:layout_marginTop="-11dp"
        android:includeFontPadding="false"
        tools:text="1"/>
</LinearLayout>

Use constraintlayout as your root view then add a guideline helper.使用约束布局作为你的根视图,然后添加一个指南助手。

Example:例子:

<TextView
 android:id="@+id/textView1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" 
 app:layout_constraintTop_toTopOf="parent" 
 app:layout_constraintStart_toStartOf="parent" />

<TextView
 android:id="@+id/textView2"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" 
 app:layout_constraintStart_toStartOf="parent"
 app:layout_constraintTop_toBottomOf="@+id/guideline" />

<androidx.constraintlayout.widget.Guideline
 android:id="@+id/guideline"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:orientation="horizontal"
 app:layout_constraintGuide_begin="20dp" />

Attribute layout_constraintGuide_begin value is just example, it depend on your needs.属性 layout_constraintGuide_begin 值只是示例,它取决于您的需要。

You can partially resolve this with some of the hacks listed here (negative margins, font padding, etc), but you can't get around the size of the font itself[1].您可以使用此处列出的一些技巧(负边距、字体填充等)部分解决此问题,但您无法绕过字体本身的大小 [1]。 The fixed height of each "cell" of a font must be large enough to accommodate the tallest character, in all languages .字体的每个“单元格”的固定高度必须足够大,以容纳所有语言中最高的字符。

If you employ the hacks listed in other answers the font can be clipped.如果您使用其他答案中列出的技巧,则可以剪裁字体。

The solution is to explain to your designers that this is how fonts are packaged, and to have them account for this in their designs.解决方案是向您的设计师解释这是字体的打包方式,并让他们在设计中考虑到这一点。 Don't hack things up now to have bugs filed down the road when it's translated to other languages.当它被翻译成其他语言时,现在不要把事情搞砸,以便在路上提交错误。

[1] I suppose one could package their own fonts with compacted ascenders and descenders. [1] 我想人们可以用压缩的上升和下降来打包自己的字体。

这对我有用:

android:minHeight="0dp"

You can try to use this attribute(ConstraintLayout): layout_constraintBaseline_toBaselineOf您可以尝试使用此属性(ConstraintLayout): layout_constraintBaseline_toBaselineOf

See this:看到这个:

Align ImageView with EditText horizontally 将 ImageView 与 EditText 水平对齐

It seems that the background image of EditText has some transparent pixels which also add padding.似乎 EditText 的背景图像具有一些透明像素,这些像素也添加了填充。

A solution is to change the default background of EditText to something else (or nothing, but no background for a EditText is probably not acceptable).一种解决方案是将 EditText 的默认背景更改为其他内容(或不更改任何内容,但 EditText 没有背景可能是不可接受的)。 That's can be made setting android:background XML attribute.这可以通过设置 android:background XML 属性来实现。

android:background="@drawable/myEditBackground"

When I have a TextView with a \\n in the text,, on the right I have two singleLine TextView s, one below the other with no spacing in between.当我有一个TextView带有\\nTextView时,在右侧,我有两个singleLine TextView ,一个在另一个之下,并且两者之间没有间隔。 I have set the following for all three TextView s.我为所有三个TextView设置了以下内容。

android:lineSpacingMultiplier="1" 
android:lineSpacingExtra="0pt" 
android:paddingTop="0pt" 
android:paddingBottom="0pt"

The first line of the left TextView lines up perfectly with the top right TextView .TextView的第一行与右上TextView完美TextView

The second line of the left TextView is a little higher than the second line of the bottom right TextView .左侧TextView的第二行比右下方TextView的第二行高一点。

It seems that there is some kind of hidden padding on the top and the bottom of the TextView s.似乎在TextView的顶部和底部都有某种隐藏的填充。 How can I remove that?我该如何删除?

Use this in your ImageView xml在您的 ImageView xml 中使用它

android:adjustViewBounds="true"机器人:adjustViewBounds =“真”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM