如何在具有多种字体大小的TextView中调整行高?

25

我有一个TextView,其中包含一个Spannable字符串。该字符串包含一堆文本,第一个单词的字体大小是其余字符串的两倍。

问题在于,由于第一个单词的增加大小,第一行和第二行之间的行距比随后的行之间的行距要大得多。

http://img.skitch.com/20100615-fwd2aehbsgaby8s2s9psx3wwii.png

以下代码片段创建了Spannable字符串:

    // Price
    CharSequence text = "$30 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
    final Pattern priceRegex = Pattern.compile("^(.[0-9]+)\\s.*");
    final Matcher m = priceRegex.matcher(text!=null ? text : "");
    if( m.matches() ) {
        text = new SpannableString(text);
        ((SpannableString)text).setSpan(new RelativeSizeSpan(2), 0, m.end(1), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

如何修复我的 TextView,使得所有行之间的间距相同?

4个回答

43
您可以尝试使用以下任一TextView属性:
android:lineSpacingMultiplier
android:lineSpacingExtra

尝试将所有行的高度至少设置为相同的高度(与第一行相同)。


1
它也会按比例增加第一行的行距吗? - emmby
4
请注意,android:lineSpacingMultiplier 仅适用于 API 级别 16 及以上版本。 - yiati
2
我曾经遇到过完全相同的问题,但这个解决方案并没有起作用。就像@emmby所说的那样,它会按比例缩放所有行的间距。 - miracula
1
@yiati:方法setLineSpacing()android:lineSpacingMultiplier从API级别1开始可用。方法getLineSpacing()从API级别16开始可用。 您可以参考此链接:http://developer.android.com/reference/android/widget/TextView.html#attr_android:lineSpacingMultiplier - Nhat Dinh

2

经过多次尝试,我找到了一个相当hacky的解决方案:

  1. 我在文本中的每个空格处都添加了与强调单词相同的加倍文本大小的可扩展字符。这样整个TextView就具有了相同的(大)行间距。请注意,您不能重复使用可扩展字符。

  2. 然后我给TextView设置了负的lineSpacingExtra,使行间距看起来很好。

  3. 为了避免由于增加的文本大小而产生不自然宽度的空格,我向每个空格添加了一个ScaleXSpan,将它们缩小到原始大小的50%。

只要每行至少包含一个空格字符,这种方法即可适用于保存本地化字符串的TextView(其中您永远不知道强调单词出现的位置或您的行有多长)。


1
我喜欢你的思维方式! - Alireza Ahmadi

1

我编写了这个函数:

输入

  • LinearLayout ll:

    布局,它将是您的“TexView”(确保其方向为垂直)

  • String money:

    您希望与其他不同的字符串(在您的情况下为更大的文本大小)

  • String text:

    文本

  • Context mContext

    上下文

如何操作

我已经对您必须编辑的部分进行了注释


private void populateText(LinearLayout ll,
        String money, String text , Context mContext) { 
    String [] textArray = text.split(" ");
    Display display = getWindowManager().getDefaultDisplay();
    ll.removeAllViews();
    int maxWidth = display.getWidth() - 20;

    LinearLayout.LayoutParams params; // to be used over and over
    LinearLayout newLL = new LinearLayout(mContext);
    newLL.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
            LayoutParams.WRAP_CONTENT));
    newLL.setGravity(Gravity.LEFT);
    newLL.setOrientation(LinearLayout.HORIZONTAL);

    int widthSoFar = 0;

    ///FIRST INSERT THE MONEY TEXTVIEW
    LinearLayout LL = new LinearLayout(mContext);
    LL.setOrientation(LinearLayout.HORIZONTAL);
    LL.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM); //THIS IS IMPORTANT TO keep spacing up not down
    LL.setLayoutParams(new ListView.LayoutParams(
            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    TextView TV = new TextView(mContext);
    TV.setText(money);
    //TV.setTextSize(size);  <<<< SET TEXT SIZE
    TV.measure(0, 0);
    params = new LinearLayout.LayoutParams(TV.getMeasuredWidth(),
            LayoutParams.WRAP_CONTENT);
    //params.setMargins(5, 0, 5, 0);  // YOU CAN USE THIS
    LL.addView(TV, params);
    LL.measure(0, 0);
    widthSoFar += TV.getMeasuredWidth();// YOU MAY NEED TO ADD THE MARGINS
    newLL.addView(LL, params);

    for (int i = 0 ; i < textArray.length ; i++ ){
        LL = new LinearLayout(mContext);
        LL.setOrientation(LinearLayout.HORIZONTAL);
        LL.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM);
        LL.setLayoutParams(new ListView.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        TV = new TextView(mContext);
        TV.setText(textArray[i]);
        //TV.setTextSize(size);  <<<< SET TEXT SIZE
        TV.measure(0, 0);
        params = new LinearLayout.LayoutParams(TV.getMeasuredWidth(),
                LayoutParams.WRAP_CONTENT);
        //params.setMargins(5, 0, 5, 0);  // YOU CAN USE THIS
        LL.addView(TV, params);
        LL.measure(0, 0);
        widthSoFar += TV.getMeasuredWidth();// YOU MAY NEED TO ADD THE MARGINS
        if (widthSoFar >= maxWidth) {
            ll.addView(newLL);

            newLL = new LinearLayout(mContext);
            newLL.setLayoutParams(new LayoutParams(
                    LayoutParams.FILL_PARENT,
                    LayoutParams.WRAP_CONTENT));
            newLL.setOrientation(LinearLayout.HORIZONTAL);
            newLL.setGravity(Gravity.LEFT);
            params = new LinearLayout.LayoutParams(LL
                    .getMeasuredWidth(), LL.getMeasuredHeight());
            newLL.addView(LL, params);
            widthSoFar = LL.getMeasuredWidth();
        } else {
            newLL.addView(LL);
        }
    }
    ll.addView(newLL);
}

注意

我没有测试过它... 我用它来做更复杂的事情,它是有效的... 你可能需要稍微调整一下。


0

我认为你做不到 :(。 Android操作系统根据字体大小计算行之间的间隔,因此“30$”会使第1行和第2行之间的间隔变大,我不知道是否可能控制这个间隔大小。

要解决这个问题,您可以轻松扩展LinearLayout并将其方向设置为垂直。然后使用fillparent为宽度放置2个文本视图....

然后实现函数,比如setNoGapText(String s); ,在这个函数中,您可以测量适合放在顶部文本视图中的文本(可以使用TextUtils完成),然后剩余的文本将适合于textview2...

在这两个文本视图之间,您可以玩弄填充和边距属性,以便行之间的间隔看起来就像您想象的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接