Center multiple items in a RelativeLayout without putting them in a container?
Asked Answered
L

5

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>
Lashondra answered 17/12, 2011 at 0:25 Comment(0)
I
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>
Inflammable answered 17/12, 2011 at 1:6 Comment(6)
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.Nathalia
Tested myself... just use the code in the question and add the line like I said...Inflammable
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.Nathalia
This does not work if there are additional items below with layout_width set to fill_parent.Embus
If you fill the parent, there is no room for centering... Your comment @Embus is like saying: if you stir left your car won't go straight.Inflammable
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. ;)Embus
E
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>
Exponent answered 7/11, 2012 at 23:6 Comment(0)
M
6
android:layout_gravity="center"

will almost give what you're looking for.

Marshamarshal answered 17/12, 2011 at 1:6 Comment(1)
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)!Gratis
G
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>
Gratis answered 7/11, 2012 at 19:15 Comment(0)
I
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.

Intermigration answered 17/12, 2011 at 0:34 Comment(6)
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.Apportion
@Intermigration 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 ?Gratis
@Exponent 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 ?Gratis
Interesting, didn't know this rule existed. meta.stackexchange.com/questions/75477/…Exponent
@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. meta.stackexchange.com/questions/28759/…Exponent
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)Intermigration

© 2022 - 2024 — McMap. All rights reserved.