How to remove the top and bottom space on textview of Android

51,861

Solution 1

Try android:includeFontPadding="false" to see if it helps. In my experience that will help a little bit, but there's no way of reducing the TextView dimensions to the exact pixel-perfect text size.

The only alternative, which may or may not give better results, is to cheat a bit and hard-wire the dimensions to match the text size, e.g. "24sp" instead of "wrap_content" for the height.

Solution 2

I had the same problem. Attribute android:includeFontPadding="false" does not work for me. I've solved this problem in this way:

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;
    }
}

Solution 3

android:includeFontPadding="false" is pretty good but it does not get it precisely. sometimes you want border line accuracy so you can figure it out yourself by applying negative margins:

try setting your bottom and top margins to a negative value.

something like this:

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

adjust the values accordingly.

Solution 4

This is the code that saved our day. It was adapted using mono C# code from maksimko:

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

Still had to play around with textView.setIncludeFontPadding(false) because we were aligning TextViews with different font sizes.

Solution 5

I faced the same problem. Here's a good answer: How to align the text to top of TextView?

But code is little unfinished and don't support all font sizes. Change the line

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

to

int additionalPadding = getTextSize() - getLineHeight();

Complete C# code (mono) removes top offset:

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 ();
    }
}
Share:
51,861
mooongcle
Author by

mooongcle

Updated on July 08, 2022

Comments

  • mooongcle
    mooongcle almost 2 years

    When I include the below XML to layout file, I can see the below image. If you see it, you could realize that the TextView has top and bottom space.

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

    enter image description here

    I wish to remove the space. How to remove it? What is it called? If anyone has clue.. please let me know. Thanks in advance.

  • Kyle Ivey
    Kyle Ivey almost 11 years
    The example referenced inverts the translation amount at the last moment, this code does not. Solution is correct otherwise.
  • Enrichman
    Enrichman about 10 years
    +1 for the second! Just note that I also had to include the includeFontPadding="false", or the text will be cropped a bit.
  • Henrique de Sousa
    Henrique de Sousa over 9 years
    I have tried a lot of hacks, including the example referenced that defined the arbitrary TypedValue.COMPLEX_UNIT_DIP, 5. Finally, this is the only one that works in order to align 2 TextViews of different textSizes, without any magic number whatsoever. I would give you +10 if I could :)
  • Daniel Storch
    Daniel Storch over 9 years
    This explains why i had padding i didn't set in my xml. Had to set padding=5dp to override the default padding form 9 patch background. Thanks
  • Henrique de Sousa
    Henrique de Sousa almost 9 years
    care to show the stacktrace, instead of down-voting a answer that was useful to a number of users?
  • dakshbhatt21
    dakshbhatt21 almost 8 years
    great solution! tried with different text size and worked like charm :)
  • dakshbhatt21
    dakshbhatt21 almost 8 years
    update: in above code, when I use q, g, y, p in lower case they got cut from bottom. So for that change setMeasuredDimension(mBounds.width() + 1, -mBounds.top + 1); to setMeasuredDimension(mBounds.width() + 1, -mBounds.top + mBounds.bottom);
  • sandrstar
    sandrstar about 7 years
    looks like performance-wise it's not great idea to call calculateTextParams in onDraw().
  • YetAnotherUser
    YetAnotherUser about 7 years
    Works. But if you specify android:fontFamily, then change mPaint to getPaint(), otherwise fontFamily is not applied.
  • Jeffrey Blattman
    Jeffrey Blattman almost 7 years
    Didn't work for me. It trimmed the padding, but the font was centered to it cut out most of the font as well. Was using a large font (56sp) if that makes a difference.
  • Harshil Dholakiya
    Harshil Dholakiya over 6 years
    this is work for me. but how to remove top and bottom space above and below ascent and descent of text?
  • InnisBrendan
    InnisBrendan over 5 years
    This did exactly what I needed it to do. This should be the accepted answer. Works on a device running > API 21
  • Farid
    Farid almost 5 years
    I'm still trying to rationalize the count of upvotes for the answer :))
  • Dot Cink
    Dot Cink almost 5 years
    The second clipped my content.
  • VIISHRUT MAVANII
    VIISHRUT MAVANII over 4 years
    It works with a single line but, when I add multiple lines using "\n" it is showing in just a single line.
  • Parth Anjaria
    Parth Anjaria over 2 years
    this works fine, but is it a scalable solution?
  • j2emanue
    j2emanue over 2 years
    If my memory serves correctly on the latest constraint layout negative margins now work someone inform me if I'm wrong