Reputation: 853
I already understand that if I use layout_gravity="center_horizontal"
on the text view, then the text will be center. But I don't want to use that because I want to have as little code as possible and the best way to do that is by applying gravity="center_horizontal"
to my relative layout. I am also asking this question because I am concerned about even using gravity
or layout_gravity
with relative layouts at all. As when doing my research I came upon this answer.
Notice the part that says:
Don't use gravity/layout_gravity with a RelativeLayout. Use them for Views in LinearLayouts and FrameLayouts.
Even though it seems pretty apparent to me from the relative layout Android Documentation, which clearly lists gravity
as a valid attribute, that Google intended these attributes to be used with relative layouts.
If that quote is correct, how do I center views in relative layouts?
Also, here is my code:
Notice the title is not centered horizontally
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:gravity="center_horizontal"
tools:context="com.something">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="@string/app_title"
android:layout_marginBottom="@dimen/main_spacing"
android:textSize="24sp" />
<AutoCompleteTextView
android:id="@+id/enterContact"
android:text="Enter Contact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_below="@+id/title"
android:layout_marginBottom="@dimen/main_spacing" />
</RelativeLayout>
Upvotes: 4
Views: 4997
Reputation: 511856
This is a supplemental answer to Gravity and layout_gravity on Android.
gravity
and layout_gravity
inside a Relative LayoutMy original statement that gravity
and layout_gravity
should not be used in the subviews of a RelativeLayout
was partly wrong. The gravity
actually works fine. However, layout_gravity
has no effect. This can be seen in the example below. The light green and light blue are TextViews. The other two background colors are RelativeLayouts.
As you can see, gravity
works, but layout_gravity
doesn't work.
gravity
My original answer about gravity
and layout_gravity
dealt with these attributes being applied to the Views within a ViewGroup
(specifically a LinearLayout
), not to the ViewGroup
itself. However, it is possible to set gravity
and layout_gravity
on a RelativeLayout
. The layout_gravity
would affect how the RelativeLayout
is positioned within its own parent, so I will not deal with that here. How gravity
affects the subviews, though, is shown in the image below.
I resized the widths of all the subviews so that what is happening is more clear. Note that the way RelativeLayout
handles gravity is to take all the subviews as a group and move them around the layout. This means that whichever view is widest will determine how everything else is positioned. So gravity in a Relative layout is probably only useful if all the subviews have the same width.
gravity
When you add gravity
to a LinearLayout
, it does arrange the subviews as one would expect. For example, one could "save code" by setting the gravity
of LinearLayout
to center_horizontally
. That way there is no need individually set the layout_gravity
of each subview. See the various options in the image below.
Note that when a view uses layout_gravity
, it overrides the LinearLayout's gravity. (This can be seen in the title for the two layouts in the left image. The LinearLayout gravity
was set to left
and right
, but the title TextView's layout_gravity
was set to center_horizontally
.)
When positioning views within a RelativeLayout, the general way to do it is adding things like the following to each view:
layout_alignParentTop
layout_centerVertical
layout_below
layout_toRightOf
If one wants to set all the views at once, a LinearLayout
would likely be better (or perhaps using a Style).
So to sum up,
layout_gravity
does not work for subviews in a RelativeLayout.gravity
of a RelativeLayout does work, but not as one might expect.XML for image "View gravity
and layout_gravity
inside a Relative Layout":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#e3e2ad" >
<TextView
android:id="@+id/tvTop1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:text="Views' gravity=" />
<!-- examples of gravity -->
<TextView
android:id="@+id/tvTop2"
android:layout_below="@id/tvTop1"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:id="@+id/tvTop3"
android:layout_below="@id/tvTop2"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:id="@+id/tvTop4"
android:layout_below="@id/tvTop3"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:id="@+id/tvTop5"
android:layout_below="@id/tvTop4"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#d6c6cd" >
<TextView
android:id="@+id/tvBottom1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:text="Views' layout_gravity=" />
<!-- examples of layout_gravity -->
<TextView
android:id="@+id/tvBottom2"
android:layout_below="@id/tvBottom1"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="left"
android:background="#bcf5b1"
android:text="left" />
<TextView
android:id="@+id/tvBottom3"
android:layout_below="@id/tvBottom2"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:background="#aacaff"
android:text="center_horizontal" />
<TextView
android:id="@+id/tvBottom4"
android:layout_below="@id/tvBottom3"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#bcf5b1"
android:text="right" />
<TextView
android:id="@+id/tvBottom5"
android:layout_below="@id/tvBottom4"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="#aacaff"
android:text="center" />
</RelativeLayout>
</LinearLayout>
XML for image "Relative Layout with gravity":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:background="#e3e2ad" >
<TextView
android:id="@+id/tvTop1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="Views' gravity=" />
<!-- examples of gravity -->
<TextView
android:id="@+id/tvTop2"
android:layout_below="@id/tvTop1"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:id="@+id/tvTop3"
android:layout_below="@id/tvTop2"
android:layout_width="300dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:id="@+id/tvTop4"
android:layout_below="@id/tvTop3"
android:layout_width="100dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:id="@+id/tvTop5"
android:layout_below="@id/tvTop4"
android:layout_width="150dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:background="#d6c6cd" >
<TextView
android:id="@+id/tvBottom1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="Views' gravity=" />
<!-- examples of layout_gravity -->
<TextView
android:id="@+id/tvBottom2"
android:layout_below="@id/tvBottom1"
android:layout_width="200dp"
android:layout_height="40dp"
android:gravity="left"
android:background="#bcf5b1"
android:text="left" />
<TextView
android:id="@+id/tvBottom3"
android:layout_below="@id/tvBottom2"
android:layout_width="300dp"
android:layout_height="40dp"
android:gravity="center_horizontal"
android:background="#aacaff"
android:text="center_horizontal" />
<TextView
android:id="@+id/tvBottom4"
android:layout_below="@id/tvBottom3"
android:layout_width="100dp"
android:layout_height="40dp"
android:gravity="right"
android:background="#bcf5b1"
android:text="right" />
<TextView
android:id="@+id/tvBottom5"
android:layout_below="@id/tvBottom4"
android:layout_width="150dp"
android:layout_height="40dp"
android:gravity="center"
android:background="#aacaff"
android:text="center" />
</RelativeLayout>
</LinearLayout>
XML for image "Linear Layout with gravity":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:background="#e3e2ad"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="24sp"
android:text="View's gravity=" />
<TextView
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:layout_width="300dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:layout_width="150dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:background="#d6c6cd"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="24sp"
android:text="View's gravity=" />
<TextView
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:layout_width="300dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:layout_width="150dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</LinearLayout>
</LinearLayout>
Upvotes: 15
Reputation: 3974
TlDr: android:gravity Works with RelativeLayout , you can skip to the bottom if you don't want to read the explanation
EDIT this is a giant wall of text, please bear with me
This is what I imagine you want to achieve:
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="@string/app_title"
android:layout_marginBottom="@dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true"/> <!-- LAYOUT PARAMS WORK!!!-->
Why does this work, while android:gravity
(apparently) doesn't?
if your goal is to put the TextView in the horizontal center of the Layout/Screen you have to let the RelativeLayout
know!
this is achieved through something called LayoutParams
- these are data structures defined by each View
which are used by the View's parent (in this case the RelativeLayout)
so let's say your TextView
has the following LayoutParams
:
android:layout_centerHorizontal="true"
you will get something like this:
When the RelativeLayout
is distributing its child views around the screen, along the way there is a callback method being run - onLayout(...) - which is part of a more complex method sequence that will determine the position of each child View inside the RelativeLayout, this is achieved in part by accessing the LayoutParams
in each child View
, in this case that line in your TextView
WARNING: Endless Confusion Source!
View positioning inside Layout
s / ViewGroup
s is done through LayoutParam
s the onLayout
calls
It so happens that some layouts like FrameLayout
have a LayoutParam called android:layout_gravity which causes great confusion with the android:gravity
property that each view can define, which is NOT the same and not even a LayoutParam
android:gravity
is used by any View (like a TextView
for example) to place its content inside.
Example: let's say that you change your TextView to be very high, and you want the text at the bottom of the TextView, instead of at the top
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="95dp" <------------ very high!
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="@string/app_title"
android:layout_marginBottom="@dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true" <----- LayoutParams for RelativeLayout
/>
TextView is CENTERED in the RelativeLayout but text is at the TOP of the "box"
Let's use android:gravity to manage the text position INSIDE THE TextView
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="95dp"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="@string/app_title"
android:layout_marginBottom="@dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true"
android:gravity="bottom" <---**NOT LayoutParams**, NOT passed to RLayout
/>
Result: As expected only the inside of the View changed
TLDR
Now if you want to ignore everything above and still use android:gravity with RelativeLayout, RelativeLayout
is also a View
so it has the android:gravity property, but you have to remove other properties or LayoutParams which will override the behaviour defined by the android:gravity property look at android:gravity at work with RelativeLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:gravity="bottom"> <!-- NOT LAYOUT PARAMS -->
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="95dp"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="@string/app_title"
android:layout_marginBottom="@dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true"
/>
<AutoCompleteTextView
android:id="@+id/enterContact"
android:text="Enter Contact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_below="@+id/title"
android:layout_marginBottom="@dimen/main_spacing" />
</RelativeLayout>
Upvotes: 0
Reputation: 23881
try this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#000000"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:background="#ffffffff"
android:text="TITLE"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textSize="24sp" />
<AutoCompleteTextView
android:id="@+id/enterContact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
android:layout_marginBottom="10dp"
android:background="#ffffffff"
android:text="Enter Contact"
android:textAlignment="center" />
</RelativeLayout>
Upvotes: 0
Reputation: 29783
As the documentation says:
android:gravity
Specifies how an object should position its content, on both the X and Y axes, within its own bounds.
...
center_horizontal
Place object in the horizontal center of its container, not changing its size.
So the android:gravity="center_horizontal"
will center horizontal-ing the RelativeLayout to its parent. Not making its content center horizontal.
Remember that android:layout_gravity
is used for the view itself relative to the parent or layout.
Please be aware that the behaviour of Layout can differ slightly for each API Level. And be noted, that we can't 100% sure that the visual result in Layout Editor is correct. Always test your layout in real devices.
Upvotes: 0
Reputation: 2119
I've always had problems with RelativeLayouts and TextViews too. I think that this is due to the fact that TextView calculates its size dynamically and this prevents it to work well with layout's gravity. That's just one my supposition. The solution I generally adopt is to configure a textview horizontal size with match_parent. It might be a suboptimal solution, but should work. In case you need a Fixed size textView you can put a fixed size dimension and should work too, it gives problems only with wrap_content.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:gravity="center_horizontal"
tools:context="com.something">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="@string/app_title"
android:layout_marginBottom="@dimen/main_spacing"
android:textSize="24sp" />
</RelativeLayout>
Edit: as suggested by @Valentino S., adding
android:layout_centerHorizontal="true"
with wrap_content should work too. The reason is in my head still the same: size of textView is calculated later.
Upvotes: 0
Reputation: 2135
Testing your layout, for me it's working (the TextView
is centered correctly).
However, you could also remove android:gravity="center_horizontal"
from the RelativeLayout
and add android:layout_centerHorizontal="true"
in the TextView
.
Upvotes: 0