2012-08-12 50 views
7

我想通過設置一個負面的'添加到TextView.setLineSpacing()來減少TextView中的行間距。除了底線被截斷之外,它運作良好。如何減少TextView行間距

主要佈局

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

主要活動:(注意

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

這在視圖的底部導致截短(注意 'G'在底線):

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

看來問題與不正確的佈局測量有關。如果我設置的TextView到

android:layout_height="fill_parent" 

它無法正確顯示:

Using 'fill_parent' does not truncate the bottom line

不知道如何解決它?如果有幫助,我不介意有醜陋的解決方法。我也可以訪問FontForge,如果需要,我可以修改字體文件。

+0

是否發生內置的字體呢?或者其他任何自定義字體?這可能是因爲字體沒有報告正確的下降值。最後一行的 – kcoppock 2012-08-12 17:37:26

+1

也是'LineSpacing of -30f'正在應用。這就是爲什麼最後一行看不到的原因。所以你可以在你的情況下設置30的底部填充... @ kcoppock我認爲在'descent values'中沒有任何錯誤' – 2012-08-12 17:43:27

+0

@kcoppock,我得到了與typeface = Typeface.SANS_SERIF相同的問題; – user1139880 2012-08-12 21:24:50

回答

0

如果填充不起作用,保證金應該做的工作。如果仍有問題,則可以將行間距值始終應用於視圖的onMeasure方法。您必須爲此創建一個custom component並擴展onMeasure。

+0

向TextView添加android:layout_margin =「20dp」或android:layout_marginBottom =「20dp」並沒有幫助。最後一行仍然被截斷。我認爲在TextView確定了所需的度量之後,邊距由父視圖添加。我也會嘗試你的自定義組件建議。 – user1139880 2012-08-12 21:38:21

+0

謝謝何塞。自定義組件的想法似乎工作。在這裏看到我自己的答案。將您的答案標記爲正確的答案。 – user1139880 2012-08-12 22:04:39

+0

我發佈了修復此錯誤的TextView的一些代碼。希望能幫助到你。 http://stackoverflow.com/a/13386208/445348 – cottonBallPaws 2012-11-14 19:52:38

0

只需將paddingBottom添加到您的TextView xml的聲明中,選擇一個可產生良好結果的值。並因此設置其他填充值(頂部,讓和右)。這應該解決您的問題

+0

向TextView添加的padding添加android:paddingBottom =「60dp」,但底線字體仍被截斷。見http://imgur.com/du5xJ – user1139880 2012-08-12 21:33:04

0

這是我根據何塞的答案在這裏做的,它似乎工作。我不太瞭解佈局機制的複雜性。這段代碼安全嗎?有任何問題嗎?

佈局:

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

延伸通過N個像素的垂直高度添加的自定義的TextView:在底部

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

結果文本視圖呈現而不截斷:

enter image description here

+0

這對你真的有用嗎?對我來說,它的行爲與底部填充相同 - 爲textview增加了空間,但最後一行仍然被剪掉 – jab11 2013-10-25 16:43:36

1

不錯! 這樣做可以完成這項工作,但在有變量的地方放置常量值並不是一個好主意。您可以使用lineSpacing值以dinamyc方式將它們添加到onMeasure方法中。 請注意,此值始終可通過「getLineSpacingExtra()」和「getLineSpacingMultiplier()」獲得。或者更容易得到兩者的價值:「getLineHeight()」。

雖然感覺對我來說,這個值應該被包含在onMeasure方法,你總是可以衡量你所需要的確切高度,然後做一個簡單的檢查:

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

最後一件事,你不」 t需要在分離的屬性中傳遞上下文。如果你看看你的構造函數,上下文已經存在。如果你需要你的組件的代碼,你可以使用「getContext()」。

希望它有幫助。

6

我碰到了同樣的問題,但是當我試圖用一個間距乘數小於1

我創建的TextView一個子類,自動修復的最後一行的截斷和不要求你設置底部已知/固定間距。

只要使用這個類,你可以正常使用它,你不需要應用任何額外的間距或修復。

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回答是好的,但如果linespacing通過XML設置

我計算了字體的原始高度與高度TextView的比較需要額外的高度並沒有對某些設備計算一條線。 如果線條高度小於字體的高度,則會添加一次差異。

這適用到至少API 10 propably下(只是未測試任何低級)

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

這是這裏最好的解決方案。 – 2014-02-05 19:40:17

+0

如果我需要以編程方式減少行間距(即setLineSpacing(float,float))適合您的解決方案,該怎麼辦? – ericn 2017-10-11 07:28:54

0

使用此,以減少在文本視圖 **

機器人線間距:lineSpacingMultiplier = 「0.8」

**