如何在Android中制作传统的蒙古文字TextView

Sur*_*gch 6 android vertical-text textview mongolian-vertical-script

你如何使用Android应用程序进行垂直(从左到右的换行)Mongolian脚本TextViews?

背景

Android对世界上许多语言都有相当好的支持,甚至包括阿拉伯语和希伯来语等RTL语言.然而,对于像传统蒙古语这样的自上而下的语言没有内置的支持(在内蒙古仍然非常活跃,不能与西里尔语蒙古语混淆).下图显示了为清晰起见添加了英语的文本方向.

在此输入图像描述

由于此功能未内置于Android中,因此几乎使应用程序开发的每个方面都非常困难.在线提供的信息非常非常少.(少数几个相关的SO问题之一甚至没有一个好的答案.)有许多应用程序开发人员为传统的蒙古语,但无论是出于商业原因还是其他原因,他们似乎并没有使他们的代码开源.

由于存在这些困难,我想提出一系列StackOverflow问题,这些问题可以作为收集与传统蒙古应用程序开发相关的一些更困难的编程问题的答案的中心位置.即使您没有蒙古语识字,我们也会感谢您帮助查看代码,提出意见和问题,给出答案甚至对问题进行投票.

蒙古文垂直TextView

蒙古语TextView需要满足以下要求:

  • 支持传统的蒙古语字体
  • 从上到下垂直显示文本
  • 换行从左到右.
  • 换行发生在一个空间(与英语相同)

(由于TypeFace可以在以后设置,因此TextView支持Mongolian字体不是绝对的要求,但是在使用许多TextView时它很方便.)

我的答案如下,但我欢迎其他方法来解决这个问题.

本系列中的其他相关问题:

iOS版:

Sur*_*gch 5

更新

我最终MongolTextView从头开始编写一个垂直脚本.它作为一部分提供mongol-library.

在此输入图像描述

下面的解决方案的问题是镜像字体中未包含的任何字符(特别是中文)将显示在后面.

老答案

蒙古字体都是用与英文相同方向的字形方向制作的,即从左到右.这允许将蒙古语单词添加到英语,中文或西里尔文本中(唯一的问题是单词是"放下"而不是"站起来"应该如此).

顺时针旋转TextView 90度会使其垂直,但换行方向错误(旋转后从右到左而不是从左到右).换行方向问题可以通过水平翻转或镜像TextView来解决,但所有字形都是镜像的.最后一个问题可以通过从垂直镜像字体开始来解决(可以通过使用像FontForge这样的开源软件编辑现有字体来实现).下图说明了该过程:

在此输入图像描述

旋转和翻转可以通过扩展TextView并覆盖onDraw()onMeasure()方法来完成:

public class MongolTextView extends TextView {

    private TextPaint textPaint;

    // Constructors
    public MongolTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public MongolTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MongolTextView(Context context) {
        super(context);
        init();
    }

    // This class requires the mirrored Mongolian font to be in the assets/fonts folder
    private void init() {

        Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
                "fonts/MongolFontMirrored.ttf");
        setTypeface(tf);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // swap the height and width
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        textPaint = getPaint();
        textPaint.setColor(getCurrentTextColor());
        textPaint.drawableState = getDrawableState();

        canvas.save();

        // flip and rotate the canvas
        canvas.translate(getWidth(), 0);
        canvas.rotate(90);
        canvas.translate(0, getWidth());
        canvas.scale(1, -1);
        canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());

        getLayout().draw(canvas);

        canvas.restore();
    }
}
Run Code Online (Sandbox Code Playgroud)

在xml布局中,使用扩展TextView的全名:

<com.example.MongolTextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:text="@string/title_string" />
Run Code Online (Sandbox Code Playgroud)

已知的问题:

  • layout_marginlayout_gravity如果你牢记旋转,但工作正常paddinggravity奇怪的行为.因此,似乎最好使用wrap_content并避免使用paddinggravity.通过将MongolTextView放在FrameLayout中并使用layout_margin和,可以实现相同的效果layout_gravity.
  • 此解决方案不涉及呈现Unicode文本.要么您需要使用非Unicode文本(不鼓励使用),要么需要在应用程序中包含渲染引擎.(Android目前不支持OpenType smartfont渲染.希望将来会改变.相比之下,iOS支持复杂的文本渲染字体.)请参阅此链接以获取Unicode蒙古语渲染引擎示例.