40

I have a RelativeLayout containing a pair of side-by-side buttons, which I want to be centered within the layout. I could just put the buttons in a LinearLayout and center that in the RelativeLayout, but I want to keep my xml as clean as possible.

Here's what I tried, this just puts the "apply" button in the center and the "undo" button to the left of it:

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="15sp">
  <TextView
    android:id="@+id/instructions"
    android:text="@string/instructions"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="15sp"
    android:layout_centerHorizontal="true"
    />
  <Button
    android:id="@+id/apply"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="@string/apply"
    android:textSize="20sp"
    android:layout_below="@id/instructions"
    />
  <Button
    android:id="@+id/undo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="@string/undo"
    android:textSize="20sp"
    android:layout_toLeftOf="@id/apply"
    android:layout_below="@id/instructions"
    />
</RelativeLayout>
herpderp
  • 15,819
  • 12
  • 42
  • 45

5 Answers5

63

android:gravity will align the content inside the view or layout it is used on.

android:layout_gravity will align the view or layout inside of his parent.

So adding

android:gravity="center"

to your RelativeLayout should do the trick...

Like this:

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:layout_marginTop="15sp">

</RelativeLayout>
BrainCrash
  • 12,992
  • 3
  • 32
  • 38
  • Can you give an example layout please? I don't see how this can work because you have to place one button to the left of the second and the other way around, which is a circular dependency. Which throws an IllegalStateException in a RelativeLayout. –  Dec 17 '11 at 01:24
  • Tested myself... just use the code in the question and add the line like I said... – BrainCrash Dec 17 '11 at 01:36
  • Ohh I see, I missinterpreted "center in RelativeLayout" as both vertical and horizontal - as opposed to center horizontal below the textview. This makes sense then. –  Dec 17 '11 at 01:40
  • This does not work if there are additional items below with `layout_width` set to `fill_parent`. – Physikbuddha Jul 16 '15 at 09:57
  • If you fill the parent, there is no room for centering... Your comment @Physikbuddha is like saying: if you stir left your car won't go straight. – BrainCrash Jul 16 '15 at 11:54
  • I think, gravity="center" actually sets the left padding to a value, so that the control looks centered. If I add another control that fills out the entire width, the padding has to be set to 0, so the centered control will show up on the left border. This behaviour is new to me, as I'm used to build WPF desktop apps, never had problems with layouting there. ;) – Physikbuddha Jul 16 '15 at 12:37
11

Here is an extension of BrainCrash's answer. It is a non nested option that groups and centers all three horizontally and vertically. In addition, it takes the top TextView and centers it horizontally across both buttons. If desired, you can then center the text within the TextView with android:gravity="center". I also removed the margins, added color, and set the RelativeLayout height to fill_parent to highlight the layout. Tested on API 11.

<RelativeLayout
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:gravity="center"
  android:background="@android:color/black"
  >
  <TextView
    android:id="@+id/instructions"
    android:text="TEST"
    android:textSize="20sp"
    android:background="@android:color/darker_gray"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_alignLeft="@+id/undo"
    android:layout_alignRight="@+id/apply"
    android:gravity="center"
    />
  <Button
    android:id="@+id/apply"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="APPLY"
    android:textSize="20sp"
    android:layout_below="@id/instructions"
    />
  <Button
    android:id="@+id/undo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="UNDO"
    android:textSize="20sp"
    android:layout_toLeftOf="@id/apply"
    android:layout_below="@id/instructions"
    />
</RelativeLayout>
mindriot
  • 14,149
  • 4
  • 29
  • 40
6
android:layout_gravity="center"

will almost give what you're looking for.

Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188
triggs
  • 5,890
  • 3
  • 32
  • 31
  • Omg, you answered this exactly the same time as BrianCrash. I downvoted b/c I thought you copied his answer. Sorry man (I'll try to fix the downvote)! – samus Dec 13 '12 at 18:51
4

Here is a combination of the above answer's that solved my specific situation:

Centering two separate labels within a layout that also includes a button in the left most position of the same layout (button, label, label, from left to right, where the labels are centered relative to the layout containing all three views - that is, the button doesn't push the labels off center).

I solved this by nesting two RelativeLayout's, where the outer most layout included the Button and an Inner-RelativeLayout.

The Inner-RelativeLayout contained the two text labels (TextView's).

Here is a snippet that provides the details of how the centering and other layout stuff was done:

see: RelativeLayout Gravity not applied? and Gravity and layout_gravity on Android for the difference's between gravity and layout_gravity.

Tweak the paddingLeft on the btn_button1 Button to see that the TextView's do not move.

(My apologies to havexz for the downvotes. I was too hasty in thinking that just b/c your suggestions didn't solve the exact question being ask, that they do help to solve very similar situations (the answer here solves a very specific situation, and only the combination of all these answer's solved my problem. I tried upvoting, but it won't let me unless I edit the answer's, which I don't want to do.)

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/rl_outer"
  android:layout_width="fill_parent"
  android:layout_height="50dip"
  android:background="#FF0000FF">

  <Button
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/btn_button1"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:background="#FF00FF00"
    android:text="&lt;"
    android:textSize="20sp"
    android:paddingLeft="40dip"/>

  <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_inner"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:background="#FFFF00FF"        
    android:layout_centerInParent="true"
    android:gravity="center">      

    <TextView
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/tv_text1"
      android:layout_width="wrap_content"
      android:layout_height="fill_parent"
      android:background="#FF505050"
      android:textSize="20sp"
      android:textColor="#FFFFFFFF"
      android:text="Complaint #"
      android:gravity="center"/>     

    <TextView
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/tv_text2"
      android:layout_width="wrap_content"
      android:layout_height="fill_parent"
      android:background="#FF505050"
      android:textSize="20sp"
      android:textColor="#FFFFFFFF"
      android:layout_toRightOf="@id/tv_text1"
      android:gravity="center"/>

  </RelativeLayout>
</RelativeLayout>
Community
  • 1
  • 1
samus
  • 6,102
  • 6
  • 31
  • 69
2

LinearLayout is a good option. Other than that there are options like create an invisible view and center that and then align left button to the left it and right on the right of it. BUT those are just work arounds.

havexz
  • 9,550
  • 2
  • 33
  • 29
  • Yes, it is an ugly workaround, but it's the best I've found. Either create that spacer view, or create a containing RelativeLayout/LinearLayout--so either way another View needs to be inflated, but this avoids the overhead of having nested ViewGroups. – Chad Schultz Apr 12 '12 at 17:51
  • @havexz Sorry for the downvote, as I actually did incorporate a separate layout to get a the centering I needed. I was too hasty to discard your answer b/c it the specific problem here was more "cleanly" solved by BrianCrash's answer. However when I pushed that solution a little bit further it did not suffice. It won't let me undo or upvote either ? – samus Nov 07 '12 at 19:58
  • @mindriot A pop-up states that my vote is locked in and cannot be changed unless the answer is edited. Is modifying someone's answer appropriate just to change my vote ? – samus Nov 07 '12 at 22:20
  • Interesting, didn't know this rule existed. http://meta.stackexchange.com/questions/75477/idea-behind-your-vote-is-now-locked-in-unless-this-answer-is-edited – mindriot Nov 07 '12 at 23:24
  • @SamusArin As for editing someone's answer to change a vote, here is a response from Jeff Atwood. It's from 2009, so I leave the interpretation to you. http://meta.stackexchange.com/questions/28759/increase-the-vote-too-old-to-be-changed-window/28783#28783 – mindriot Nov 07 '12 at 23:31
  • its ok...:) Don't worry. Its just a lesson learnt. SamusArin and mindriot Its good to know that people do really care about voting right. (PS: why is the restriction on more than one @ reference) – havexz Nov 08 '12 at 06:59