如何使用StaticLayout在自定义视图中绘制BiDi文本

Ger*_*uze 6 android drawing text bidi

在自定义的Android视图中,我正在绘制几个可能是双向的用户输入文本.例如希伯来语或阿拉伯语混合英文文本或数字.要绘制文本,我基本上使用视图的Canvas,TextPaint和StaticLayout.实际的代码相当复杂并且分散开来,但绘制文本的位看起来像这样:

TextPaint _paint = getPaint();
Canvas _canvas = ...; // the canvas passed in the View.onDraw(Canvas canvas) method
PointF l = locationCenter(); // the location at which the center of text should be painted
int alignment = getAlignment(); // for this element, can vary for each element.
PointF textSize = getTextBounds(); // the bounding box of the text
String text = userInputText(); // actually some user input BiDi text
                switch (alignment) {
                    case 0:
                        _paint.setTextAlign(Paint.Align.CENTER);
                        l.x += textSize.x / 2.0f;
                        break;
                    case 1:
                        _paint.setTextAlign(Paint.Align.LEFT);
                        l.x -= 1;
                        break;
                    default:
                        _paint.setTextAlign(Paint.Align.RIGHT);
                        l.x += (textSize.x + 1);
                        break;
                }

                StaticLayout layout = new StaticLayout(text, _paint, (int) Math.ceil(textSize.x + 0.5f), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
                _canvas.translate(l.x, l.y);
                layout.draw(_canvas);
                _canvas.translate(-l.x, -l.y);
Run Code Online (Sandbox Code Playgroud)

这适用于仅限LTR或RTL的文本,但不适用于出现乱码的Bidi文本.奇怪的是,当我强制对齐为0(导致_paint.setTextAlign(Paint.Align.Left)时,它通常似乎工作正常(=我可以测试).但是,当文本包含时,使对齐条件为0比迪(或RTL)字符,也不能正常工作.看来无论是油画,漆或StaticLayout是保持状态.

我试过像这样使用BidiFormatter:

                BidiFormatter.Builder builder = new BidiFormatter.Builder();
                builder.stereoReset(true);
                android.support.v4.text.BidiFormatter formatter = builder.build(); 
                String text = formatter.unicodeWrap(userInputText());
                // proceed as above
Run Code Online (Sandbox Code Playgroud)

但这没有区别(仍然是乱码文本).

任何想法如何在自定义视图中可靠地绘制(许多)BiDi文本?任何想法为什么强制对所有文本的 Paint.Align.Left对齐似乎解决了问题.这应该最好从android 4.0开始,但至少4.2或4.4.提前致谢.

我通过使用Character.getDirectionality来测试文本中的rtl字符或多或少地工作:

public static boolean containsRtlChar(String text) {
    for (int i = 0; i < text.length(); i++) {
        int c = text.codePointAt(i);
        int direction = Character.getDirectionality(c);
        if ((direction == Character.DIRECTIONALITY_RIGHT_TO_LEFT) || (direction == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC) || (direction == Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING) || (direction == Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE))
            return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

然后基于该力对齐到左(

                if (containsRtlChars(text)) {
                    alignment = TextStyle.textAlignLeft;
                }
Run Code Online (Sandbox Code Playgroud)

这导致包含RTL char的文本没有问题,尽管具有固定(中心)对齐.