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

背景

Android对世界上许多语言提供了很好的支持,甚至包括阿拉伯文和希伯来文这样的RTL语言。但是,没有内置支持从上到下的语言,例如traditional Mongolian(在内蒙古仍然活跃,不要与Cyrillic Mongolian混淆)。下图显示了文本方向,为清楚起见添加了英语。

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

由于这些困难,我想提出一系列StackOverflow问题,这些问题可以作为中心位置来收集与传统蒙古语应用程序开发相关的一些较困难的编程问题的答案。即使您不懂蒙古语,也可以帮助您检查代码,提出意见和问题,给出答案甚至投票赞成该问题。

蒙古语垂直TextView

蒙古文TextView需要具有以下要求:

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

  • (因为将来可以设置TypeFace,所以不是必须要支持TextView的蒙古字体,但是当使用许多TextView时,这是一种方便。)

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

    本系列中的其他相关问题:
  • How to make a traditional Mongolian script EditText in Android
  • How to make a traditional Mongolian script ListView in Android
  • 以后还会有更多...( toast ,对话框,菜单)

  • iOS:
  • How do you make a vertical text UILabel and UITextView for iOS in Swift?
  • 最佳答案

    更新
    我最终从零开始开发了一个垂直脚本 MongolTextView 。它可以作为 mongol-library 的一部分使用。
    android - 如何在Android中制作传统的蒙古语脚本TextView-LMLPHP
    以下解决方案的问题在于,镜像字体中未包括的任何字符(特别是中文)都将向后显示。
    旧答案
    蒙古字体全部以字形的方向与英语相同的方向制作,即从左到右。这样就可以将蒙古语单词添加到英语,中文或西里尔文字中(唯一的问题是单词正在“放下”而不是“站起来”)。
    顺时针旋转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();
        }
    }
    
    在您的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确实支持复杂的文本呈现字体。)有关Unicode蒙古语呈现引擎示例,请参见this link
  • 10-08 17:55