Why doesn't gravity work when applied to Relative Layout? - android

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>

This is a supplemental answer to Gravity and layout_gravity on Android.
View gravity and layout_gravity inside a Relative Layout
My 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.
Relative Layout with 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.
Linear Layout with 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.)
Final notes
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,
The layout_gravity does not work for subviews in a RelativeLayout.
The gravity of a RelativeLayout does work, but not as one might expect.
Supplemental XML
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>

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.

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.

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.

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>

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
This is why we say LayoutParams are passed on to the parent like in the link you mentioned before
WARNING: Endless Confusion Source!
View positioning inside Layouts / ViewGroups is done through LayoutParams 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 Viewso 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>

Related

layout_gravity isn't working as expected - just partially

I have the following layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:text="#string/title_day"
android:textStyle="bold"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Tuesday"
android:textSize="16sp" />
</LinearLayout>
<TextView
android:id="#+id/tv_fail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+22"
android:textSize="16sp"
android:layout_gravity="end|center_vertical" />
</LinearLayout>
</LinearLayout>
And this looks like this:
And I want the last TextView with id tv_fail to be pinned to right end of screen. I suppose that
android:layout_gravity="end|center_vertical"
should handle it, but this instruction centers TextView vertically, but doesn't move it to end. How to fix it?
I suppose that
android:layout_gravity="end|center_vertical"
should handle it, but this instruction centers TextView vertically, but doesn't move it to end.
This is due to how LinearLayout works; your understanding of layout_gravity is generally correct.
LinearLayout takes its children and lays them out in a line, and the children will all be packed towards the "start" of the LinearLayout. In other words, a horizontal LinearLayout will ignore the horizontal component of the layout_gravity attribute of a child.
There are a few ways to work around this. The one that I think works best for your scenario is to make the TextView stretch to fill all the remaining space in the LinearLayout (using layout_weight), and then have the TextView position its text at the end of its content area (using gravity).
<TextView
android:id="#+id/tv_fail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="+22"
android:textSize="16sp"
android:layout_gravity="center_vertical"
android:gravity="end"/>
If you just want to set text inside of your last TextView to end then you should use :
android:gravity="end"
for TextView gravity use:
android:layout_gravity="center"
Difference between android:gravity & android:layout_gravity is that first one arrange content inside of any view with given gravity while second one arranges view according to given gravity.
Updated code:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:text="title_day"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Tuesday"
android:textSize="16sp" />
</LinearLayout>
<TextView
android:id="#+id/tv_fail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="+22"
android:textSize="16sp" />
</LinearLayout>

android:layout_below not properly working

I have a RelativeLayout with three views. Both TextViews should be to right of the ImageView and the seconds one should be below the first TextView.
Code:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#bdbdbd"
android:paddingBottom="15dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="15dp" >
<ImageView
android:id="#+id/avatar"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerVertical="true"
android:src="#drawable/default_avatar" />
<TextView
android:id="#+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/avatar"
android:text="Chris"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/university"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/username"
android:layout_toRightOf="#id/avatar"
android:text="Oxford"
android:textSize="13sp" />
</RelativeLayout>
Result:
After removing android:layout_centerVertical="true" from the first TextView, everything works as expected (except that it's not vertical).
Why is this and how can I make the first TextView vertical centered?
For some reason the RelativeLayout's height param is giving the problem. Try setting it to 94dp (64 of the image + 15 of bottom padding + 15 of top padding). This should solve the problem
#f. de is right. The problem is android:layout_height="wrap_content", as the height of relative layout is determined my it's content setting it's content to vertically center based on it's height wont work. You need to set this to match_parent or to a fixed value.
You also could wrap your data, in your case Name and University inside another RelativeLayout or any other ViewGroup and make it to align center.
Like that
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#bdbdbd"
android:paddingBottom="15dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="15dp">
<ImageView
android:id="#+id/avatar"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerVertical="true"
android:src="#drawable/default_avatar" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_toEndOf="#id/avatar"
android:layout_toRightOf="#id/avatar">
<TextView
android:id="#+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Chris"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/university"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/username"
android:text="Oxford"
android:textSize="13sp" />
</RelativeLayout>
</RelativeLayout>
This makes sense in order to group related views (TextViews) and also it produces better result because whole container is aligned center, in your initial example Name view is centered vertically but other view is below it and it makes it to look not as good as it will in case of container where baseline is vetical center of container.
Since trying to place both TextViews center vertical, they overlap. Use the padding attribute for the advantage.
So to align them as required, use this code.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#bdbdbd"
android:paddingBottom="15dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="15dp" >
<ImageView
android:id="#+id/avatar"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerVertical="true"
android:src="#drawable/default_avatar" />
<TextView
android:id="#+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/avatar"
android:text="Chris"
android:paddingBottom="7dp"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/university"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/username"
android:layout_toRightOf="#id/avatar"
android:paddingTop="7dp"
android:text="Oxford"
android:textSize="13sp" />
</RelativeLayout>
I wish this solves your problem...
The problem is with your RelativeLayout's height attribute,
if you change it to "match_parent" then it will work the way you wanted.
Or
you can make another Relativelayout in your main RelativeLayout who's height is "match_parent". After doing so you can place everything at any place without any problem.

Android - Place oposite views in a Layout

I have a Horizontal Layout and I have some views inside it. I want some to start from the left and others to start in the right, but I can't manage to do it. I tried several Gravity configurations but they don't do anything.
That's the case I have:
I want the Flag to be in the right and the Time to be in the left, as pointed by the arrows. I will add some more flags later.
Could anyone help me out with this? Thanks :D
EDIT:
XML so far:
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:id="#+id/hlTopBar"
android:background="#e6262626"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/default_time_date_string"
android:id="#+id/tvTime"
android:textStyle="bold"
android:paddingLeft="10dp"
android:gravity="left" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ibUSA"
android:src="#drawable/united_states_flag"
android:background="#android:color/transparent"
android:adjustViewBounds="true" />
</LinearLayout>
android:layout_gravity works in the direction opposite the orientation of the LinearLayout – the children of a vertical LinearLayout can use android:layout_gravity to control their positioning horizontally (left or right), but not vertically. In the same way children of horizontal LinearLayout can use android:layout_gravity to control their positioning vertically (top or bottom) but not horizontally. As you are using Horizontal LinearLayout you can use android:layout_gravity to position children either top or bottom.For your purpose it is better to go with RelativeLayout.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
.........
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
/>
<ImageView
.......
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
/>
</RelativeLayout>
Instead of using a horizontal layout use a Relative layout
example:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Time" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Image" />
</RelativeLayout>
result:
The RelativeLayout is a good answer. If, however, you REALLY want to do it with a LinearLayout, try putting an empty TextView in the middle, with width=0 and weight=1.
This empty view will automatically try to fill up however much space isn't taken up by the other views.
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:id="#+id/hlTopBar"
android:background="#e6262626"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/default_time_date_string"
android:id="#+id/tvTime"
android:textStyle="bold"
android:paddingLeft="10dp" />
<TextView
android:id="#+id/spacer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ibUSA"
android:src="#drawable/united_states_flag"
android:background="#android:color/transparent"
android:adjustViewBounds="true" />
</LinearLayout>

Android TextView center text

This will allow to make textview horizontally centered.
<TextView
android:id="#+id/footer_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/footer_text" />
Just change your code like this:
<TextView
android:id="#+id/footer_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textAlignment="center"
android:gravity="center"
android:text="#string/footer_text" />
This is something that is confused often when starting android. layout_gravity determines how the view is aligned within the parent. gravity centers the contents of the view within the view container. So layout_gravity would center your view in your layout, while gravity would center your text in it's view.
<TextView
android:id="#+id/footer_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/footer_text"
android:gravity="center" />
And, assuming that you want your footer to stretch the width of the layout you could do this
<TextView
android:id="#+id/footer_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/footer_text"
android:gravity="center" />
Just to handle things a little better, but again that is only if your view stretches the entire layout width.
Just wrap it for example into a LinearLayout like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/footer_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Centered text example" />
</LinearLayout>

Adding ScrollView to RelativeLayout changes position of wigdets

The following is the XML of my layout. It explicitly states that the title, time and description TextViews should be under the image of the alarm. However, as the screen shot shows, the TextViews have moved into the ImageView. Why does this happen and how can I fix this? The problem only started happening when I added the scrollview.
XML
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/img_alarm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/alarm"
android:layout_centerInParent="true"
android:contentDescription="#string/content_description_layout_alarm"/>
<TextView
android:id="#+id/lbl_alarm_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:layout_centerHorizontal="true"
android:layout_below="#+id/img_alarm"
android:layout_alignLeft="#+id/img_alarm"
android:text="#string/empty"
/>
<TextView
android:id="#+id/lbl_alarm_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:layout_centerHorizontal="true"
android:layout_below="#+id/img_alarm"
android:layout_alignRight="#+id/img_alarm"
android:text="#string/empty"
/>
<TextView
android:id="#+id/lbl_alarm_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/lbl_alarm_title"
android:layout_alignLeft="#+id/lbl_alarm_title"
android:layout_alignRight="#+id/lbl_alarm_time"
android:maxLines="1"
android:ellipsize="marquee"
android:text="#string/empty"
/>
<Button
android:id="#+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/lbl_alarm_description"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:text="#string/stop_layout_alarm"
android:gravity="center" />
</RelativeLayout>
</ScrollView>
Image
Cute app :)
hmm... not sure why it's doing it, looks like you have the right code, without busting out eclipse. but i've also had some weird bugs with relativelayout that i didn't understand and didn't have time to debug.
i do know of an alternative way you can accomplish what you're looking for -
have a scrollview that encases a linearlayout instead of a relative layout. Do these things:
For the linearlayout, you can set orientation = vertical so that it's still a top down order.
For the part where you need two textviews where one is aligned to the right and the other is aligned to the right, you need another inner linearlayout with its orientation=horizontal. then have one element align parent left, and the other align parent right. add a weightSum=1 attribute to this linearlayout and have each of the two textviews layout_width=0.5 so that each is half the width of the screen
Apply a weightSum=1 attribute to your outer most linearlayout, and see each element inside so that it's layout_weight sum adds up to 1. layout_weight will allow an element to take up that much % of real estate on the screen. like if you set your imageView to have android:layout_weight=0.8 then it'll take up 80% of the screen... since mathematically, (layout_weight/weightSum) = (.08/1) = 80%
try to use that mechanism instead, and if should work :) if it's confusing i can give code
example
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<ImageView
android:id="#+id/img_alarm"
android:layout_width="match_parent"
android:layout_height="0dip"
android:src="#drawable/alarm"
android:layout_weight="0.7"
android:contentDescription="#string/content_description_layout_alarm"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.1">
<TextView
android:id="#+id/lbl_alarm_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:text="#string/empty"
/>
<TextView
android:id="#+id/lbl_alarm_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:text="#string/empty"
/>
</LinearLayout>
<TextView
android:id="#+id/lbl_alarm_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="0.1"
android:maxLines="1"
android:ellipsize="marquee"
android:text="#string/empty"
/>
<Button
android:id="#+id/btn_stop"
android:layout_weight="0.1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:text="#string/stop_layout_alarm"
android:gravity="center" />
</LinearLayout>
</ScrollView>
i hope this deserves at least an upvote for the effort :D

Categories

Resources