7

您如何为 Android 应用程序制作垂直(从左到右换行)蒙古文脚本 TextViews?

背景

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

在此处输入图像描述

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

由于这些困难,我想提出一系列 StackOverflow 问题,这些问题可以作为收集与传统蒙古语应用程序开发相关的一些更困难的编程问题的答案的中心位置。即使您不懂蒙古语,您也可以帮助查看代码、发表评论和问题、给出答案甚至对问题进行投票,我们将不胜感激。

蒙古文垂直TextView

一个蒙古文 TextView 需要具备以下要求:

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

(让TextView支持蒙古字体不是绝对要求,因为TypeFace可以稍后设置,但在使用许多TextView时很方便。)

我的答案如下,但我欢迎其他解决此问题的方法。

本系列其他相关问题:

IOS:

4

1 回答 1

6

更新

我最终MongolTextView从头开始开发了一个垂直脚本。它作为mongol-library.

在此处输入图像描述

以下解决方案的问题是镜像字体中未包含的任何字符(尤其是中文)都会向后出现。

旧答案

蒙古文字体的字形方向与英文的方向一致,即从左到右。这允许将蒙古语单词添加到英语、中文或西里尔文文本中(唯一的问题是这些单词是“放下”而不是“站立”)。

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

在此处输入图像描述

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

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如果您牢记轮换,则可以正常工作,但是行为padding却很gravity奇怪。所以似乎最好使用wrap_content和避免使用paddingand gravitylayout_margin将 MongolTextView 放在 FrameLayout 中并使用and可以达到相同的效果layout_gravity
  • 此解决方案不处理呈现 Unicode 文本。要么你需要使用非 Unicode 文本(不鼓励),要么你需要在你的应用程序中包含一个渲染引擎。(Android 目前不支持 OpenType 智能字体渲染。希望将来会有所改变。相比之下,iOS 确实支持复杂的文本渲染字体。)请参阅此链接以获取 Unicode 蒙古语渲染引擎示例。
于 2015-04-20T05:10:19.220 回答