261

When I have a TextView with a \n in the text,, on the right I have two singleLine TextViews, one below the other with no spacing in between. I have set the following for all three TextViews.

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.

The second line of the left TextView is a little higher than the second line of the bottom right TextView.

It seems that there is some kind of hidden padding on the top and the bottom of the TextViews. How can I remove that?

rehman_00001
  • 1,299
  • 1
  • 15
  • 28
700 Software
  • 85,281
  • 83
  • 234
  • 341

25 Answers25

621
setIncludeFontPadding (boolean includepad)

or in XML this would be:

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. The default is true.

JKennedy
  • 18,150
  • 17
  • 114
  • 198
user634545
  • 9,099
  • 5
  • 29
  • 40
  • 6
    But it seems always has a `1dp` top/bottom padding, am i wrong?(I use `Developer options -> Show layout bounds`) – Autobots Jul 01 '14 at 11:34
  • 133
    `includeFontPadding="false"` does remove some of the space, but not all of it. very strange. – theblang Jul 07 '14 at 15:59
  • 7
    This can be a double edged sword. `includeFontPadding` is great for removing any additional padding from the font itself but it can cause issues in languages that have ascenders and descenders. I would make sure if you do this that you test languages like spanish and thai if you support them. – Elliott Jan 30 '15 at 01:41
  • 1
    android:layout_marginTop="-5dp" android:layout_marginBottom="-5dp" (Optional) has worked for me. – Rohit Mandiwal Feb 08 '15 at 05:46
  • 4
    After setting runtime it's not taking top padding but bottom padding still there, even left and right padding as well? any suggestion? – CoDe Apr 23 '15 at 12:45
  • 2
    Pay attention because this will remove the padding needed to display some bottom parts of letters like "p", "y", g. These letters will be partially cut off. – vovahost Feb 07 '16 at 18:43
  • For normal alphabets A-Z, a-z, includeFontPadding = false should work nicely. @mattblang The extra tiny bit of padding is reserved for things like $ sign. So includeFontPadding should work nicely for a standard english keyboard. But for foreign languages like a Chinese character, you might get into cropping problem. – Vennsoh Apr 27 '16 at 00:17
  • 7
    This didn't work for me. I don't understand what I'm missing. I still have unwanted space at the bottom of my TextView – Marty Miller Mar 14 '17 at 23:42
  • 1
    @MartyMiller add a attribute on your textview, android:letterSpacing="0" – Jack Aug 12 '21 at 00:04
  • If you are seeking for something you will get it as long as you don't stop. I am feeling lucky. From the past few days I got mad and was thinking like if it was the problem of line height. Thanks! – Maseed Nov 09 '22 at 08:15
49

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

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

Adding these two lines to TextView xml will do the work.
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

Mohammed Atif
  • 4,383
  • 7
  • 28
  • 57
42

I feel your pain. I've tried every answer above, including the setIncludeFontPadding to false, which did nothing for me.

My solution? layout_marginBottom="-3dp" on the TextView gives you a solution for the bottom, BAM!

Although, -3dp on layout_marginTop fails....ugh.

Praful Bhatnagar
  • 7,425
  • 2
  • 36
  • 44
hunterp
  • 15,716
  • 18
  • 63
  • 115
34

You can try to use this attribute(ConstraintLayout):layout_constraintBaseline_toBaselineOf

Like this:

app:layout_constraintBaseline_toBaselineOf="@+id/textView"

enter image description here

enter image description here

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
windplume
  • 451
  • 4
  • 6
  • Tnx. this also helped me in an other problem which there is a textview that has multisizeed text. with this solution I can use multiple textview with there different textsizes and with the help of base line constraints I can show them like its one textview. – Reza Oct 23 '20 at 07:20
28

Updated XML

android:fontFamily="monospace"
android:includeFontPadding="false"
Ali
  • 2,702
  • 3
  • 32
  • 54
SJJ
  • 417
  • 4
  • 5
  • 1
    Hi, welcome to Stack Overflow! When you answer a question you should include some kind of explanation, like what the author did wrong and what you did to fix it. I'm telling you this because your answer has been flagged as low-quality and is currently being reviewed. You can [edit] your answer by clicking the "Edit" button. – Federico Grandi May 19 '20 at 20:15
  • 2
    Actually changing android:fontFamily is not necessary if you already have correct font. Basicly android:includeFontPadding is the only thing necessary and it has been mentioned in previous answers from the thread. – Darek Deoniziak May 21 '20 at 06:30
  • @DarekDeoniziak Some fonts have spaces – SJJ May 21 '20 at 08:57
20

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:

XML

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

Kotlin

text.firstBaselineToTopHeight = 0
text.includeFontPadding = false
Tim
  • 41,901
  • 18
  • 127
  • 145
Mario Lenci
  • 10,422
  • 5
  • 39
  • 50
20

Add android:includeFontPadding="false" to see if it helps.And make text view size same as that of text size rather than "wrap content".It will definitely work.

Sahil Bansal
  • 609
  • 8
  • 6
14

I remove the spacing in my custom view -- NoPaddingTextView.

https://github.com/SenhLinsh/NoPaddingTextView

enter image description here

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;
    }
}
Linsh
  • 141
  • 1
  • 6
  • 6
    While this code may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) of how and why this solves the problem would really help to improve the quality of your post (and get up-votes). Remember that you are answering the question for readers in the future, not just the person asking now! Please edit your answer to add explanation, and give an indication of what limitations and assumptions apply. – Makyen Mar 03 '17 at 03:27
  • 1
    Subclassing from `TextView` and especially overriding `onDraw` seems to me as a very bad idea. In such a way you will lose all the fancy decorations that Google does or will do in the future releases (and of course no features from the `AppCompat` as well) and you can't match OEM-specific style of this control on particular device if there is one. – SergGr Mar 03 '17 at 03:32
  • I changed in a new way. – Linsh Mar 29 '17 at 02:08
  • 1
    It may work but creating new TextView on every measure event is not memory efficient. Android Lint discourages creating new objects in draw(), onDraw() or any method that is related to layout and can be called unknown times during layout. – Adil Soomro Apr 25 '20 at 17:32
14

This annoyed me too, and the answer I found was that there is actually additional space in the font itself, not the TextView. It is rather irritating, coming from a document publishing background, the limited amount of control you have with Android over typographic elements. I'd recommend using a custom typeface (such as Bitstream Vera Sans, which is licensed for redistribution) that may not have this issue. I'm not sure specifically whether or not it does, though.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • do you have some free font to point me to? I need to have no margin on top without assigning negative margins! Thank you! – vault Jan 23 '13 at 09:51
6

Since my requirement is override the existing textView get from findViewById(getResources().getIdentifier("xxx", "id", "android"));, so I can't simply try onDraw() of other answer.

But I just figure out the correct steps to fixed my problem, here is the final result from Layout Inspector:

enter image description here

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:

enter image description here

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);:

enter image description here

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

enter image description here

Without setIncludeFontPadding(false);:

enter image description here

Without 3 of them (i.e. the original):

enter image description here

林果皞
  • 7,539
  • 3
  • 55
  • 70
5
<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. Other views can align itself using the bottom of the ImageView which itself is the same as the TextView's baseline.

This however only fixes the padding bottom not the top.

Viven
  • 627
  • 7
  • 14
3

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

ScreenShot-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.

Wei Wei
  • 31
  • 2
1

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

phnghue
  • 1,578
  • 2
  • 10
  • 9
1

Only thing that worked is

android:lineSpacingExtra="-8dp"
Antonis Radz
  • 3,036
  • 1
  • 16
  • 34
1

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]. 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 may end up 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 and ascenders / descenders are clipped.

[1] I suppose one could package their own fonts with compacted ascenders and descenders.

Jeffrey Blattman
  • 22,176
  • 9
  • 79
  • 134
  • I was really confused as to why these fonts always have padding but the UI designs don't. Thank you for bringing this aspect to light. – Atul Jul 18 '23 at 20:03
0

You might want to try aligning the bottom of the left text view with the bottom of the 2nd right text view.

Jems
  • 11,560
  • 1
  • 29
  • 35
  • But then the top line would not line up. And actually I do not care about them lining up as much as I would really like to remove the spacing. – 700 Software Jan 22 '11 at 15:50
0

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.

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!

The only suggestion I would have is to create your own 9 patch files and use them in your application.

Ahhh the pains that are Android.

Edited: Clarify padding vs white space.

user432209
  • 20,007
  • 10
  • 56
  • 75
0

This trick worked for me (for 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...)

enter image description here

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>
ultra.deep
  • 1,699
  • 1
  • 19
  • 23
0

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.

Jack
  • 142
  • 9
0

This worked for me:

android:minHeight="0dp"
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/32044921) – Shabbir Dhangot Jun 24 '22 at 05:03
0

You can try to use this attribute(ConstraintLayout): layout_constraintBaseline_toBaselineOf

Tyhoo Wu
  • 1
  • 1
0

You can take reference from the below XML file where the imageView will start from the bottom of baseline of the text of Textview.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageViewHello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img_star_05"
        android:baselineAlignBottom="true"
        android:layout_alignBaseline="@+id/textViewHello"
        android:layout_toRightOf="@+id/textViewHello"
        android:layout_toEndOf="@+id/textViewHello" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textViewHello"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

</RelativeLayout>

Alternatively, assuming for most of your use cases you would need the bottom of your imageView to be aligned with the baseline, for that you can put the below code in your TextView.

android:layout_alignBaseline="@+id/imageViewHello"
sahil333
  • 11
  • 2
-1

See this:

Align ImageView with EditText horizontally

It seems that the background image of EditText has some transparent pixels which also add padding.

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). That's can be made setting android:background XML attribute.

android:background="@drawable/myEditBackground"
Community
  • 1
  • 1
User
  • 31,811
  • 40
  • 131
  • 232
-1

It's working for me

just add two lines to your Textview

 android:includeFontPadding="false"
 android:lineSpacingMultiplier="0.8"
<TextView
            android:id="@+id/searchByItemTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:fontFamily="@font/dm_sans"
            android:includeFontPadding="false"
            android:lineSpacingMultiplier="0.8"
            android:paddingVertical="3dp"
            android:paddingStart="4dp"
            android:paddingEnd="6dp"
            android:text="@string/date_of_birth"
            android:textColor="@color/text_black"
            android:textSize="16dp" />

note: don't use android:textAppearance=""

Maruf Alam
  • 228
  • 4
  • 10
-9

Use this in your ImageView xml

android:adjustViewBounds="true"