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

时间:2015-04-20 05:10:19

标签: android textview vertical-text mongolian-vertical-script

如何制作用于Android应用程序的蒙古文字TextViews的垂直(从左到右的换行)?

背景

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

enter image description here

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

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

Mongolian Vertical TextView

Mongolian TextView需要具备以下要求:

  • 支持传统的蒙古语字体
  • 从上到下垂直显示文字
  • 换行从左到右。
  • 换行符出现在空格处(与英语相同)

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

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

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

的iOS:

1 个答案:

答案 0 :(得分:5)

更新

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

enter image description here

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

旧答案

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

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

enter image description here

可以通过扩展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();
    }
}

在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" />

已知问题:

    如果你记住轮换,
  • layout_marginlayout_gravity工作正常,但paddinggravity行为奇怪。因此,最好使用wrap_content并避免使用paddinggravity。将MongolTextView放入FrameLayout并使用layout_marginlayout_gravity可以达到同样的效果。
  • 此解决方案不涉及呈现Unicode文本。您需要使用非Unicode文本(不鼓励),或者需要在应用程序中包含渲染引擎。 (Android目前不支持OpenType smartfont渲染。希望将来会有所改变。相比之下,iOS支持复杂的文本渲染字体。)请参阅this link获取Unicode蒙古语渲染引擎示例。