Today I have been playing a bit with the LinearLayout and have been suprised with the results:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Big Text"
android:gravity="center_vertical|center_horizontal"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="Button"
/>
</LinearLayout>
This is a simple layout with a text view header, then a text view that I want it to cover all parent (but the space occupied by the bottom button) and a button that is placed at the botton side with the layout_gravity="bottom".
This produces a layout where header is shown correctly, center text view covers all remaining free space and the button does not appear. Why is this? Shouldn't the center text view just calculate its size taking into account the bottom button size?.
Use layout_weight="1" in your center TextView.
Always remember thumb rule
If you are using linear layout with vertical orientation as soon as it finds the control
with
android:layout_height="match_parent"
The layout will ignore all the controls present below it.
Hope this help
Vipul
In place of this
android:layout_width="match_parent"
android:layout_height="match_parent"
use 'wrap_content' like this
android:layout_width="wrap_content"/"fill_parent"
android:layout_height="wrap_content"/"fill_parent"
Shouldn't the center text view just calculate its size taking into account the bottom button size?.
No, because you tell the second TextView to match its parent's height, thus FILL_PARENT and hence it will fill up all remaining space, leaving none for the last TextView.
(...) and a button that is placed at the botton side with the layout_gravity="bottom".
Unfortunately, that's not how a LinearLayout works. If you set the orientation to vertical, basically only the left and right gravities will have effect. Vice versa, with the (default) horizontal orientation, only top and bottom work. The orientation determines in which direction the View children are dynamically positioned in order, which implies you cannot manually change the 'position' in that direction.
Now, to get the desired effect, you can give the second TextView a height of 0dp and a weight of 1, resulting in it dynamically filling up all remaining space without pushing the third TextView off the bottom. Alternatively, you can use a RelativeLayout, with which you can directly set the position, and simply instruct the middle TextView to sit below the first, but above the last.
Related
Why doesn't this center a button both horizontally and vertically on the screen?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FFFFFFFF">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/red"
android:textColor="#color/white"
android:text="click"
android:layout_gravity="center"/>
</LinearLayout>
layout_gravity specifies alignment for the button within it's parent. But this only centers the button vertically, not horizontally. If I change the orientation of the linearlayout to vertical, the button is centered horizontally, not vertically. I don't see why the orientation matters here because I only have 1 child element.
I know I can achieve this by specifying the gravity in the LinearLayout with android:gravity="true" or using a RelativeLayout and have the Button android:centerInParent="true", but I'd like to know how android came up with the layout in the code above.
P.S. Why does the background color still show as gray if that's the hex code for white?
LinearLayout will only allocate the minimum amount of space needed for a view in the direction of its orientation. That's why you can't seem to center a view in the same direction as the orientation. LinearLayout generally assumes that you want to put multiple things adjacent to each other, not occupy an entire space unconditionally for a single item.
P.S. I see the entire background of the LinearLayout as white in my preview view in Android Studio, so I don't know what you mean in your P.S.
Don't use a linear layout to display items in the middle of the screen, as these are meant to list items in a row. Use a relative layout instead. So your code should look like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FFFFFF">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/red"
android:textColor="#color/white"
android:text="click"
android:layout_centerInParent="true"/>
</RelativeLayout>
This is my layout:
TEXTVIEW
IMAGEVIEW (optional)
LINEARLAYOUT - to which I add Buttons dynamically
LINEARLAYOUT - with two buttons side by side (left button and right button)
What do I need to do to ensure that the bottom two linear layouts are fixed to the bottom of the screen, regardless of how much space they may take up? ie. The first linear layout might have 3 buttons and take up over half the screen, which is okay. It just needs to be above the left/right buttons in the last linear layout, which is fixed to the bottom.
Then I want my TextView and my ImageView vertically centred in the remaining space. The ImageView will be set to invisible if there is no image, so it could only be the text view which needs to be centred.
I've been playing around with android:gravity="bottom", android:layout_height="0dip"/android:layout_weight="1" (I later realised this would only give 50% to the text/imageview and 50% to the 2 linear layouts), but I can't get my desired result.
Any advice appreciated.
You have to take RelativeLayout.
There you have a better control of the relative position of the views, something like this:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/textView"
android:layout_above="#+id/imageView"
android:layout_centerVertical="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/imageView"
android:layout_above="#+id/ll_1"
android:layout_centerVertical="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<LinearLyout
android:id="#+id/ll_1"
android:layout_above="#+id/ll_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<LinearLyout
android:id="#+id/ll_2"
android:layout_alignParentBottom="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
I have a horizontal LinearLayout set to wrap_content. Inside is a vertical LinearLayout containing a single TextView that allows multiple lines (also wrap_content) and an ImageButton (wrap_content). Several of the components have margins and padding so things space out nicely.
When the text in the TextView is short, everything is fine. When the text wraps to multiple lines, still fine. When the text is almost long enough to wrap, the ImageButton gets clipped horizontally - its left and right sides are lopped off. If I pull out the margins and padding it works, but of course it doesn't look good.
My guess is that the layout system is calculating the text width without taking into account some of the margins and padding. Then it's laying things out, and there's less total space than that first pass at the TextView thought, so it's clipping the second item in the layout and honoring the calculated TextView width. But that is just a guess.
Short of writing my own layout, any ideas?
EDIT
Here's a screen shot from hierarchy viewer, showing where the ImageButton is clipped and with the relevant XML highlighted. The ImageButton's bounds are consistent with what I'm seeing: 27dp wide, whereas the circle image itself is actually 36dp wide, and the ImageButton has 4dp padding specified on each side.
Again, I had to choose that text carefully: any shorter and the button is fine; longer and it would wrap, and the button's fine again.
EDIT
And, here's my XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/messageBubble"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minHeight="#dimen/message_bubble_min_height"
android:layout_alignTop="#id/avatar"
android:layout_alignLeft="#id/avatar"
android:layout_marginTop="#dimen/message_bubble_margin_top"
android:layout_marginLeft="#dimen/message_bubble_inset"
android:layout_marginRight="#dimen/message_inbound_padding_inside"
android:paddingLeft="#dimen/message_bubble_padding_outside"
android:paddingRight="#dimen/message_bubble_padding_inside"
android:paddingTop="#dimen/message_bubble_padding_v"
android:paddingBottom="#dimen/message_bubble_padding_v"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/contentContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:orientation="vertical">
<TextView
android:id="#+id/messageBody"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/message_body_margin_outside"
android:layout_marginRight="#dimen/message_body_margin_inside"
android:layout_marginTop="#dimen/message_body_margin_v"
android:layout_marginBottom="#dimen/message_body_margin_v"
android:gravity="left"
android:autoLink="all"
android:textSize="17dp" />
</LinearLayout>
<include layout="#layout/view_message_action_btn" />
</LinearLayout>
And the included view_message_action_btn:
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/actionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null"
android:src="#drawable/action_btn"
android:paddingLeft="#dimen/message_action_btn_padding_h"
android:paddingRight="#dimen/message_action_btn_padding_h" />
I have this layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="left">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some text" />
</LinearLayout>
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"/>
</LinearLayout>
But if in first text view (that in LinearLayout) is a lot of text, second text view goes off the screen. This can be solved by setting android:layout_weigh="1" to linear layout. But in this case linear layout will fill all space, and I need that linear layout fill minimum space when in it short text, and not hiding second text view when in linear layout a lot of text.
If the first textview occupies too much horizontal space, the second textview is rendered outside the screen...
To avoid rendering the second textview outside the screen, you need to limit the horizontal size of the first textview. You could give the first textview an android:layout_width with a fixed numeric value. You could set android:singleLine to false. You could set android:maxWidth to an appropriate value. (I haven't tried these solutions, but they should work).
Alternatively, you may consider using a single textview instead of two in a row.
A solution is to put your first TextView in a ScrollView, and put your second TextView in a fixed footer which will never be hidden (this can be done with a RelativeLayout).
If you have too much text in your first TextView then you will be able to scroll it while still showing the second TextView.
My Login screen layout seems like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/login_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff">
<include
android:id="#+id/headerlayout"
layout="#layout/headerview"
android:layout_height="50dip"
android:layout_width="fill_parent" />
<ImageView
android:id="#+id/imgIcon"
android:src="#drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txtUserName"
android:layout_width="fill_parent"
android:layout_height="80dip"
android:lines="1"
android:textColor="#000000"
android:textStyle="bold"
android:textSize="16dip"
android:text="User Name"/>
</LinearLayout>
However I am not able to see ImageView and TextView. Only headerview is visible and white layout below it. Why is it so?
Thanks,
Stone
just add
android:orientation="vertical"
in your <LinearLayout> tag.
Edit:
By default the orientation is set to Horizontal means every component will be added horizontally, since you are using "fill_parent" to the header, so it covers all the place(width) and leave no room for other components to appear. So when you add vertical all components are placed vertically. So enough room is available for components to layout themselves.More detail here
Bydefault LinearLayout aligns all children in a single direction horizontally (if you dont specify android:orientation ) .
So here in your case it was adding views horizontally. Your header portion took full width of the screen (as you have specified android:layout_width="fill_parent" in include tag)and no space is left for that TextView and ImageView.
You just have to add orientation tag in LinearLayout and set its value to vertical.
ie android:orientation="vertical".
LinearLayout from Android Docs says
LinearLayout aligns all children in a single direction — vertically or horizontally, depending on how you define the orientation attribute. All children are stacked one after the other, so a vertical list will only have one child per row, no matter how wide they are, and a horizontal list will only be one row high (the height of the tallest child, plus padding). A LinearLayout respects margins between children and the gravity (right, center, or left alignment) of each child.