2012-08-12 20 views
7

Próbuję zmniejszyć odstępy między wierszami w TextView, ustawiając ujemny "add" na TextView.setLineSpacing(). Działa dobrze, z wyjątkiem tego, że dolna linia zostanie obcięta.Jak zmniejszyć odstęp między wierszami w programie TextView?

Główny układ

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

Główna działalność: (zawiadomienie

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

Powoduje to skrócenie u dołu widoku (zawiadomienie 'g' w dolnym wierszu):

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

Wygląda na to, że problem jest związany z nieprawidłowym pomiarem układu. Jeżeli ustawić TextView do

android:layout_height="fill_parent" 

To jest poprawnie:

Using 'fill_parent' does not truncate the bottom line

jakiś pomysł jak to naprawić? Nie mam nic przeciwko brzydkim obejściom, jeśli to pomaga. Mam również dostęp do FontForge i mogę w razie potrzeby zmodyfikować plik czcionki.

+0

Czy zdarza z wbudowanymi czcionkami? Lub inne niestandardowe czcionki? Możliwe, że czcionka nie zgłasza prawidłowej wartości zejścia. – kcoppock

+1

w ostatniej linii również stosuje się "LineSpacing of -30f". dlatego ostatnia linia nie jest poprawnie widoczna. więc możesz "ustawić dolny margines" na 30 w twoim przypadku ... @ kcoppock Nie sądzę, że coś złego w "wartościach zejścia" –

+0

@kcoppock, pojawia się ten sam problem z krojem czcionki = Typeface.SANS_SERIF; – user1139880

Odpowiedz

0

Jeśli wypełnienie nie działa, margines powinien wykonać zadanie. Jeśli nadal masz problem, zawsze możesz zastosować wartość odstępu między wierszami do metody onMeasure widoku. Będziesz musiał stworzyć dla niego custom component i rozszerzyć onMeasure.

+0

Dodawanie android: layout_margin = "20dp" lub android: layout_marginBottom = "20dp" do TextView nie pomogło. Ostatnia linia jest nadal okrojona. Myślę, że margines jest dodawany przez widok nadrzędny, po tym jak TextView określił pożądaną miarę. Spróbuję również zaproponować niestandardową składową. – user1139880

+0

Dzięki Jose. Idea komponentu niestandardowego wydaje się działać. Zobacz moją własną odpowiedź tutaj. Oznaczanie odpowiedzi jako poprawnej odpowiedzi. – user1139880

+0

Napisałem kod do TextView, który naprawił ten błąd. Mam nadzieję, że to pomoże. http://stackoverflow.com/a/13386208/445348 – cottonBallPaws

0

Wystarczy dodać paddingBottom do deklaracji swojego xml TextView, wybierz wartość, która daje dobry wynik. I w konsekwencji ustaw wartości dla innych paddings (góra, let i right). To powinno naprawić Twój problem.

+0

Dodanie Androida: paddingBottom = "60dp" do dopełnienia dodanego w TextView, ale dolna czcionka jest nadal obcięta. Zobacz http://imgur.com/du5xJ – user1139880

0

To jest to, co zrobiłem na podstawie odpowiedzi Jose tutaj i wydaje się działać. Nie jestem zaznajomiony z zawiłością mechanizmu układu. Czy ten kod jest bezpieczny? Jakiś problem z tym?

Układ:

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

Dodany zwyczaj TextView który rozszerza wysokość pionowe N pikseli:

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

Wynik widok tekst renderowania bez obcinania na dole:

enter image description here

+0

czy to naprawdę działa?dla mnie działa tak samo, jak dolny margines - dodaje spację do tekstu, ale ostatnia linia jest nadal przycięta – jab11

1

Nice! To da ci pracę, ale nigdy nie warto wpisywać wartości stałych, niezależnie od tego, gdzie mamy zmienne. Możesz użyć wartości lineSpacing, aby dodać je do metody onMeasure w dinamyc. Należy pamiętać, że te wartości są zawsze dostępne za pośrednictwem "getLineSpacingExtra()" i "getLineSpacingMultiplier()". Lub jeszcze łatwiej można uzyskać wartość obu zsumowanych: "getLineHeight()".

Mimo, że czuje do mnie, że wartość ta powinna być zawarte w metodzie onMeasure, zawsze można zmierzyć dokładną wysokość co potrzeba, a następnie dokonać prostego sprawdzenia:

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

Ostatnią rzeczą, don” t musisz przekazać kontekst w oddzielnym atrybucie. Jeśli spojrzysz na swoich konstruktorów, kontekst już tam jest. Jeśli potrzebujesz kodu kodu komponentu, możesz po prostu użyć "getContext()".

Mam nadzieję, że to pomaga.

6

wpadłem na ten sam problem, ale kiedy próbuje użyć mnożnik dystansową mniej niż 1.

stworzyłem podklasę TextView który poprawia obcinanie ostatnim wierszu automatycznie i nie wymaga ustawienia znany/ustalony odstęp na dole.

Po prostu używaj tej klasy i możesz jej używać normalnie, nie musisz stosować żadnych dodatkowych odstępów ani poprawek.

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 odpowiedź jest dobra, ale to nie działa na niektórych urządzeniach, jeżeli linespacing została ustalona poprzez XML

obliczyć dodatkową wysokość potrzebną porównując oryginalną wysokość czcionki o wysokości TextView oblicza dla linii. Jeśli wysokość linii jest mniejsza niż wysokość czcionki, różnica jest dodawana jeden raz.

Działa się do co najmniej API 10 propably niższe (tylko nie badano niżej)

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

To najlepsze rozwiązanie tutaj, bez użycia rąk. –

+0

co jeśli programowo trzeba zmniejszyć odstępy między wierszami, np. Gdzie "setLineSpacing (float, float)" pasuje do twojego rozwiązania? – ericn

0

Służy do zmniejszenia odstępów liniowy w widoku tekstu **

ANDROID lineSpacingMultiplier = "0.8"

**

Powiązane problemy