How to reduce TextView line spacing

user1139880 picture user1139880 · Aug 12, 2012 · Viewed 16k times · Source

I am trying to reduce the line spacing in a TextView by setting a negative 'add' to TextView.setLineSpacing(). It works well except that the bottom line get truncated.

Main layout

<TextView
    android:id="@+id/text_view"
    android:padding="dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    tools:context=".MainActivity" />

Main activity: (notice the

package com.font_test;

import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/custom_fonts.ttf");
        final TextView tv = (TextView) findViewById(R.id.text_view);
        tv.setTypeface(typeface);
        tv.setTextSize(60);
        tv.setLineSpacing(-30f, 1f);  // *** -30 to reduce line spacing
        tv.setBackgroundColor(0x280000ff);
        tv.setText("gggkiiikkk" + "\n" + "gikgikgik" + "\n" + "kigkigkig");
    }
}

This results in truncation at the bottom of the view (notice the 'g' at the bottom line):

Reducing the line spacing cuts the 'g' at the bottom line

It seems that the problem is related to incorrect layout measurement. If I set the TextView to

 android:layout_height="fill_parent"

It does render properly:

Using 'fill_parent' does not truncate the bottom line

Any idea how to fix it? I don't mind to have ugly workarounds if it helps. I also have access to FontForge and I can modify the font file if needed.

Answer

Zarokka picture Zarokka · Jun 10, 2013

littleFluffyKittys answer is good but it didn't work on some devices if the linespacing was set through xml

I calculate the additional height needed by comparing the original height of the font with the height the textview calculates for a line. If the line height is smaller than the height of the font the diffrence is added one time.

This works down to at least API 10 propably lower (just not tested any lower)

public class ReducedLineSpacingTextView extends TextView {

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

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int truncatedHeight = getPaint().getFontMetricsInt(null) - getLineHeight();
        if (truncatedHeight > 0) {
            setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() + truncatedHeight);
        }
    }

}