如何在Android的TextView中设置字体宽度?

20

我正在开发一个应用程序,用于显示一些信息,例如ASCII艺术,这些信息对字体宽度非常敏感。我一直在使用等宽字体,但是由于信息中存在宽字符(例如中文和日文字符),而且textview不能将宽字符正好扩展为普通字符的两倍宽。因此,我想知道是否可以改变textview中字体的宽度,或者是否有更好的解决方法?在我的应用程序中安装另一个等宽字体是一个好主意吗?非常感谢您的任何建议。

Kevin

3个回答

45

你可以尝试

textView.setTextScaleX(1.5f);

textView.setTextSize(20);

textView.setTypeface(Typeface.MONOSPACE);    //all characters the same width
希望这三种方法可以帮助您设置字体以获得理想的外观。

谢谢您的回复。看起来setTextScaleX根据其原始宽度调整字体宽度。因此,宽度与原始宽度成比例,而不是使所有字体具有相同的宽度。有没有解决这个问题的方法?谢谢。 - Kevin
等宽字体适用于使常规字符具有相等的宽度。似乎对于宽字符不起作用。为了正确显示ASCII艺术,宽字符需要比常规字符宽两倍。例如,aaaaaaaa aaaa这两个字符串在终端上应该具有相同的长度。维基百科称,等宽字体不支持中日等宽字符语言。http://en.wikipedia.org/wiki/Droid_(font)因此,它无法正确呈现宽字符的宽度,所以我希望找到一种设置宽字符宽度的方法。谢谢。 - Kevin
1
作为样式项:<item name="android:typeface">等宽字体</item> - larham1
请注意,如果您设置了fontFamily,它可能无法正常工作。一个有问题的值的例子是"sans-serif-light"。 - android developer

15

如果想在XML中设置等宽字体,可以尝试添加“android:typeface =“monospace””

        <TextView
            android:id="@+id/tv_output"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"  
            android:typeface="monospace" />

添加等宽字体之前

输入图像描述

添加等宽字体之后 输入图像描述


9
这个问题太旧了,但我遇到了类似的问题,并最终找到了一个好的解决方案。
我有一种字体,没有等宽变体。 我需要在 TextView 中显示一些十六进制值,但我不想使用其他字体。 Android documentation说:
引用: Spans 是强大的标记对象,您可以使用它们在字符或段落级别上为文本设置样式。通过将 Spans 附加到文本对象,您可以以多种方式更改文本,包括添加颜色,使文本可点击,缩放文本大小以及以自定义方式绘制文本。Spans 还可以更改 TextPaint 属性,在 Canvas 上绘制,甚至更改文本布局。
因此,我创建了一个自定义的 MonospaceSpan 实现,它派生自 ReplacementSpan。该 span 检测给定文本中最宽的字符,并以相同的宽度绘制其他字符。
这是结果:

MonospaceSpan result

{{链接1:GitHub}}

MonospaceSpan.java

    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.text.style.ReplacementSpan;

    public class MonospaceSpan extends ReplacementSpan {
        private boolean ignoreFullText;

        public void setIgnoreFullText(boolean ignoreFullText) {
            this.ignoreFullText = ignoreFullText;
        }

        private int getMaxCharWidth(@NonNull Paint paint, @NonNull CharSequence text, int start, int end, float[] widths) {
            if (widths == null) {
                widths = new float[end - start];
            }

            paint.getTextWidths(text, start, end, widths);

            float max = 0;

            for (float w : widths) {
                if (max < w) {
                    max = w;
                }
            }

            return Math.round(max);
        }

        @Override
        public int getSize(@NonNull Paint paint, @NonNull CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {
            if (fm != null) {
                paint.getFontMetricsInt(fm);
            }

            int count = end - start;

            if (text.charAt(start) == '\n') {
                count -= 1;
            }

            if (text.charAt(end - 1) == '\n') {
                count -= 1;
            }

            if (count < 0) {
                count = 0;
            }

            if (ignoreFullText) {
                return getMaxCharWidth(paint, text, start, end, null) * count;
            } else {
                return getMaxCharWidth(paint, text, 0, text.length(), null) * count;
            }
        }

        @Override
        public void draw(@NonNull Canvas canvas, @NonNull CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
            float[] widths = new float[end - start];
            int max = getMaxCharWidth(paint, text, start, end, widths);

            if (!ignoreFullText) {
                max = getMaxCharWidth(paint, text, 0, text.length(), null);
            }

            for (int i = 0, n = end - start; i < n; ++i) {
                float p = (max - widths[i]) / 2;
                canvas.drawText(text, start + i, start + i + 1, x + max * i + p, y, paint);
            }
        }
    }

使用示例:

MainActivity.java

    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.text.SpannableString;
    import android.widget.TextView;

    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main);

            String text = "Lorem ipsum\ndolor sit amet\n0123456789";
            SpannableString textMono = new SpannableString(text);
            textMono.setSpan(new MonospaceSpan(), 0, textMono.length(), 0);

            TextView textView1 = findViewById(android.R.id.text1);
            TextView textView2 = findViewById(android.R.id.text2);

            textView1.setText(text);
            textView2.setText(textMono);
        }
    }

res/layout/activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:padding="16dp">

        <TextView
            android:id="@android:id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="4dp"
            android:background="#fa0"
            android:fontFamily="@font/fredoka_one" />

        <TextView
            android:id="@android:id/text2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="4dp"
            android:background="#0af"
            android:fontFamily="@font/fredoka_one" />
    </LinearLayout>

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