背景
可以使用以下代码获取当前语言环境的方向:
val isRtl=TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL
如果开发者设置了,也可以获取视图的布局方向:
val layoutDirection = ViewCompat.getLayoutDirection(someView)
问题
视图的默认布局方向不是基于其语言环境的。实际上,它是LAYOUT_DIRECTION_LTR。
当您将设备的语言环境从LTR(从左到右)语言环境(例如英语)更改为RTL(从右到左)语言环境(例如阿拉伯语或希伯来语)时,视图将相应地对齐,但视图的默认值仍然是LTR...
这意味着,给定一个视图,我无法确定它将走哪个正确的方向。
我尝试过的
我制作了一个简单的POC。它有一个带有TextView的LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/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:gravity="center_vertical" tools:context=".MainActivity">
<TextView
android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Hello World!"/>
</LinearLayout>
在代码中,我编写了区域设置和视图的方向:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL
Log.d("AppLog", "locale direction:isRTL? $isRtl")
Log.d("AppLog", "linearLayout direction:${layoutDirectionValueToStr(ViewCompat.getLayoutDirection(linearLayout))}")
Log.d("AppLog", "textView direction:${layoutDirectionValueToStr(ViewCompat.getLayoutDirection(textView))}")
}
fun layoutDirectionValueToStr(layoutDirection: Int): String =
when (layoutDirection) {
ViewCompat.LAYOUT_DIRECTION_INHERIT -> "LAYOUT_DIRECTION_INHERIT"
ViewCompat.LAYOUT_DIRECTION_LOCALE -> "LAYOUT_DIRECTION_LOCALE"
ViewCompat.LAYOUT_DIRECTION_LTR -> "LAYOUT_DIRECTION_LTR"
ViewCompat.LAYOUT_DIRECTION_RTL -> "LAYOUT_DIRECTION_RTL"
else -> "unknown"
}
}
即使我切换到RTL语言环境(希伯来语 - עברית),它仍会在日志中打印此内容:
locale direction:isRTL? true
linearLayout direction:LAYOUT_DIRECTION_LTR
textView direction:LAYOUT_DIRECTION_LTR
当然,根据当前的语言环境,textView会被对齐到正确的一侧: 如果它按照我的想象工作(意味着默认情况下采用LAYOUT_DIRECTION_LOCALE),这段代码将会检查视图是否为RTL:
fun isRTL(v: View): Boolean = when (ViewCompat.getLayoutDirection(v)) {
View.LAYOUT_DIRECTION_RTL -> true
View.LAYOUT_DIRECTION_INHERIT -> isRTL(v.parent as View)
View.LAYOUT_DIRECTION_LTR -> false
View.LAYOUT_DIRECTION_LOCALE -> TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL
else -> false
}
但它不能,因为LTR是默认的,但实际上并不重要...
所以这段代码是错误的。
问题
为什么默认情况下方向是LTR,但实际上如果区域设置已更改,则会对齐到右侧?
如何检查给定视图的方向是否为LTR或RTL,无论开发人员为其设置了什么(或未设置)?
getResources().getConfiguration().locale
替换Locale.getDefault()
吗?这样能正确返回RTL吗? - Eugen Pechanecandroid:supportsRtl="true"
?如果您查看View.resolveLayoutDirection
的源代码,它只在这种情况下起作用。 - Eugen PechaneconResume
的结果是一样的。然而,如果我使用Handler().postDelayed(...,1000)
,就能正常工作。有没有办法尽快检查它?即使在 onCreate 中?为什么默认是从左到右?这个值应该只有在需要时才强制设置,不是吗? - android developerView.getLayoutDirection
之前通过反射调用View.resolveRtlPropertiesIfNeeded
应该能解决问题。 - Eugen Pechanec