I am a UX architect working with a team of Android developers that are mostly junior. We are having issues properly setting line height in Android.
We are using the Material Design spec as our guide for our app. In particular, you can see line height specs here:
https://material.google.com/style/typography.html#typography-line-height
Let's use Body 2 as our example. The spec says the type is 13sp or 14sp, and the leading (line height - same thing) should be 24dp.
Here's the problem: these devs are telling me there is no such way to set line height like that in the code. Instead, they are telling me to measure the distance between the two lines of text and give them that measure - let's say it's 4dp. They want this for each style of text we are using.
We are using a Sketch > Zepelin flow for spec.
It seems odd to me to be able to create a font style (which could easily be class/style in the code) that is 13sp with 24dp leading, and not be able to set the leading, but instead have to add a 3rd measure to the mix. There is no place in Sketch or Zepelin for such a measure "between lines."
Is this really the way it is done, or is there a proper way to set line height?
The solution is simple. Just use these two attributes in your TextView
, lineSpacingExtra
and lineSpacingMultiplier
.
For example,
<TextView
android:layout_width="match_parent"
android:layout_height="80dp"
android:lineSpacingMultiplier="2.5"
android:lineSpacingExtra="6dp"/>
EDIT
These are only meant for controlling the spacing between the lines and not characters (aka Kerning). To control character spacing, you can use this library which I made, KerningViews.
EDIT 2
The android:lineSpacingExtra
add the actual extra space between the lines. You should be using this. Just to give you more information, I gave you the android:lineSpacingMultiplier
attribute which works as a scale factor with the height of the TextView
.
If you want 15dp
of space between lines, use android:lineSpacingExtra="15dp"
, and you are good to go.
I'll explain this from Android Developer perspective.
Line height usually means text size + "padding" top/bottom.
So, if your designer write line height 19sp and text size 15sp, it means you need to have extra padding 4sp.
19sp - 15sp = 4sp.
To implement it in your layout, use lineSpacingExtra
attribute.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:lineSpacingExtra="4sp"
android:fontFamily="sans-serif"
tools:text="StackOverflow is awesome"
/>
Another way to achieve line height is using scale. For example, 1.2
. It means, the spacing is 120% of the text size.
In example above, the line height is 19sp and the text size is 15sp. If we translate it into scale, it become.
19/15 = 1.26
To implement it in your layout, use lineSpacingMultiplier
attribute.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
androdi:lineSpacingMultiplier="1.26"
android:fontFamily="sans-serif"
tools:text="StackOverflow is awesome"
/>
Since API 28 we now have lineHeight
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Lorem ipsum dolor sit amet"
app:lineHeight="50sp"/>
If you are using a style don't forget to remove the app:
<style name="H1">
<item name="android:textSize">20sp</item>
<item name="lineHeight">30sp</item>
</style>
Or in code
TextView.setLineHeight(@Px int)
Here's a way to do it programatically.
public static void setLineHeight(TextView textView, int lineHeight) {
int fontHeight = textView.getPaint().getFontMetricsInt(null);
textView.setLineSpacing(dpToPixel(lineHeight) - fontHeight, 1);
}
public static int dpToPixel(float dp) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return (int) px;
}
Here's React Native's solution: add a span that adjusts the line height https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLineHeightSpan.java
My design colleagues use line height excessively and its a pain that it never looks right after rending in-app.
I'll be planning on making a custom TextView class that takes an arg by XML and will post it here after.
I always do the things programmatically :
float spc = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,6,r.getDisplayMetrics());
textView.setLineSpacing(spc, 1.5f);
Also, read the material design guideline about typography. This is really helpful for achiving the best look.
来源:https://stackoverflow.com/questions/37754299/how-to-properly-set-line-height-for-android