Как сделать традиционный монгольский скрипт TextView в Android

Как сделать вертикальный (с переносом строк слева направо) монгольский скрипт TextViews для приложений Android?

Фон

Android имеет довольно хорошую поддержку для многих языков мира, даже для языков RTL, таких как арабский и иврит. Тем не менее, нет встроенной поддержки языков "сверху вниз", таких как традиционный монгольский (который все еще очень жив во Внутренней Монголии и не следует путать с кириллическим монгольским). На следующем рисунке показано направление текста с добавлением английского для ясности.

Поскольку эта функциональность не встроена в Android, она делает практически все аспекты разработки приложений чрезвычайно сложными. В Интернете также очень и очень мало информации. (Один из немногих связанных с этим вопросов SO даже не дает хорошего ответа.) Существует множество разработчиков приложений для традиционного монгольского языка, но, похоже, по коммерческим или иным причинам они не делают свой код открытым исходным кодом.

Из-за этих трудностей я хотел бы составить серию вопросов Stackru, которые могут служить центральным местом для сбора ответов на некоторые из более сложных проблем программирования, связанных с разработкой традиционных монгольских приложений. Даже если вы не владеете монгольским языком, ваша помощь в просмотре кода, комментировании и вопросах, даче ответов или даже голосовании по данному вопросу будет принята с благодарностью.

Монгольский вертикальный TextView

Монгольский TextView должен иметь следующие требования:

  • Поддерживает традиционный монгольский шрифт
  • Отображает текст вертикально сверху вниз
  • Перенос строки идет слева направо.
  • Разрывы строк происходят в пробелах (как на английском)

(Наличие поддержки TextView для монгольского шрифта не является абсолютным требованием, поскольку TypeFace можно установить позже, но это удобно, когда используется много TextView.)

Мой ответ ниже, но я приветствую другие способы решения этой проблемы.

Другие связанные вопросы в этой серии:

IOS:

1 ответ

Решение

Обновить

Я закончил разработку вертикального сценария 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();
    }
}

В макете 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_margin а также layout_gravity работать хорошо, если вы помните вращение, но padding а также gravity вести себя странно. Так что, кажется, лучше всего использовать wrap_content и избегать использования padding а также gravity, Этого же эффекта можно добиться, поместив MongolTextView в FrameLayout и используя layout_margin а также layout_gravity,
  • Это решение не имеет дело с отображением текста Unicode. Либо вам нужно использовать не-Unicode текст (не рекомендуется), либо вам нужно включить движок рендеринга в ваше приложение. (В настоящее время Android не поддерживает рендеринг смарт-шрифтов OpenType. Надеемся, что это изменится в будущем. IOS, для сравнения, поддерживает сложные шрифты рендеринга текста.) См. Эту ссылку для примера движка рендеринга монгольского языка Unicode.
Другие вопросы по тегам