2012-08-12 20 views
7

Ich versuche, den Zeilenabstand in einem TextView zu reduzieren, indem Sie TextView.setLineSpacing() auf ein negatives "add" setzen. Es funktioniert gut, außer dass die untere Zeile abgeschnitten wird.So reduzieren Sie den TextView-Zeilenabstand

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

Haupttätigkeit: (man beachte die

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

Die am unteren Teil der Ansicht in Trunkierung führt (man beachte die 'g' in der untersten Zeile):

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

Es scheint, dass das Problem mit einer falschen Layoutmessung zusammenhängt. Wenn ich die Textview zu

android:layout_height="fill_parent" 

Es richtig eingestellt ist Render:

Using 'fill_parent' does not truncate the bottom line

eine Ahnung, wie man es beheben? Ich habe nichts dagegen, hässliche Workarounds zu haben, wenn es hilft. Ich habe auch Zugriff auf FontForge und kann die Schriftartdatei bei Bedarf ändern.

+0

Kommt es vor, mit den eingebauten Schriften auch? Oder andere benutzerdefinierte Schriftarten? Es könnte sein, dass die Schriftart nicht den korrekten Abstiegswert meldet. – kcoppock

+1

in der letzten Zeile gilt auch 'LineSpacing von -30f'. Deshalb wird die letzte Zeile nicht richtig angezeigt. so können Sie in Ihrem Fall "Bodenpolsterung" von 30 einstellen ... @ kcoppock Ich glaube nicht, dass irgendwas falsch in "Abstiegswerten" ist –

+0

@kcoppock, bekomme ich das gleiche Problem mit typeface = Typeface.SANS_SERIF; – user1139880

Antwort

0

Wenn Padding nicht funktioniert, sollte Marge den Job erledigen. Wenn das Problem weiterhin besteht, können Sie den Wert für den Zeilenabstand immer auf die onMeasure-Methode der Ansicht anwenden. Sie müssen dafür eine custom component erstellen und onMeasure erweitern.

+0

Das Hinzufügen von android: layout_margin = "20dp" oder android: layout_marginBottom = "20dp" zum TextView hat nicht geholfen. Die letzte Zeile ist noch abgeschnitten. Ich denke, dass der Rand von der Elternansicht hinzugefügt wird, nachdem der TextView sein gewünschtes Maß bestimmt hat. Ich werde auch versuchen Sie benutzerdefinierte Komponente Vorschlag. – user1139880

+0

Danke Jose. Die Idee der benutzerdefinierten Komponente scheint zu funktionieren. Siehe meine eigene Antwort hier. Markieren Sie Ihre Antwort als die richtige Antwort. – user1139880

+0

Ich habe einen Code für einen TextView gepostet, der diesen Fehler behebt. Ich hoffe es hilft. http://stackoverflow.com/a/13386208/445348 – cottonBallPaws

0

Fügen Sie paddingBottom zur Deklaration Ihres TextView xml hinzu, wählen Sie einen Wert, der ein gutes Ergebnis liefert. Setzen Sie daher Werte für andere Paddings (oben, links und rechts). Dies sollte Ihr Problem beheben

+0

Hinzufügen von android: paddingBottom = "60dp" zum TextView-Padding hinzugefügt, aber die untere Zeile Schriftart ist immer noch abgeschnitten. Siehe http://imgur.com/du5xJ – user1139880

0

Dies ist, was ich basierend auf Jose Antwort hier getan habe und es scheint zu funktionieren. Ich bin nicht sehr vertraut mit dem komplizierten Layout-Mechanismus. Ist dieser Code sicher? Irgendein Problem damit?

Layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <com.font_test.MyTextView 
     android:id="@+id/text_view" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
     android:layout_centerVertical="true" 
     tools:context=".MainActivity" /> 

</RelativeLayout> 

Added benutzerdefinierte Textview, die von N Pixeln, die die vertikale Höhe erstreckt:

package com.font_test; 

import android.content.Context; 
import android.util.AttributeSet; 
import android.widget.TextView; 

public class MyTextView extends TextView { 

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

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     // TODO: provide an API to set extra bottom pixels (50 in this example) 
     setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() + 50);  
    } 
} 

Ergebnis Textansicht Rendering ohne Trunkierung am Boden:

enter image description here

+0

funktioniert das wirklich für Sie?Für mich funktioniert es genauso wie bottom padding - fügt textview Platz hinzu, aber die letzte Zeile ist immer noch abgeschnitten – jab11

1

Schön! Das macht den Job, aber es ist nie eine gute Idee, Konstantenwerte überall dort zu platzieren, wo wir Variablen haben. Sie können die lineSpacing-Werte verwenden, um sie der Methode onMeasure in einer dynamischen Methode hinzuzufügen. Beachten Sie, dass diese Werte immer über "getLineSpacingExtra()" und "getLineSpacingMultiplier()" verfügbar sind. Oder noch einfacher können Sie den Wert von beiden zusammenfassen: "getLineHeight()".

Obwohl es für mich die Meinung, dass dieser Wert in den onMeasure Verfahren aufgenommen werden, können Sie immer die genaue Höhe messen Sie brauchen, und dann eine einfache Prüfung machen:

final int measuredHeight = getMeasuredHeight(); 
if (measuredHeight < neededHeight) { 
    setMeasuredDimension(getMeasuredWidth, neededHeight); 
} 

Eine letzte Sache, Sie don‘ t müssen den Kontext in einem getrennten Attribut weiterleiten. Wenn Sie sich Ihre Konstruktoren ansehen, ist der Kontext bereits vorhanden. Wenn Sie den Code Ihrer Komponente benötigen, können Sie einfach "getContext()" verwenden.

Ich hoffe, es hilft.

6

Ich lief in das gleiche Problem, aber wenn ich einen Abstand Multiplikator kleiner als 1

zu nutzen versuchte, habe ich eine Unterklasse von TextView, die das Abschneiden der letzten Zeile passt sich automatisch und erfordert keine von Ihnen festgelegten ein bekannter/fester Abstand an der Unterseite.

Verwenden Sie einfach diese Klasse und Sie können sie normal verwenden, Sie müssen keine zusätzlichen Abstände oder Fixes anwenden.

public class ReducedLineSpacingTextView extends TextView { 

    private boolean mNegativeLineSpacing = false; 

    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); 
     if (mNegativeLineSpacing) { // If you are only supporting Api Level 16 and up, you could use the getLineSpacingExtra() and getLineSpacingMultiplier() methods here to check for a less than 1 spacing instead. 
      Layout layout = getLayout(); 
      int truncatedHeight = layout.getLineDescent(layout.getLineCount()-1); 
      setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() + truncatedHeight); 
     } 
    } 

    @Override 
    public void setLineSpacing(float add, float mult) { 
     mNegativeLineSpacing = add < 0 || mult < 1; 
     super.setLineSpacing(add, mult); 
    } 

} 
9

littleFluffyKittys beantworten ist gut, aber es nicht auf einigen Geräten nicht funktionierte, wenn der LineSpacing durch xml gesetzt wurde

ich berechnen die zusätzliche Höhe erforderlich, indem die ursprüngliche Höhe der Schriftart mit der Höhe Vergleich der Textview berechnet für eine Linie. Wenn die Zeilenhöhe kleiner als die Schrifthöhe ist, wird der Diffrence einmal hinzugefügt.

Dies funktioniert mindestens API 10 nach unten propably unteren (nicht getestet irgendein unteren)

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

} 
+1

Dies ist die beste Lösung hier hands down. –

+0

Was ist, wenn ich den Zeilenabstand programmgesteuert reduzieren muss, d. H. Wo passt 'setLineSpacing (float, float) 'in Ihre Lösung? – ericn

0

verwendet Zeilenabstand in der Textansicht zu reduzieren **

android: lineSpacingMultiplier = "0.8"

**

Verwandte Themen