1

我使用谷歌翻译将以下字符串“我认为 CompanyXYZ 在 2014 年及以后是一家伟大的公司”翻译成希伯来语,结果是在此处输入图像描述

当我在 Galaxy S3(Android 4.3)上的 TextView 中显示此文本时,我得到在此处输入图像描述

这似乎是正确的。

当我在 Galaxy Tab 7(运行 Android 2.2)上运行相同的程序时,我得到在此处输入图像描述

这显然是不正确的。

我可以使用 android.support.v4.text.BidiFormatter 和/或 java.text.Bidi 来正确呈现这个吗?
运行以下代码时

    Bidi bidi = new Bidi(text, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
    for (int i = 0; i < bidi.getRunCount(); i++)
    {
        int start = bidi.getRunStart(i);
        int level = bidi.getRunLevel(i);
        int limit = bidi.getRunLimit(i);
        Log.d("RTL", "bidi.run["+i+"] = "+start+";"+level+";"+limit+";"+ text.substring(start, limit));
    }

我确实得到了以下 5 次运行

bidi.run[0] = 0;1;9;אני חושב 
bidi.run[1] = 9;2;19;CompanyXYZ
bidi.run[2] = 19;1;36; היא חברה גדולה ב
bidi.run[3] = 36;2;40;2014
bidi.run[4] = 40;1;46; ומעבר

因此,所有信息似乎都可用于正确呈现此字符串,但我不知道如何继续。我可以使用 BidiFormatter 吗?或者我应该覆盖 TextView.draw()?

4

3 回答 3

2

好吧,我意识到已经有一段时间了......

我为我的应用程序制作了一个函数,它可以获取双向字符串,具体取决于我认为会有所帮助的主要方向。

public static String getBidiString(String input, int direction) {
    boolean rtlContext;
    int defaultBidiDirection;
    if (direction == Bidi.DIRECTION_LEFT_TO_RIGHT) {
        rtlContext = false;
        defaultBidiDirection = Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
    } else /* if (lang == Util.Lang.HE) */{
        rtlContext = true;
        defaultBidiDirection = Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT;
    }

    Bidi bidi = new Bidi(input,defaultBidiDirection);
    if (!bidi.isMixed()) return input;



    BidiFormatter bidiFormatter = BidiFormatter.getInstance(rtlContext);
    StringBuilder bidiTestBuilder = new StringBuilder();
    for (int i = 0; i < bidi.getRunCount(); i++)
    {
        int start = bidi.getRunStart(i);
        int level = bidi.getRunLevel(i);
        int limit = bidi.getRunLimit(i);
        String run = input.substring(start, limit);

        if (level != direction) {
            run = bidiFormatter.unicodeWrap(run,!rtlContext) + " ";
        }
        bidiTestBuilder.append(run);
    }

    return bidiTestBuilder.toString();
}

direction参数应该是Bidi.DIRECTION_LEFT_TO_RIGHT或者Bidi.DIRECTION_RIGHT_TO_LEFT取决于文本的默认方向。

我当然没有声称我完全正确地实现了这一点,但这段代码适用于我的用例。

于 2016-04-18T02:46:02.520 回答
1

在您的 2.2 设备上渲染是不正确的。不同的是段落方向是LTR。“按上下文”设置段落方向是很常见的,这意味着 - 根据我运行的第一个投标。但是以其他方式设定方向是合法的。例如,Windows 文本框允许最终用户通过按left ctrlshiftright ctrlshift(左移或右移,无所谓)来切换此方向。通常,对齐遵循这个方向。

在 4.2 中引入了对 RTL 布局方向的官方支持。但甚至在此之前,从 2011 年(似乎是 4.0.1)开始,就有一个@hide方法View.setLayoutDirection() 归功于杜顺鹏,他在一年前发表了他的答案

不幸的是,2.2 甚至更老,而且这个非公共 API 不可用。考虑使用 WebView,它确实支持dir=rtl用于div和文本输入。

请注意,即使在那时,包括 Tab 7 设备在内的 ME 版本的 Android 也经常由制造商或分销商定制,以提供一定程度的双向支持,因此在您的观众将使用的设备上进行测试非常重要。

于 2014-02-28T12:20:39.597 回答
0

我认为下面的代码可以帮助你

public static Spannable getRtlBidiString(String input)
{
    return getBidiString(Spannable.Factory.getInstance().newSpannable(input), Bidi.DIRECTION_RIGHT_TO_LEFT);
}

public static Spannable getForceRtlBidiString(String input)
{
    return getForceBidiString(Spannable.Factory.getInstance().newSpannable(input), Bidi.DIRECTION_RIGHT_TO_LEFT);
}

public static Spannable getRtlBidiString(Spannable input)
{
    return getBidiString(input, Bidi.DIRECTION_RIGHT_TO_LEFT);
}

public static Spannable getLtrBidiString(Spannable input)
{
    return getBidiString(input, Bidi.DIRECTION_LEFT_TO_RIGHT);
}

public static Spannable getLtrBidiString(String input)
{
    return getBidiString(Spannable.Factory.getInstance().newSpannable(input), Bidi.DIRECTION_LEFT_TO_RIGHT);
}

public static Spannable getBidiString(Spannable input, int direction)
{
    boolean isRtl;
    int baseDirection;
    TextDirectionHeuristicCompat heu;

    if (direction == Bidi.DIRECTION_LEFT_TO_RIGHT)
    {
        isRtl = false;
        baseDirection = Bidi.DIRECTION_LEFT_TO_RIGHT;
        heu = TextDirectionHeuristicsCompat.FIRSTSTRONG_LTR;
    }
    else  /* if (lang == Util.Lang.HE) */
    {
        isRtl = true;
        baseDirection = Bidi.DIRECTION_RIGHT_TO_LEFT;
        heu = TextDirectionHeuristicsCompat.FIRSTSTRONG_RTL;
    }

    Bidi bidi = new Bidi(input.toString(), baseDirection);

    if (!bidi.isMixed())
        return input;

    BidiFormatter bidiFormatter = BidiFormatter.getInstance(isRtl);
    SpannableStringBuilder bidiBuilder = new SpannableStringBuilder();

    for (int i = 0; i < bidi.getRunCount(); i++)
    {
        int start = bidi.getRunStart(i);
        int level = bidi.getRunLevel(i);
        int limit = bidi.getRunLimit(i);

        CharSequence run = input.subSequence(start, limit);

        if (level != baseDirection)
        {
            run = bidiFormatter.unicodeWrap(run, heu, !isRtl).toString();
        }

        bidiBuilder.append(run);
    }

    return bidiBuilder;
}

public static Spannable getForceBidiString(Spannable input, int direction)
{
    boolean isRtl;
    int baseDirection;
    TextDirectionHeuristicCompat heu;

    if (direction == Bidi.DIRECTION_LEFT_TO_RIGHT)
    {
        isRtl = false;
        baseDirection = Bidi.DIRECTION_LEFT_TO_RIGHT;
        heu = TextDirectionHeuristicsCompat.ANYRTL_LTR;
    }
    else  /* if (lang == Util.Lang.HE) */
    {
        isRtl = true;
        baseDirection = Bidi.DIRECTION_RIGHT_TO_LEFT;
        heu = TextDirectionHeuristicsCompat.ANYRTL_LTR;
    }

    Bidi bidi = new Bidi(input.toString(), baseDirection);

    if (!bidi.isMixed())
        return input;

    BidiFormatter bidiFormatter = BidiFormatter.getInstance(isRtl);
    SpannableStringBuilder bidiBuilder = new SpannableStringBuilder();

    for (int i = 0; i < bidi.getRunCount(); i++)
    {
        int start = bidi.getRunStart(i);
        int level = bidi.getRunLevel(i);
        int limit = bidi.getRunLimit(i);

        CharSequence run = input.subSequence(start, limit);

        if (level != baseDirection)
        {
            run = bidiFormatter.unicodeWrap(run, heu, !isRtl).toString();
        }

        bidiBuilder.append(run);
    }

    return bidiBuilder;
}
于 2018-05-26T07:04:38.200 回答