Skip to content

How to Position Views Properly in Layouts

January 14, 2010

Hey everyone,

Have you ever wondered what the difference between layout_gravity and gravity is? Or been frustrated because you included android:layout_gravity=”center” in your view but nothing was centering? In this tutorial I’ll try to address those issues and focus on the LinearLayout class.

First off, the difference between android:gravity and android:layout_gravity is that android:gravity positions the contents of that view (i.e. what’s inside the view), whereas android:layout_gravity positions the view with respect to its parent (i.e. what the view is contained in). If this isn’t clear to you now, then maybe after these examples it will become clear.

Say you have an example Layout like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <LinearLayout
    	android:orientation="horizontal"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:gravity="center" >
    <TextView  
    	android:layout_width="wrap_content" 
   	android:layout_height="wrap_content"
    	android:text="@string/hello" />
    <ImageView
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:src="@drawable/icon" />
    </LinearLayout>
</LinearLayout>

Which looks like:

And you’re wondering…

“Why is this not centering? I have two views, and I’m using gravity on the parent view so that its children (i.e. the TextView and ImageView) will be centered inside.”

Well check out what happens when you click the LinearLayout in the XML preview:

See what happened? Because your parent LinearLayout has width “wrap_content”, it’s essentially “hugging” the two views inside and so they have no space to center themselves in. What’s the fix? Change the width to “fill_parent” and see what happens:

So now that we let the parent view expand to fill the entire width of the screen, its contents have room to actually center themselves and so we’re done.

Now, let’s say that we want the TextView to stay to the left and the ImageView to go to the right. The example XML is:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <LinearLayout
    	android:orientation="horizontal"
    	android:layout_width="fill_parent"
    	android:layout_height="wrap_content" >
    <TextView  
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_gravity="left"
    	android:text="@string/hello" />
    <ImageView
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_gravity="right"
    	android:src="@drawable/icon" />
    </LinearLayout>
</LinearLayout>

And you’re thinking…

“Okay so my my parent fills the entire width and I tell the TextView to position itself with respect to its parent on the left, and I tell the ImageView to position itself with respect to its parent on the right, but how come it doesn’t work?”

Well my honest answer is: I don’t know.

[UPDATE]
It’s recently been brought to my attention (thanks to reader Sam Duke) that the “layout_gravity” property can only be used orthogonally with the orientation of the LinearLayout.

In other words, if you have a horizontal LinearLayout, then by construction, each inside child view can only have layout_gravity top, bottom, and center. The intuition behind this is that the LinearLayout is already told to place each child view horizontally adjacent to each other (left to right), and so it only allows vertical specification for the layout_gravity of each child. Vice versa for a vertical LinearLayout.

For a more in-depth explanation, I direct you to:

http://sandipchitale.blogspot.co.uk/2010/05/linearlayout-gravity-and-layoutgravity.html
[END UPDATE]

I’m not sure why this aspect of the layout is so unintuitive but there’s a fix! Simply wrap the desired view that you want to shift to the right in another LinearLayout who has width “fill_parent” and tell it to position its children to the right! To be precise, the new XML example looks like:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <LinearLayout
    	android:orientation="horizontal"
    	android:layout_width="fill_parent"
    	android:layout_height="wrap_content" >
    <TextView  
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_gravity="left"
    	android:text="@string/hello" />
    <!-- New Layout -->
    <LinearLayout
    	android:orientation="horizontal"
    	android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:gravity="right" >
    <ImageView
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:src="@drawable/icon" />
    </LinearLayout>
    </LinearLayout>
</LinearLayout>

So notice how we removed the layout_gravity=”right” from the ImageView and instead set android:gravity=”right” in the new LinearLayout. There’s no good reason for this besides that in my experience android:gravity has just worked better than layout_gravity (sometimes the behavior works as intended, and other times even I’m stumped for long periods of time). But any who, now we are left with:

And so we see the new layout in action as it fills the rest of the parent width and allows the ImageView to have the space it needs to position itself to the right!

And finally, I’ll conclude with two screen shots which illustrate the difference between layout_gravity and gravity:

<?xml version="1.0" encoding="utf-8"?>
<!-- layout_gravity example -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <LinearLayout
    	android:orientation="horizontal"
    	android:layout_width="fill_parent"
    	android:layout_height="200px" >
     <TextView  
    	android:layout_width="wrap_content"
    	android:layout_height="100px"
    	android:gravity="center"
    	android:text="@string/hello" />
    </LinearLayout>
</LinearLayout>

Again, why it does not center horizontally escapes me, but from the image you can see that at least the TextView is centering itself vertically within its parent LinearLayout. Notice however that the text in the TextView is clipped to the top, and now notice what happens when we include android:gravity=”center” in the TextView from our previous example:

So you see the TextView centering its internal contents!

That’s it for now on working with layouts. Of course I can’t provide examples for every sort of layout but hopefully the ideas and concepts behind these examples will help you when you’re making your own custom layouts!

Happy coding.

- jwei

About these ads
45 Comments leave one →
  1. brian permalink
    January 27, 2010 2:04 pm

    have you seen this thread? http://groups.google.com/group/android-developers/browse_thread/thread/7410e21361bb1b?pli=1

    it helps me to understand why.

    • January 27, 2010 2:07 pm

      no i haven’t! that thread is useful, gives us a little more insight as to the motivation behind this whole gravity and layout_gravity thing

      thanks brian

  2. Maragues permalink
    March 26, 2010 1:55 am

    Thanks, you saved my day!

  3. Fred B permalink
    April 23, 2010 3:21 pm

    Wow! I never would have figured out how to get two images, one right-aligned, and one left-aligned. I was getting nowhere – found your page and now I’m done. Thanks!

  4. May 20, 2010 5:16 am

    Hai…

    Thanks a lot, i’ve been pulling my hair trying to center an image view inside a linear layout using layout_gravity=center from image view but it didnt work. It worked after i put gravity from its parent linearlayout

    My question:
    Why if we try to center an image view using layout_gravity=center from image view itself it doesn’t work?I think it should center itself to it’s parent layout.

    • May 27, 2010 11:44 pm

      Hm could it be that the parent view was set to “wrap_content”? In which case the image view has no room to “budge” inside the parent view and so it appears that it’s not centering itself?

      That’s the only thing I could think of…

      – jwei

  5. Windman permalink
    August 12, 2010 10:31 am

    Thank you for the easy to read and “easy to digest” insight and lesson!

  6. Walter Mundt permalink
    August 14, 2010 1:45 am

    Just ran into this post. My guess so far is that LinearLayout only pays attention to layout_gravity in the orientation perpendicular the one you specify in the XML. That is, a horizontal LinearLayout’s children’s layout_gravity will only operate vertically, and a vertical LinearLayout’s children’s layout_gravity only works horizontally. Does that match up with your observations?

    • August 26, 2010 7:11 pm

      Hey Walter,

      So I believe the layout_gravity specifies how the object is placed relative to its parent, whereas the gravity attribute specifies how the object’s children are placed inside of it. Hence it doesn’t seem like the orientation inside a LinearLayout would affect how you could position it relative to its parent.

      Unless you meant “gravity” instead of “layout_gravity”, in which case I don’t think I’ve made such consistent observations but I’d be curious to go back and see if that’s the case.

      Thanks for the comment!

      – jwei

    • November 11, 2010 6:27 pm

      @Walter. I’ve found the same thing. Specifying layout_gravity inside a LinearLayout only works for perpendicular directions.

  7. Dudeson permalink
    October 16, 2010 4:23 am

    Really helpful, thanks a bunch!

  8. October 26, 2010 5:51 pm

    In that situation I usually gave up trying to figure out the how and why, and went right to a RelativeLayout and let it do the work for me.

    • June 26, 2012 10:46 pm

      True, RelativeLayout is correct way to set one item at the left side of screen and another on the right side.

      Children views of LinearLayout support layout_gravity but with horizontal LL only vertical positioning is working (top, center, bototm) and with vertical LL only horizontal positioning is working.

      A little extra, gravity works in every direction in FrameLayout view.

  9. tone permalink
    November 7, 2010 2:36 am

    thanks man lol. i was gettin pissed

  10. November 7, 2010 1:14 pm

    Thanks!

  11. November 12, 2010 12:11 am

    thanks a lot. it’s very usefull for me

  12. Tom permalink
    February 4, 2011 10:37 pm

    Phew! Luckily I found this post while I still have some hair left on my head…

  13. Andrew Martin permalink
    February 10, 2011 8:22 am

    Lifesaver, this is clearly one of the top results for “android:gravity” for a reason. :)

  14. GxKoder permalink
    February 11, 2011 3:40 am

    Made my day !
    Really helpul

  15. Kawsar permalink
    April 19, 2011 8:12 am

    Thank you! This saved me a lot of time.

  16. Peter permalink
    May 25, 2011 5:49 am

    Great article! Saved me a lot of time, thanks ;)

  17. Filip Tudic permalink
    July 24, 2011 10:27 am

    hey..nice article.
    I have a problem though. I need to set the android:layout_gravity parameter from code and I can’t find any method for that. I found for android:gravity, but not for android:layout_gravity.
    Is there any way around?
    Thanks

  18. Annon permalink
    July 27, 2011 9:29 pm

    thanks a lot!

  19. September 29, 2011 12:05 am

    Thanks a lot : )

  20. Sandy permalink
    December 3, 2011 3:33 pm

    Dang why can’t this be more intuitive! Thanks for the post, helped!

  21. January 17, 2012 8:14 pm

    Try this:

    LinearLayout with a horizontal orientation.
    2 buttons inside it, side by side. Wrapping their content.

    Shouldn’t setting the layout container to “center (contents) vertically” put the 2 buttons the same height from the top and bottom of their container?

    They aren’t. They seem to hug the inside TOP of their container.

    Why?

  22. May 5, 2012 5:54 am

    Thanks for very good idea on Gravity, we need to experiment on layouts for better results. As you mentioned Android:gravity is really better

  23. nalaka permalink
    July 4, 2012 8:15 pm

    many thanks….

  24. waterfif permalink
    August 28, 2012 4:30 am

    Many thanks! That saved alot of time.

  25. September 12, 2012 2:48 am

    Thanks a lot for this wonderful explanation….. the Android documentation always lacks this basic but yet important concept detail explanation due to which we developer are left without crystal understanding about view arrangement and drawing……..Your explanation has given me a crystal clear understanding about difference between gravity and layout_gravity

  26. Sam Duke permalink
    September 12, 2012 5:15 am

    Hi there, your second example you say you don’t know why it doesnt work. I think you are missing the point of a linearlayout. This was a very useful article for me to understand this. Essentially layout_gravity can only be used orthogonally tot he orientation of a linearlayout:

    http://sandipchitale.blogspot.co.uk/2010/05/linearlayout-gravity-and-layoutgravity.html

    • September 12, 2012 6:02 am

      Hey Sam,

      Thanks for this! I’ll make sure to incorporate this into my post as well =)

      Had no idea this orthogonality rule existed but good to know!

      – jwei

      • Sam Duke permalink
        September 12, 2012 6:06 am

        no problem. the key point is that linearlayout puts items right next to eachother. the other solution to that problem is to give the first item in the linearlayout android:weight=”1″ and android:layout_width=”0dp” this will give that item the highest priority for width in the linearlayout, so it will fill remaining space.

      • September 12, 2012 7:16 am

        Hey Sam,

        Agreed. I think the cleanest solution to this problem is to use a RelativeLayout and align the inner children to the left/right.

        I’ll make sure to include all these updates (the tutorial is a tad out of date), and credit you of course =)

        Thanks again!

        – jwei

      • Sam Duke permalink
        September 12, 2012 8:17 am

        :) thanks.

        I agree that the more natural layout to use for this kind of thing is relative layout. There are some cases you can get into where using a linear layout with a weight set to 1 can be useful (Romain Guy uses it here: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/ … you could probably just as well do that part with relativelayout so its nice to know about both ways)

      • September 12, 2012 11:34 am

        Ah very neat – yes I’ve never experimented much with layout weights so this is good to know. Romain Guy is probably one of the few people who know Android inside out… so whatever he says… the rest of us should probably listen =P

        – jwei

Trackbacks

  1. Problem with layout_gravity « Hopbit's Dev Blog
  2. Android User Interface Layout « tediscript.wordpress.com
  3. PM's Blog
  4. Android: Vertical Alignment video
  5. Android: Vertical Alignment : Android Community - For Application Development
  6. How to position a ListView in Android? : Android Community - For Application Development
  7. Align icon and the title in Listview item : Android Community - For Application Development
  8. Android – gravity and layout_gravity | Everyday I'm coding

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 887 other followers

%d bloggers like this: