Jim
Jim

Reputation: 19572

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:

enter image description here

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?

Upvotes: 1

Views: 2005

Answers (3)

Gabe Sechan
Gabe Sechan

Reputation: 93589

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>

Upvotes: 3

Avneesh Khanna
Avneesh Khanna

Reputation: 29

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>

Upvotes: 2

ibrcic
ibrcic

Reputation: 856

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.

Upvotes: 3

Related Questions