简体   繁体   English

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

[英]How to set font width in an Android textview?

I am developing an app that displays information such as ascii arts which are very sensitive to font width. 我正在开发一个应用程序,显示对字体宽度非常敏感的ascii arts等信息。 I've been using monospace font, but it does not work well because there are wide chars (such as Chinese and Japanese characters) in the information and the textview does not make the wide chars exactly twice wide as regular chars. 我一直在使用等宽字体,但由于信息中存在宽字符(例如中文和日文字符)而不能很好地工作,而textview不会使宽字符与常规字符完全相同。 Therefore I am trying to see if it's possible to alter the width of fonts in a textview, or if there's better way to solve this problem? 因此,我试图看看是否可以改变textview中字体的宽度,或者是否有更好的方法来解决这个问题? Is Installing another monospace font to my app a good idea? 在我的应用程序中安装另一个等宽字体是个好主意吗? Any input is greatly appreciated. 任何输入都非常感谢。 Thank you. 谢谢。

Kevin 凯文

You can try 你可以试试

textView.setTextScaleX(1.5f);

textView.setTextSize(20);

textView.setTypeface(Typeface.MONOSPACE);    //all characters the same width

With these three methods I hope you can set the font to a desirable appearance. 使用这三种方法,我希望您可以将字体设置为理想的外观。

This question is too old, but I got similar issue and I eventually found a good solution. 这个问题太旧了,但我遇到了类似的问题,最终我找到了一个很好的解决方案。

I have font, which has no monospace variant. 我有字体,没有等宽变体。 I need to display some hexadecimal value in few lines within TextView , but I don't want to use any other font. 我需要在TextView中的几行中显示一些十六进制值,但我不想使用任何其他字体。

Android documentation says: Android文档说:

Spans are powerful markup objects that you can use to style text at a character or paragraph level. 跨度是强大的标记对象,可用于在字符或段落级别设置文本样式。 By attaching spans to text objects, you can change text in a variety of ways, including adding color, making the text clickable, scaling the text size, and drawing text in a customized way. 通过将跨距附加到文本对象,您可以通过多种方式更改文本,包括添加颜色,使文本可单击,缩放文本大小以及以自定义方式绘制文本。 Spans can also change TextPaint properties, draw on a Canvas, and even change text layout. Spans还可以更改TextPaint属性,在Canvas上绘制,甚至更改文本布局。

So, I create custom MonospaceSpan implementation which derives from ReplacementSpan . 因此,我创建了自定义的MonospaceSpan实现,它源自ReplacementSpan This span detects the widest char of given text and draws others with the same width. 此跨度检测给定文本的最宽字符,并绘制具有相同宽度的其他字符。

Here's result: 结果如下:

MonospaceSpan结果

GitHub GitHub上

MonospaceSpan.java 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);
            }
        }
    }

Example of usage: 用法示例:

MainActivity.java 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 RES /布局/ 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>

for those who wants to set monospace using xml, try adding 'android:typeface = "monospace"' 对于那些想要使用xml设置monospace的人,请尝试添加'android:typeface =“monospace”'

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

before adding monospace 在添加monospace之前

在此输入图像描述

after adding monospace 添加等宽后 在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM