【问题标题】:Strange behavior of setMarginStart with supportsRTL false in Manifest清单中 supportRTL false 的 setMarginStart 的奇怪行为
【发布时间】:2019-03-08 01:14:30
【问题描述】:

考虑以下 sn-ps:

<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 中将 supportRTL 标志设置为 true,上述代码会按预期生成具有 0 边距的文本。但是,supportsRTL 为 false 时,setMarginStart 无效。

此外,如果 SupportsRTL 为 false,则无论您如何设置左边距(在 xml 中或以编程方式使用 setMargins),一旦设置了左边距,setMarginStart 对其没有任何影响。

这是预期的 android 行为还是错误?有人可以解释这种行为吗?

【问题讨论】:

    标签: android layout right-to-left


    【解决方案1】:

    tl;dr - android:supportsRtl="false" 将应用程序置于“RTL 兼容模式”,这会导致在定义 leftMargin 的任何情况下忽略 startMargin。删除android:layout_marginLeft="50dp" 属性使startMargin 生效。


    MarginLayoutParams 类中,两个不同的字段跟踪“左”边距和“开始”边距(它们的名称非常有创意:leftMarginstartMargin)。同样,两个不同的字段跟踪“右”边距和“结束”边距。

    该类几乎使用“左”和“右”边距来完成所有工作;它只是通过将“开始”和“结束”值(基于布局方向)解析为“左”或“右”的过程。这是该方法的源代码:

        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 语句的第一个分支。所以现在的问题是左边距是否“未定义”......我们知道它是不是,因为视图标签指定了android:layout_marginLeft="50dp"。因此,传递给setMarginStart() 的值将被忽略。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多