清单中 supportsRTL false 的 setMarginStart 的奇怪行为
Strange behavior of setMarginStart with supportsRTL false in Manifest
考虑以下片段:
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:text="StrangerThings"/>
Java边,
TextView tv =findViewById(R.id.tv);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tv.getLayoutParams();
params.setMarginStart(0);
在 Android Manifest 中将 supportsRTL 标志设置为 true,上面的代码会按预期生成边距为 0 的文本。但是,如果 supportsRTL 为 false,setMarginStart 无效。
此外,在 SupportsRTL 为 false 的情况下,无论您如何设置左边距(在 xml 中或以编程方式使用 setMargins),一旦您设置了左边距,setMarginStart 就不会对其产生任何影响。
这是预期的 android 行为还是错误?有人可以解释这种行为吗?
tl;dr - android:supportsRtl="false"
将应用程序放入 "RTL compatibility mode",这会导致 startMargin
在 leftMargin
被定义。删除 android:layout_marginLeft="50dp"
属性允许 startMargin
生效。
在 MarginLayoutParams
class 内,两个不同的字段跟踪 "left" margin 和 "start" margin(它们有非常有创意的名称:leftMargin
和 startMargin
).同样,两个不同的字段跟踪 "right" 保证金和 "end" 保证金。
class 几乎所有工作都使用 "left" 和 "right" 边距;它只是通过一个将 "start" 和 "end" 值(基于布局方向)解析为 "left" 或 "right" 的过程。这是该方法的源代码:
private void doResolveMargins() {
if ((mMarginFlags & RTL_COMPATIBILITY_MODE_MASK) == RTL_COMPATIBILITY_MODE_MASK) {
// if left or right margins are not defined and if we have some start or end margin
// defined then use those start and end margins.
if ((mMarginFlags & LEFT_MARGIN_UNDEFINED_MASK) == LEFT_MARGIN_UNDEFINED_MASK
&& startMargin > DEFAULT_MARGIN_RELATIVE) {
leftMargin = startMargin;
}
if ((mMarginFlags & RIGHT_MARGIN_UNDEFINED_MASK) == RIGHT_MARGIN_UNDEFINED_MASK
&& endMargin > DEFAULT_MARGIN_RELATIVE) {
rightMargin = endMargin;
}
} else {
// We have some relative margins (either the start one or the end one or both). So use
// them and override what has been defined for left and right margins. If either start
// or end margin is not defined, just set it to default "0".
switch(mMarginFlags & LAYOUT_DIRECTION_MASK) {
case View.LAYOUT_DIRECTION_RTL:
leftMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ?
endMargin : DEFAULT_MARGIN_RESOLVED;
rightMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ?
startMargin : DEFAULT_MARGIN_RESOLVED;
break;
case View.LAYOUT_DIRECTION_LTR:
default:
leftMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ?
startMargin : DEFAULT_MARGIN_RESOLVED;
rightMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ?
endMargin : DEFAULT_MARGIN_RESOLVED;
break;
}
}
mMarginFlags &= ~NEED_RESOLUTION_MASK;
}
当使用 android:supportsRtl="false"
设置清单时,我们进入顶部 if
语句的第一个分支。所以现在的问题是左边距是否是 "undefined"... 我们知道它是 而不是 ,因为视图标签指定了 android:layout_marginLeft="50dp"
。因此,传递给 setMarginStart()
的值将被忽略。
考虑以下片段:
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:text="StrangerThings"/>
Java边,
TextView tv =findViewById(R.id.tv);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tv.getLayoutParams();
params.setMarginStart(0);
在 Android Manifest 中将 supportsRTL 标志设置为 true,上面的代码会按预期生成边距为 0 的文本。但是,如果 supportsRTL 为 false,setMarginStart 无效。
此外,在 SupportsRTL 为 false 的情况下,无论您如何设置左边距(在 xml 中或以编程方式使用 setMargins),一旦您设置了左边距,setMarginStart 就不会对其产生任何影响。
这是预期的 android 行为还是错误?有人可以解释这种行为吗?
tl;dr - android:supportsRtl="false"
将应用程序放入 "RTL compatibility mode",这会导致 startMargin
在 leftMargin
被定义。删除 android:layout_marginLeft="50dp"
属性允许 startMargin
生效。
在 MarginLayoutParams
class 内,两个不同的字段跟踪 "left" margin 和 "start" margin(它们有非常有创意的名称:leftMargin
和 startMargin
).同样,两个不同的字段跟踪 "right" 保证金和 "end" 保证金。
class 几乎所有工作都使用 "left" 和 "right" 边距;它只是通过一个将 "start" 和 "end" 值(基于布局方向)解析为 "left" 或 "right" 的过程。这是该方法的源代码:
private void doResolveMargins() {
if ((mMarginFlags & RTL_COMPATIBILITY_MODE_MASK) == RTL_COMPATIBILITY_MODE_MASK) {
// if left or right margins are not defined and if we have some start or end margin
// defined then use those start and end margins.
if ((mMarginFlags & LEFT_MARGIN_UNDEFINED_MASK) == LEFT_MARGIN_UNDEFINED_MASK
&& startMargin > DEFAULT_MARGIN_RELATIVE) {
leftMargin = startMargin;
}
if ((mMarginFlags & RIGHT_MARGIN_UNDEFINED_MASK) == RIGHT_MARGIN_UNDEFINED_MASK
&& endMargin > DEFAULT_MARGIN_RELATIVE) {
rightMargin = endMargin;
}
} else {
// We have some relative margins (either the start one or the end one or both). So use
// them and override what has been defined for left and right margins. If either start
// or end margin is not defined, just set it to default "0".
switch(mMarginFlags & LAYOUT_DIRECTION_MASK) {
case View.LAYOUT_DIRECTION_RTL:
leftMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ?
endMargin : DEFAULT_MARGIN_RESOLVED;
rightMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ?
startMargin : DEFAULT_MARGIN_RESOLVED;
break;
case View.LAYOUT_DIRECTION_LTR:
default:
leftMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ?
startMargin : DEFAULT_MARGIN_RESOLVED;
rightMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ?
endMargin : DEFAULT_MARGIN_RESOLVED;
break;
}
}
mMarginFlags &= ~NEED_RESOLUTION_MASK;
}
当使用 android:supportsRtl="false"
设置清单时,我们进入顶部 if
语句的第一个分支。所以现在的问题是左边距是否是 "undefined"... 我们知道它是 而不是 ,因为视图标签指定了 android:layout_marginLeft="50dp"
。因此,传递给 setMarginStart()
的值将被忽略。