I am trying to get a better understanding of android layouts. In the following example I solved my problem but only through trial and error. I would like to understand WHY it worked.
I am setting up a "header" line inside another layout. I want the first part to use as much of the width as possible and the second part to use only what it needs. So I set layout_1 to have a weight of 1, layout_2 to have a weight of 0. Originally, I had both with layout_width of match_parent. That caused layout_2 to take the entire width and made layout_1 disappear. I finally fixed it by setting width on layout_2 to wrap_content. I understand that it makes sense for layout_2 to have width wrap_content. But don't understand why layout_2 match_parent would take the entire width when it has weight of 0 and layout_1 also has width match_parent.
An example of the code follows.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout android:id="#+id/header_layout_1"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_gravity="center" >
<LinearLayout android:orientation="horizontal"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:gravity="center"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="some text"/>
</LinearLayout>
<!-- changing width on header_layout_2 to match_parent takes over layout, wrap_content gives me what I want -->
<LinearLayout android:id="#+id/header_layout_2"
android:orientation="horizontal"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="0">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="some more text"/>
</LinearLayout>
</LinearLayout>
<!--end of header-->
</LinearLayout>
You can find lots of sources and blogs on The Internet about LinearLayout and layout_weight.
There are some useful websites:
https://ugia.io/2012/01/19/android-linearlayout-distribution-explained-weight-and-sizes/
http://www.101apps.co.za/index.php/articles/using-android-s-layout-weight-attribute.html
https://blog.stylingandroid.com/layout-weights-part-1/
https://www.mkyong.com/android/android-linearlayout-example/
Related
I'm trying to understand the UI behavior when parent layout_width/layout_height is set to wrap_content while in son layout_width/layout_height is set to match_parent. I found a old question in stackoverflow combining wrap_content on parent and fill_parent on child
But the post writer tried to achieve that all his sons (buttons in his case) will be at the same height, the response refereed to this purpose and not to how this conflict is set.
For example in the following code i have written:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="25dp"
android:layout_margin="#dimen/cardview_compat_inset_shadow">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textStyle="bold" />
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
I ran this code and CardView width take occupied all the screen (it seems that layout_width (match_parent) in CardView overcome on layout_width (wrap_content) in RelativeLayout. While CardView height occupied only both TextViews and not all the screen ( it seems that layout_width (wrap_content) in RelativeLayout overcome on layout_width (match_parent) in CardView
I can't find any "rule" how the conflict should be set.
I hope someone can help me understanding the logic or facts on how this conflict is set?
This question already has answers here:
What does android:layout_weight mean?
(13 answers)
Closed 2 years ago.
The xml layout is like this:
<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="match_parent"
android:layout_weight="1">
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bottom"/>
</LinearLayout>
And it turns out that the textview will be placed to the bottom of its parent.I think layout_weight is used to allocate unusesd space and it's very common to use layout_weight with code like :
android:layout_width="0dp"
But in this case,the first layout asks to occupy all spaces with:
android:layout_width="match_parent"
android:layout_height="match_parent
So how does layout weight work here?
PS:I have read this question: What does android:layout_weight mean? but I don't think it accounts for this question.
layout_weight specifies how much of the extra space in the layout to be allocated to the View.
The first linearlayout has already taken the whole space with attribute match_parent,why setting layout_weight enables the second view to showup at the bottom ?
I believe this is not the common usage of layout_weight.Hope somebody point out my mistake.
When you use layout_weight attribute it is used to calculate the weightage of child views of the single parent.
As you have not mentioned weight of all other views it's behaving wrong.
layout_weight is useful when you want your child views to be certain percentage of the parent view.
for example,
in parent view you need to mention:
android:weightSum="1"
So your parent view will have total weight as 1, and in both of the views you need to mention the:
android:layout_weight=".9" and android:layout_weight=".1"
so the first view will take 90%, and second view will take 10% of the space.
To be more clear Ideally the sum of weights of all the childs should be equal to the weightsum mentioned in parent, to it work as expected.
**And as you have provided android:layout_width,android:layout_height` of the textview, this is the mistake as it will make issue in the weight.
So to use weight attribute correctly you need to give other specs as 0dp in order to weight to apply successfully.**
Note: When you use weight other specs like android:layout_width,
android:layout_height should be set to 0dp.
To understand it practically, why don't you play around with below
layout:
Just Try to change the weight of linear_layout, text_view and you will see, how it's supposed to works ideally:
<?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"
android:weightSum="100" >
<LinearLayout
android:id="#+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:background="#android:color/holo_blue_bright" >
</LinearLayout>
<TextView
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="90"
android:background="#android:color/white"
android:text="bottom"
android:textColor="#android:color/black" />
</LinearLayout>
If you want to place your components in separate boxes in layout ,you should use LinearLayout.
You can define the manner of boxes place with orientation vertical or horizental.
You can define their size easily with layout_weight.
look here:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id=#+id/parent_linear>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4">
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="bottom"/>
</LinearLayout>
parent_linear divides your layout in 2 parts(because you use 2 components) vertically. Now you can set weights to child's components width. So,(for TextView) you set android:layout_width="0dp" for its width and android:layout_weight="2" ..follow it for LinearLayout- .
The result of this is parent_layout divide itself into 6 parts (2+4=6),and allocates 4 parts to LinearLayout and 2 for TextView.
After looking around for some time, I've yet to find a question that matches my problem. My issue is this, I have a ListView whose entries adhere to the following 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="wrap_content"
android:baselineAligned="false"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
amdroid:layout_weight="1"
android:orientation="vertical" >
...
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="vertical" >
...
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
...
</LinearLayout>
</LinearLayout>
I would expect this to produce an entry in which the 1st nested layout gets 1/4 of the available width, the 2nd gets 1/2 of the width, and the 3rd gets 1/4 of the width. This isn't what happens, though; instead, the width of each nested layout is wrapped for some reason.
Interestingly, if I specify a particular width in the parent LinearLayout instead of "match_parent", the nested layout widths obey the weights as expected. For example, the following produces the expected result:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="290dp"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
amdroid:layout_weight="1"
android:orientation="vertical" >
...
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="vertical" >
...
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
...
</LinearLayout>
</LinearLayout>
Obviously, though, specifying a particular width ignores the whole point of weights. So my question is this: why aren't the weights actually filling the parent LinearLayout when "match_parent" is used, and how can this be corrected?
Oh and one final point of interest, the graphical layout preview in Eclipse produces expected results when "match_parent" is used for the parent LinearLayout width. It's only when emulated or used on an actual device that the contents of the nested LinearLayouts get width-wrapped. I'm guessing that this is due to the layout's use inside of a ListView, but who knows?
Thanks
Alright, I feel dumb now; my suspicion was correct: the problem was with the ListView.
I had specified "wrap_content" for the ListView width in the layout that instantiates the ListView. Correcting the ListView width by specifying "match_parent" produces the expected results for the entry layout without relying on a hard-coded layout_width.
In this layout definition:
<?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:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="7"
android:id="topLayout"
android:background="#android:color/holo_green_light">
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:layout_weight="2"
android:id="bottomLayout"
android:background="#android:color/holo_orange_light">
</LinearLayout>
</LinearLayout>
I don't understand why the named "bottomLayout" is higher than the topLayout. You can see a commented screenshot of the result in Android Studio.
First of all fix your xml and change layout_height to 0dp.This is because your are using weights to manage height and at the same time your are instructing it to fill parent.
Second, if you'll experiment by giving weights as 1 for each you'll notice that both the layouts are now divided equally.What I assume is that weight is the calculation of available space that's left after adding the view i.e The weight is calculated according to the available space.
Check in your preview by clicking on the outline for any overflowing of layouts out of screen, you might find that some part of your layout is out of screen. To get some clarity either use your weights according to percentage for example instead of giving in 2 and 7 try with 0.2 and 0.8, this will balance the weigts. Or you can use the attribute "weight_sum" to declare total available weight and then distribute it evenly, for example with weight_sum 100 you can follow a percentage based approach.
See this link for further clarity.
LinearLayout children are laid out in order they are declared.
layout_weight mechanism only distributes any remaining space to elements in proportion to their weight, it doesn't affect the ordering.
This is unlike some other environments where a "weight" parameter affects an item's position in a container.
If you make your code to like this then you can find solution
<LinearLayout
android:![enter image description here][1]orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="7"
android:id="topLayout"
android:background="#android:color/holo_green_light">
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="3"
android:id="bottomLayout">
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="b"
android:id="#+id/button4"
android:layout_gravity="center"
android:background="#android:color/holo_orange_light"/>
</LinearLayout>
if you want to use layout_weight in linearlayout then you have to add weightSum in parent LinearLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="10"
android:orientation="vertical"
>
<--70% of free space in parent LinearLayout-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="7"
>
</LinearLayout>
<--30% of free space in parent LinearLayout-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
>
</LinearLayout>
</LinearLayout>
in xml comments i wrote 70% of free space in parent LinearLayout
if you add some layout with exact height then both your linearlayouts will occupy 70% and 30% of left height in that particular linearlayout
for example if height of your parent linearlayout is 100dp
your child layouts will be drawn first one 70dp and the second one will be 30dp tall
but if you add some imageview with height 50dp then your first child linearlayout will be about 35dp tall and 15dp for second one
I'm having trouble figuring out why my image isn't within the bounds of my imageview. Instead, it is floating off to the left and hidden. Is this only because the Graphical Interface doesn't show it?
EDIT:
I edited the original code to more clearly show the issue i'm having and added a picture(i want the image to show in the red box):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/top_container"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
>
<LinearLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
>
<View
android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="195"
android:background="#00FF00"/>
<ImageView
android:id="#+id/img"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ff0000"
android:src="#drawable/img" />
<View
android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:background="#0000FF"
/>
</LinearLayout>
</LinearLayout>
Ok I have it working. The height attribute of "block_container" is set to a random 200dp you WILL want to change the height to whatever your needs are, or potentially set it to "wrap_content". I tested this on emulator and device.
I am also assuming that you want all three block to be equally spaced. Notice how the parent "block_container" has a weight_sum of 9? Well the children are equal widths because they have a weight of 3 each (3 blocks * 3 weight each = 9 weight total).
I noticed before it looks like you were trying to use weight as width directly e.g. a weight of 569. Just remember weight != width directly.
EDIT: added the missing id attributes from some of the views
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/top_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:id="#+id/block_container"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:orientation="horizontal"
android:weightSum="9"
>
<View
android:id="#+id/left_block"
android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="3"
android:background="#00FF00"/>
<ImageView
android:id="#+id/img"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="3"
android:background="#ff0000"
android:src="#drawable/logo" />
<View
android:id="#+id/right_block"
android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="3"
android:background="#0000FF"
/>
</LinearLayout>
</LinearLayout>
Why are you setting android:layout_height to be 0dp? I can't even get it to display unless I change this to something like fill_parent.
Either way, its because of your layout_weight for the parent LinearLayout. Specify a larger layout_weight for your ImageView and it will come into view.
<ImageView
android:id="#+id/my_img"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="279"
android:src="#drawable/my_img" />
This worked for me.. but math might not be right.
I don't know where to begin with the issues with what you posted, some simple observations before even debugging further:
Your layouts ALL need ids (e.g. android:id="#+id/another_layout")
You have a width on the second linear layout of 0dp
Your first linear layout has a height of 0 dp, combined with the previous I'm surprised it renders at all
The last inner linear layout again has a width of 0dp
What are you trying to achieve? To me there seems to be a lot of layouts unless you have removed some elements to make it easier to understand? You could post a simple image of what you are trying to do then perhaps we can help you refine the markup?