How to fix TextView font fallback?

2019-04-29 14:39发布

问题:

I have a program that is localized into multiple languages. It works well on Android 4.x but has a font rendering issue Android 2.3.x. Here is a small example that reproduces it. Any help will be greatly appreciated.

Main activity layout. Nothing special here. Just two TextView views:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp" >

    <TextView
        android:id="@+id/text_view1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="80dp"
        tools:context=".MainActivity" />

    <TextView
        android:id="@+id/text_view2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="80dp"
        tools:context=".MainActivity" />

</LinearLayout>

Main activity:

package com.font_test;

import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    private static final String TEXT = 
            "\u0440\u0443\u0441\u0441\u043A\u0438\u0439" + 
            "\n" + 
            "pyccknn";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set textview 1
        final Typeface typeface1 = Typeface
                .createFromAsset(getAssets(), "fonts/chelsea.ttf");
        final TextView tv1 = (TextView) findViewById(R.id.text_view1);
        tv1.setTypeface(typeface1);
        tv1.setTextSize(40);
        tv1.setBackgroundColor(0x280000ff);
        tv1.setText(TEXT);

        // Set textview 2
        final Typeface typeface2 = Typeface.SANS_SERIF;
        final TextView tv2 = (TextView) findViewById(R.id.text_view2);
        tv2.setTypeface(typeface2);
        tv2.setTextSize(40);
        tv2.setBackgroundColor(0x280000ff);
        tv2.setText(TEXT);
    }
}

The custom font chelsea.ttf is from here http://www.dafont.com/chelsea.font . Nothing special about it, I can reproduce it with other fonts as well.

The TEXT string contains two lines, the first line with unicode characters that are not in the chelsea font and the second lines with characters that are in the font. The first text view is rendered with the custom font and the second with the stock san serif fonts (which contains all the unicode characters of TEXT).

Android 4.x renders it correctly, failing over to stock font when needed:

However, Android 2.3.x, does not render it correctly. It does fall back to the stock fonts (good) but uses strange metrics that resulted in way too large characters spacing:

Any suggestion how to fix it? I am open for ugly workarounds, if needed.