当前位置: 首页 > 知识库问答 >
问题:

如何防止LTR布局在某些Android设备上被强制RTL?

滕学义
2023-03-14

在我的应用程序中实现RTL支持后,一位用户报告说,在阿拉伯语地区,LTR文本被强制为RTL。如下所示:

请注意文本是如何右对齐的,尽管它应该是左对齐的。

用户告诉我,这个错误只出现在

  • 华为Y5 Prime 2018版8.1.0
  • 和LG G3版本6.0.0

三星Galaxy J7 6.0.1版或Android Emulator(SDK 23、26、27、28)上不存在该功能。在RTL语言环境中,它可以正确渲染LTR,如此屏幕截图所示:

我无法在模拟器中重现它 - LTR 文本左对齐显示,而 RTL 文本(在本例中为阿拉伯语)正确右对齐显示。我怀疑根本原因是某些 OEM 添加了代码以强制在 RTL 语言环境中进行 RTL 布局。

请注意,由于我的应用程序是 RSS 提要阅读器,因此我无法控制显示的实际文本,因此我被迫依赖双向算法(工作正常!这些设备除外)。

我在清单中指定了< code > Android:supports RTL = " true " :

<application
      android:allowBackup="true"
      android:name=".FeederApplication"
      android:icon="@mipmap/ic_launcher_round"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:usesCleartextTraffic="true"
      android:theme="@style/AppTheme">
...
</application>

链接到完整清单

这是截图中的布局:

<com.nononsenseapps.feeder.views.ObservableScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/scroll_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.nononsenseapps.feeder.ui.ReaderFragment">

  <!-- Action bar is overlayed, so add some padding -->
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingStart="@dimen/keyline_1"
    android:paddingTop="?actionBarSize"
    android:paddingEnd="@dimen/keyline_1"
    android:paddingBottom="@dimen/activity_vertical_margin">


    <TextView
      android:id="@+id/story_title"
      style="@style/TextAppearance.Reader.Title"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginBottom="6dp"
      android:textDirection="anyRtl"
      android:textIsSelectable="true"
      android:transitionName="title"
      tools:text="@tools:sample/cities" />

    <TextView
      android:id="@+id/story_feedtitle"
      style="@style/TextAppearance.Reader.Author"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="2dp"
      android:layout_marginBottom="2dp"
      android:textDirection="locale"
      android:textIsSelectable="true"
      tools:text="CowboyProgrammer" />

    <TextView
      android:id="@+id/story_author"
      style="@style/TextAppearance.Reader.Author"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="2dp"
      android:layout_marginBottom="8dp"
      android:textDirection="locale"
      android:textIsSelectable="true"
      tools:text="Jonas, Sep 14 2015" />

    <com.nononsenseapps.feeder.views.LinkedTextView
      android:id="@+id/story_body"
      style="@style/TextAppearance.Reader.Body"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:minHeight="300dp"
      android:textDirection="anyRtl"
      android:textIsSelectable="true"
      tools:text="@tools:sample/lorem/random" />
  </LinearLayout>


</com.nononsenseapps.feeder.views.ObservableScrollView>

如果你想知道ImageView在哪里-没有。您在屏幕截图中看到的图像作为ImageSpan包含在LinkedTextView中。

我使用anyRtl来获得混合文本的正确格式。如果文本以英语单词开头,则默认行为(firstStrong)将文本呈现为左对齐。这是在TextViews上设置文本的代码:

val viewModel = getFeedItemViewModel(_id)
viewModel.liveItem.observe(this, androidx.lifecycle.Observer {
    rssItem = it

    rssItem?.let { rssItem ->
        setViewTitle()

        // feedDisplayTitle is a SpannableString
        mFeedTitleTextView.text = rssItem.feedDisplayTitle

        rssItem.pubDate.let { pubDate ->
            rssItem.author.let { author ->
                when {
                    author == null && pubDate != null ->
                        mAuthorTextView.text = getString(R.string.on_date,
                                pubDate.withZone(DateTimeZone.getDefault())
                                        .toString(dateTimeFormat))
                    author != null && pubDate != null ->
                        mAuthorTextView.text = getString(R.string.by_author_on_date,
                                // Must wrap author in unicode marks to ensure it formats
                                // correctly in RTL
                                unicodeWrap(author),
                                pubDate.withZone(DateTimeZone.getDefault())
                                        .toString(dateTimeFormat))
                    else -> mAuthorTextView.visibility = View.GONE
                }
            }
        }
    }
})

viewModel.liveImageText.observe(this, androidx.lifecycle.Observer {
    // the liveImageText is a SpannableString
    bodyTextView.text = it
})

// [...]

fun Fragment.unicodeWrap(text: String): String =
        BidiFormatter.getInstance(getLocale()).unicodeWrap(text)

fun Fragment.getLocale(): Locale? =
        context?.getLocale()

fun Context.unicodeWrap(text: String): String =
        BidiFormatter.getInstance(getLocale()).unicodeWrap(text)

fun Context.getLocale(): Locale =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            resources.configuration.locales[0]
        } else {
            @Suppress("DEPRECATION")
            resources.configuration.locale
        }

链接到完整文件

正如我所说,我不控制要显示的文本,我只是在显示(使用此代码)之前将(可能是HTML格式的)文本转换为SpannableString

因此,正如标题所说,有谁知道为发生此错误的特定设备添加解决方法的方法?

共有1个答案

鲜于宏义
2023-03-14

有没有可能你的用户有RTL语言的应用程序,而在某些情况下,设备在绘制文本时忽略了Bidi算法的响应?

 类似资料:
  • 我在布局上有个很奇怪的问题。它在eclipse XML编辑器和我的三星galaxy中看起来是设计的,但在我的旧手机xperia x10 mini中却搞砸了。我只能假设这也会发生在其他设备上。 如果有人能帮助解决这个问题,我将不胜感激。 下面是两个截图和XML代码。

  • 最近,我们在Android应用程序中增加了对Chromecast的支持,但在对各种移动设备(手机和平板电脑)的扩展测试中,发现在许多移动设备上,Flipps应用程序都没有发现Chromecast。在相同的设备上,我们使用了最新版本的官方Chromecast SDK演示应用程序进行测试,该应用程序从https://github.com/googlecast/castvideo-Android下载(主

  • 我的Android应用程序无法安装在一些“随机”、较旧的API设备上(任何低于API级别25的设备),错误如下: 所以,基本上看起来… API 我见过类似的问题,答案与小写的包名有关。我已经有了。 有人有什么想法吗? 舱单: BTW我用的是Visual Studio 2019和一夫一妻制3.7

  • 我要防止我的应用改变定位,强制布局坚持“画像”。 基本上。达特,我说: 但当我使用Android模拟器旋转按钮时,布局“遵循”了新设备的方向。。。 我怎样才能解决这个问题? 谢谢

  • 我正试图在后台获取用户位置。在我的手机(htc one m7)上一切都很好,但出于某种原因,它不能在我测试的两个设备上工作:三星galaxy s3索尼Xperia Z1 顺便说一句:我把所有东西都添加到了清单中。

  • 问题内容: 我看到Google Play中与Fabric / Crashlytics相关的崩溃。从正常的Crashlytics更新到新的Fabric Crashlytics之后,发生了这种情况。我只能在其中一台设备(Galaxy S2)上重现它。我拥有的所有其他设备(Nexus 5和S4)都没有崩溃。这是堆栈跟踪: 这是我的build.gradle的内容: 问题答案: 我只是凭直觉就知道了!升级到