简体   繁体   中英

Why margin top and layout_above in relative view behave this way?

I am trying to place a view on top of another view and a bit outside of its bounding box.
My code simplified to show the problem:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent">


    <View
        android:id="@+id/view"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:layout_above="@+id/linear"
        android:layout_marginTop="200dp"
        android:background="@color/red"
        />

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="200dp"
        android:orientation="vertical"
        android:padding="0dp"
        android:background="@color/white"
        >

        <View
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="@color/orange"
            />
    </LinearLayout>    
</RelativeLayout>

The result:

在此处输入图片说明

The second arrow shows where I expected the small rectangle view.
Why does it show up on the top although I have specified the same top margin as the linear layout bellow it?
If I remove the android:layout_above="@+id/linear" then it goes where the second arrow shows either but bellow the orange view and not above it.
Why does relative layout do that?

Layout_above causes it to layout with its bottom directly on top of the view its named above. If you want to make it layout directly above, you'd have 0 marginTop.

Without the layout above, it goes below because the z order is determined by the order of views in the file- the lower in the file, the higher the z order.

If you want it to appear on the upper left corner of the orange view, do layout_alignTop="@id/linear" and make sure the smaller view is later in the file than the bigger view. Do not put a margin on it.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="200dp"
        android:orientation="vertical"
        android:padding="0dp"
        android:background="@color/white"
        >

        <View
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="@color/orange"
            />
    </LinearLayout>

    <View
        android:id="@+id/view"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:layout_alignTop="@+id/linear"
        android:background="@color/red"
        />
</RelativeLayout>

It is not RelativeLayout that does that but nature of margins. If you put a view (orange box) and say that there is margin of 200dp above it, then no other view can be placed in that 200dp margin.

To center a orange box and then put another view above it you need to do something like this.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <View
        android:id="@+id/view"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:layout_above="@+id/center_view"
        android:background="@color/red" />


    <View
        android:id="@+id/center_view"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="@color/orange" />


</RelativeLayout>

This will put orange view in center and red view directly on top of it. Notice that you don't even need LinearLayout but can have orange view in RelativeLayout directly.

When you include the attribute android:layout_marginTop="200dp" in the LinearLayout android:id="@+id/linear" , the margin is considered to be a part of the LinearLayout container.

Hence, effectively, the container wrapping the LinearLayout includes the margin android:layout_marginTop="200dp" . And since your root layout is a Relative Layout, the LinearLayout is aligned to the top of the root layout by default (since the LinearLayout doesn't contain any relative attributes like android:layout_below , android:layout_above etc). So when you include the android:layout_above="@+id/linear" attribute in your View tag given by android:id="@+id/view" , it is trying to place the View above LinearLayout which starts from the top of the screen.

A better way to code your layout would be:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/view"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:layout_marginTop="200dp"
        android:background="@color/red"
        />

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_below="@+id/view"
        android:orientation="vertical"
        android:padding="0dp"
        android:background="@color/white"
        >

        <View
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="@color/orange"
            />
    </LinearLayout>    
 </RelativeLayout>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM