如何在 Android 文本视图中设置字体宽度?

发布于 2024-11-08 14:45:10 字数 213 浏览 0 评论 0原文

我正在开发一个应用程序,用于显示诸如 ascii arts 之类的信息,这些信息对字体宽度非常敏感。我一直在使用等宽字体,但它效果不佳,因为信息中存在宽字符(例如中文和日文字符),并且文本视图不会使宽字符恰好是常规字符的两倍宽。因此我想看看是否可以改变文本视图中字体的宽度,或者是否有更好的方法来解决这个问题?在我的应用程序中安装另一种等宽字体是个好主意吗?任何意见都将受到高度赞赏。谢谢。

凯文

I am developing an app that displays information such as ascii arts which are very sensitive to font width. 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. 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? Is Installing another monospace font to my app a good idea? Any input is greatly appreciated. Thank you.

Kevin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼眸印温柔 2024-11-15 14:45:10

您可以尝试

textView.setTextScaleX(1.5f);

textView.setTextSize(20);

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

通过这三种方法希望您可以将字体设置为理想的外观。

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.

神也荒唐 2024-11-15 14:45:10

对于那些想要使用 xml 设置等宽字体的人,请尝试

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

在添加等宽字体之前

添加 'android:typeface = "monospace"' < img src="https://i.sstatic.net/qwAd0.jpg" alt="在此处输入图像描述">

添加等宽字体后,
输入图像描述这里

for those who wants to set monospace using xml, try adding '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

enter image description here

after adding monospace
enter image description here

猥琐帝 2024-11-15 14:45:10

这个问题太老了,但我遇到了类似的问题,最终找到了一个很好的解决方案。

我有字体,它没有等宽字体变体。我需要在 TextView 中的几行中显示一些十六进制值,但我不想使用任何其他字体。

Android 文档 说:

Span 是功能强大的标记对象,可用于在字符或段落级别设置文本样式。通过将跨度附加到文本对象,您可以通过多种方式更改文本,包括添加颜色、使文本可单击、缩放文本大小以及以自定义方式绘制文本。 Spans 还可以更改 TextPaint 属性、在 Canvas 上绘图,甚至更改文本布局。

因此,我创建了源自 ReplacementSpan 的自定义 MonospaceSpan 实现。此跨度检测给定文本的最宽字符并绘制具有相同宽度的其他字符。

结果如下:

MonospaceSpan result

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>

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.

Android documentation says:

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.

So, I create custom MonospaceSpan implementation which derives from ReplacementSpan. This span detects the widest char of given text and draws others with the same width.

Here's result:

MonospaceSpan result

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

Example of usage:

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文