Wie stelle ich die Zeilenhöhe für Android richtig ein?

76

Ich bin ein UX-Architekt und arbeite mit einem Team von Android-Entwicklern zusammen, die größtenteils jünger sind. Wir haben Probleme, die Zeilenhöhe in Android richtig einzustellen.

Wir verwenden die Material Design-Spezifikation als Leitfaden für unsere App. Insbesondere können Sie hier Angaben zur Linienhöhe sehen:

https://material.google.com/style/typography.html#typography-line-height

Nehmen wir als Beispiel Body 2. Die Spezifikation besagt, dass der Typ 13sp oder 14sp ist und der führende Wert (Zeilenhöhe - dasselbe) 24dp betragen sollte.

Hier ist das Problem: Diese Entwickler sagen mir, dass es keine solche Möglichkeit gibt, die Zeilenhöhe im Code so einzustellen. Stattdessen fordern sie mich auf, den Abstand zwischen den beiden Textzeilen zu messen und ihnen dieses Maß zu geben - sagen wir, es ist 4dp. Sie wollen dies für jeden Textstil, den wir verwenden.

Wir verwenden einen Sketch> Zepelin-Flow für die Spezifikation.

Es erscheint mir seltsam, in der Lage zu sein, einen Schriftstil (der im Code leicht Klasse / Stil sein kann) zu erstellen, der 13sp mit 24dp-Führung ist, und nicht in der Lage zu sein, die Führung festzulegen, sondern stattdessen eine dritte Kennzahl hinzuzufügen die Mischung. In Sketch oder Zepelin gibt es keinen Platz für ein solches Maß "zwischen Zeilen".

Ist das wirklich so, oder gibt es eine richtige Möglichkeit, die Linienhöhe einzustellen?

MajorTom
quelle

Antworten:

81

Ich werde dies aus der Perspektive von Android Developer erklären.

Zeilenhöhe bedeutet normalerweise Textgröße + "Auffüllen" oben / unten.

Wenn Ihr Designer also die Zeilenhöhe 19sp und die Textgröße 15sp schreibt, bedeutet dies, dass Sie eine zusätzliche Polsterung von 4sp benötigen.

19sp - 15sp = 4sp.

Verwenden Sie lineSpacingExtraAttribut, um es in Ihrem Layout zu implementieren .

<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"
/>

Eine andere Möglichkeit, die Linienhöhe zu erreichen, ist die Verwendung der Skalierung. Zum Beispiel 1.2. Dies bedeutet, dass der Abstand 120% der Textgröße beträgt.

Im obigen Beispiel beträgt die Zeilenhöhe 19sp und die Textgröße 15sp. Wenn wir es in Maßstab übersetzen, wird es.

19/15 = 1,26

Verwenden Sie das lineSpacingMultiplierAttribut, um es in Ihrem Layout zu implementieren .

<TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:textSize="15sp"
  android:lineSpacingMultiplier="1.26"
  android:fontFamily="sans-serif"
  tools:text="StackOverflow is awesome"
/>
Aldok
quelle
2
Geniale Antwort
Vlad
6
Ich denke, wenn der Text aus zwei oder mehr Zeilen besteht, sollte lineSpacingExtra (19sp - 15sp) / 2 = 2sp sein.
AndroidRuntimeException
Erstaunliche Erklärung!
Rohanpro
12

Seit API 28 haben wir jetzt lineHeight

<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Lorem ipsum dolor sit amet"
app:lineHeight="50sp"/>

Wenn Sie einen Stil verwenden, vergessen Sie nicht, die App zu entfernen:

<style name="H1">
    <item name="android:textSize">20sp</item>
    <item name="lineHeight">30sp</item>
</style>

Oder im Code

TextView.setLineHeight(@Px int)
latsson
quelle
1
Was ich gefunden habe, ist, dass sogar Googles Bemühungen, die Zeilenhöhe festzulegen, nicht mit dem übereinstimmen, was in Designs angezeigt wird (dh was HTML mit derselben Konfiguration gerendert hätte) - ich habe eine 20SP-Textgröße und eine 24-DP-Zeilenhöhe und die berechnete Schrifthöhe in TextView.setLineHeight () funktioniert tatsächlich auf 24sp, so dass setLineHeight nichts ändert
kassim
Das Entfernen des App- Präfixes führt zu einem Fehler:Attribute is missing the namespace prefix
IgorGanapolsky
1
@latsson Was ist das Äquivalent von app:lineHeighton api 21 bis api 27?
toobsco42
@ toobsco42 Sie können dies verwenden, wenn Sie compileSdkVersion auf mindestens 28 haben, was ich denke, Sie haben?
Latsson
2
@ Latsson Ja. Aber wie würde das auf API-Ebenen unter 28 funktionieren?
toobsco42
6

Hier ist eine Möglichkeit, dies programmatisch zu tun.

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;
}
Miguel
quelle
6
lineHeight = height * multiplier + extra

Wenn Sie also den Multiplikator = 0 setzen, kann die Zeilenhöhe mit einer zusätzlichen übereinstimmen.

<TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:textSize="14sp"
  android:lineSpacingMultiplier="0"
  android:lineSpacingExtra="24sp"
/>
Mladen Rakonjac
quelle
0

Ich mache die Dinge immer programmatisch:

float spc = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,6,r.getDisplayMetrics());
textView.setLineSpacing(spc, 1.5f);

Lesen Sie auch die Materialdesign-Richtlinie zur Typografie . Dies ist sehr hilfreich, um den besten Look zu erzielen.

ucMedia
quelle
-1

Hier ist die Lösung von React Native: Fügen Sie einen Bereich hinzu, der die Zeilenhöhe anpasst: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLineHeightSpan .Java

Meine Designkollegen verwenden die Linienhöhe übermäßig und es ist ein Schmerz, dass es nach dem Rendern in der App nie richtig aussieht.

Ich plane, eine benutzerdefinierte TextView-Klasse zu erstellen, die ein Argument per XML verwendet und es anschließend hier veröffentlicht.

kassim
quelle
1
Dies ist keine reine Linkantwort. Es ist eine Antwort mit einem Link. Die Antwort lautet im Wesentlichen "Fügen Sie eine Spanne hinzu, die die Linienhöhe anpasst"
Wai Ha Lee,