21

Is it possible to align a view in XML in a RelativeLayout centered horizontal or vertical according another already existing view.

For example: lets say there is something like this:

enter image description here

The second text view should be displayed centered below the first text view:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="72dp"
        android:text="dynamic text" />

    <TextView
        android:id="@+id/second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/textView"
        android:layout_marginLeft="43dp" <!-- Is there a rule to center it? -->
        android:text="centered below text 1" />

</RelativeLayout>

Is is possible to implement something like that in XML? Is there a rule that i have missed yet? I do not want to calculate the position programmatically

Onik
  • 19,396
  • 14
  • 68
  • 91
sockeqwe
  • 15,574
  • 24
  • 88
  • 144

7 Answers7

35

I have a much better solution than the accepted one. NO EXTRA NESTING! You can do this by combining two attributes on the smaller view. if you are centering horizontally you can use both align_start & align_end to the bigger view. Make sure the text gravity is centered btw "android:gravity="center". For Vertical alignment use both align_top & align_bottom. below is the modified implementation of your layout.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="43dp" >

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignStart="@+id/second"
    android:layout_alignEnd="@+id/second"
    android:gravity="center"
    android:text="dynamic text" />

<TextView
    android:id="@+id/second"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/textView"
    android:gravity="center"
    android:text="centered below text 1" />

</RelativeLayout>

No need for unnecessary nesting like the accepted answer.

Jessicardo
  • 826
  • 1
  • 8
  • 12
  • 1
    Yeah, but that only works if you know the width of the textview to adjust the margin. – sockeqwe Oct 15 '14 at 20:13
  • There is no need for margin.... The margin there is what you had initially. What happens is that the smaller text's width is mad equal to the larger text, and by having the gravity center, the view will be centered relative to the larger textview. To verify this, addjust the margin of the second textview or the contents of the text and watch the first one move as well. – Jessicardo Oct 15 '14 at 20:50
  • I have also removed the explicit margin, added padding to the layout container, and updated the layout. – Jessicardo Oct 15 '14 at 20:55
  • Sorry I had the wrong spelling of the attribute because I just typed it without an editor. Modified the code and tested and it works. I had it as "align_start" instead of "layout_align_start" – Jessicardo Oct 15 '14 at 21:00
  • Note that this is only useful if the text view doesn't have a background of its own that needs to be positioned just so, or a compound drawable on one of the sides on that axis. – androidguy Nov 18 '16 at 23:12
  • This worked for me. Even when I manually set the width for the View, It always pulls the child relative to this parent to the center It seems to do the same thing ContraintLayout does – Ndifreke Apr 23 '19 at 12:55
17

Use a separate parent layout for those views and add it in your main layout(can contain other things if you have)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
         android:gravity="center"
         android:layout_marginLeft = "30dp">
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="dynamic text" />

        <TextView
            android:id="@+id/second"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="centered below text 1" />
    </LinearLayout>
...
...
other veiws go here
...

</RelativeLayout>
Noundla Sandeep
  • 3,334
  • 5
  • 29
  • 56
  • 15
    No, I do not want to center it in parent – sockeqwe May 12 '13 at 19:00
  • That is not be the correct solution. Because, RelativeLayout is the heavy weight compare to LinearLayout. So we dont include on RL into another RL unless until we develop the complex UI. In your case it is little one so It is better to use LinearLayout. – Noundla Sandeep May 12 '13 at 19:17
13

Use the followings which suits you

    android:layout_centerHorizontal="true"
    android:layout_centerInParent="true"    
    android:layout_centerVertical="true"    
stinepike
  • 54,068
  • 14
  • 92
  • 112
  • 4
    No, i do not want to center it in parent ... I want to center it below or above a certain other view. For example: The other view has a marginLeft="72dp" – sockeqwe May 12 '13 at 18:47
  • yes just use centerhoarizontal=true and place that view above or below another – stinepike May 12 '13 at 18:49
  • Hm, maybe I get you wrong, but applying this centers the second text view in parent. But i want it to be centered below the other view, so centered relative according the first view is what i want ... I guess the that could be implemented by wrapping this two views in another RelativeLayout – sockeqwe May 12 '13 at 19:00
  • only use centerhorizontal .. i wrote all because I though you want to know how to center a view in a relativelayout. – stinepike May 12 '13 at 19:01
  • No, that center it horizontally in parent, but i want to center it relative to the first text view: http://i42.tinypic.com/2jkih.jpg – sockeqwe May 12 '13 at 19:07
3

Correct solution is to use ConstraintLayout

I tried to align a textview horizontally below a button in a RelativeLayout but it was not possible as align_bottom and layout_below didn't play well together. Finally i picked up constraintLayout and tried the same logic and it worked like a charm. here is the code below.

<android.support.constraint.ConstraintLayout 
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
xmlns:android="http://schemas.android.com/apk/res/android">

<Button
    android:id="@+id/episode_recording_header_stop"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@mipmap/ic_launcher"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.399" />


<TextView
    android:id="@+id/button_selected_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:textAlignment="center"
    android:textColor="@android:color/black"
    android:textSize="12sp"
    android:text="text which is exactly center aligned w.r.t the Button above"
    app:layout_constraintEnd_toEndOf="@+id/episode_recording_header_stop"
   app:layout_constraintStart_toStartOf="@+id/episode_recording_header_stop"
    app:layout_constraintTop_toBottomOf="@+id/episode_recording_header_stop" 
    />

</android.support.constraint.ConstraintLayout>

The final output is attached below

enter image description here

Rakesh Gopathi
  • 302
  • 1
  • 12
  • As you can see the alignment is w.r.t the anchor view (button) and not the parent or any other view. – Rakesh Gopathi Jan 04 '18 at 06:58
  • Yes, just use ConstraintLayout as it allows to do stuff like that (RelativeLayout doesn't) ... – sockeqwe Jan 04 '18 at 07:19
  • @sockeqwe The accepted answer doesn't answer the question right? Also it took me some time to realize that horizontal alignment of a view w.r.t another view is not possible in RelativeLayout. The correct answer is to use ConstraintLayout for now. – Rakesh Gopathi Jan 04 '18 at 07:40
  • Sometime it is not very good idea if you should have nested layouts inside another ConstraintLayout and I guess in this way the nested ConstrainedLayout is not recommended. – Sergey V. Jul 20 '22 at 15:04
1

Do this->

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="dynamic text" />

    <TextView
        android:id="@+id/second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true" <!-- Is there a rule to center it? -->
        android:text="centered below text 1" />

</RelativeLayout>
Vishal Pawale
  • 3,416
  • 3
  • 28
  • 32
1

I found the solution: Wrap the content into another RelativeLayout and then you can place this LayoutWrapper wherever you want:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="58dp"
        android:layout_marginTop="58dp" >

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerInParent="true"
            android:text="dynamic text" />

        <TextView
            android:id="@+id/second"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textView"
            android:layout_centerInParent="true"
            android:text="centered below text 1" />
    </RelativeLayout>

</RelativeLayout>
sockeqwe
  • 15,574
  • 24
  • 88
  • 144
0

If you need to use RelativeLayout please don't use the nested layouts as far as possible. Today we have many other efficient cases to solve your task. But with use of the old faithful RelativeLayout the better way is to use attributes android:layout_alignTop, android:layout_alignBottom and android:gravity. For example, you would like to align TextView according to EditText vertically.

<RelativeLayout ...>
        ...
        <TextView
                android:id="@+id/tv1"
                ...
                android:gravity="center"
                android:layout_alignTop="@+id/edt1"
                android:layout_alignBottom="@id/edt1"/>
        <EditText
                android:id="@+id/edt1"
                ... 
                android:layout_toRightOf="@id/tv1"/>
</RelativeLayout>

enter image description here

In the same way you can use android:layout_alignLeft, android:layout_alignRight and android:gravity or android:layout_alignStart, android:layout_alignEnd and android:gravity horizontally.

Sergey V.
  • 981
  • 2
  • 12
  • 24