当包含为片段时,视图之间的布局约束不保留

Layout constraint between Views not preserved when included as Fragment

我有一个 fragment_cameracontroller.xml,它定义了按钮的布局方式:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              tools:context="cc.closeup.android.activities.TileActivity$CameraController"
              android:id="@+id/cameracontroller_layout"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="right|top">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="150dp"
        android:layout_marginTop="5dp"
        android:id="@+id/cameracontroller_layout_top"
        android:layout_toLeftOf="@+id/cameracontroller_layout_right">

        <ImageButton
            android:id="@+id/button_togglecamera"
            android:background="@android:drawable/ic_menu_camera"
            android:layout_marginRight="8dp"
            android:layout_width="48dp"
            android:layout_height="48dp"/>

    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/cameracontroller_layout_right"
        android:layout_marginTop="15dp"
        android:layout_marginRight="5dp">

        <Button
            android:layout_width="72dp"
            android:layout_height="72dp"
            android:id="@+id/button_talk"
            android:background="@drawable/button_talk"
            android:text="@string/talk"
            android:textColor="@color/white"/>

    </LinearLayout>

</RelativeLayout>

具体来说,请注意 android:layout_toLeftOf="@+id/cameracontroller_layout_right" 约束,它指定按钮如何相互关联。

在 Android Studio 的预览中,尊重关系(绿色箭头):

但是当我稍后将该片段 xml 嵌入到 Activity 中时,两个按钮彼此重叠(在设备上)。这是 Activity XML:

<RelativeLayout
        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:orientation="vertical">

    <fragment
        android:name="cc.closeup.android.activities.TileActivity$CameraControllerFragment"
        android:id="@+id/cameracontroller"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:layout="@layout/fragment_cameracontroller"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"/>

</RelativeLayout>

我使用以下静态代码片段对片段进行扩充:

public static class CameraControllerFragment extends Fragment {
    @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_cameracontroller, container, false);
    }
}

我有什么地方做错了吗?我知道在这种情况下我可能会丢失片段根布局的宽度和高度,这取决于我如何膨胀,但这种关系存在于两个子视图之间。

嵌入在 XML 布局资源中的片段定义了它们的内容视图的布局参数。虽然 Fragment 的布局被定义为匹配 parent 的尺寸,但 Fragment 本身被定义为包装其内容。

由于第二个 child 没有锚定在 parent 的右侧,除非通过定义的重力(在测量尺寸之前无法应用),它被定位在基础锚上点 (0, 0)。第一个 child 的布局被定义在第二个 child 的左侧,后者超出了 parent 的范围。 RelativeLayout 通过匹配第二个 child.

的宽度来测量它包装到内容的宽度

如果您明确地将第二个 child 锚定到底部的另一侧(通过在您的情况下将 android:layout_alignParentRight="true" 添加到布局属性),那么 RelativeLayout 将始终消耗该维度中的最大可用 space(如果 parent 已定义和限定维度)。

RelativeLayout 似乎没有任何机制既可以包装其内容又可以定义自定义基础定位点。如果在测量时使用重力作为确定锚点的提示,那就太好了。将布局方向更改为 right-to-left 可以用作在水平轴上翻转锚点的 hack。请注意,在这种情况下,您不应定义任何自定义重力,因为在这种情况下 bug 会导致布局错误地向左偏移。