How layout_weight works? - java

I researched on another stackoverflow question//answer and found a working definition of layout_weight to be that "This attribute assigns an "importance" value to a view, and allows it to expand to fill any remaining space in the parent view"
(source:What does android:layout_weight mean?)
I am trying to apply that concept to my code.
Currently my code (without the layout weights) is
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Home"
android:gravity="center"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="About"
android:gravity="center"
/>
</LinearLayout>
And the current layout is http://imgur.com/eq6q0I8
(the home should take up all the space bc of match_parent)
However if i add android:layout_weight="1" to both text views,
i get this layout http://imgur.com/fscM0Zr
(Both are visible and share same amount of space)
My question is how is this happening from that working definition of layout_weight? layout_weight in this example will assign extra space equally to both the text views. But there is no extra space because the first one has width match_parent which will make it take the width of the entire parent(no extra space)

How is this happening ?
To fix the ideas, let's say that LinearLayout's width is 100px.
TextView Home is MATCH_PARENT so 100px
TextView About is MATCH_PARENT so 100px
So, total width used by children is 100px+100px = 200px
Now, let's compute the remaining width : this is the difference between the available width and the width used by all children :
RemainingWidth = AvailableWidth (100px) - TotalWidthUsedByChildren (200px) = -100px
Note that it is negative
There is 2 child views, so distribute the remaining width to each of them according their weight. In this case each child receive 50% of the remaining... it means that each child receive -50px.
So finally :
TextView Home width is 100px + -50px = 50px
TextView About width is 100px + -50px = 50px
Perfectly logic, but not very intuitive. So the recommendation when using layout_weight is to always set the width of chid views to 0.

Related

How can I get all available width?

I have a linear layout with horizontal orientation.
The left side of the layout is a linear layout with a vertical orientation.
The right side of the layout is a small view of fixed width 80dp * 80dp.
Problem:
If I set the left layout with width "match_parent" the right layout is not visible.
If I set the right layout with "width=0dp" and "weight=1" to get as much space as available it just wraps around the content. I mean that it does not go all the way to the next element on the right.
How can I make sure that the left element expands all the way to the parent width minus the 80 dp occupied by the right element?
Give this a try (background colors are for visualizing what is going on only):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:background="#00ff00">
</LinearLayout>
<View
android:layout_width="80dp"
android:layout_height="80dp"
android:background="#ff0000"/>
</LinearLayout>
The general approach for this is to leave the right element's width hardcoded to your 80dp and set the following on the left:
android:layout_width="0dp"
android:layout_weight="1"
This allows the right element to measure itself and reserve its 80dp and then the parent grants all the additional space to the left element since it's weight is 1.
Edit:
To explain a little further why match_parent pushes your right hand element offscreen -- LinearLayout will perform two layout passes when it has a child with a layout_weight. The first pass will allocate the minimum amount of space based on the specified widths/heights. It is during this pass that your match_parent element will behave as you're seeing and fill it's parent container, thus pushing the right element offscreen. Then, during the second layout pass, the parent LinearLayout will allocate any left-over space according to the layout_weight attributes. There is none left to allocate, so nothing changes.
If, however, you use a layout_width="0dp" on the left element, it will get no space during the first pass, and your right element will get the 80dp that it requested. During the second pass, the LinearLayout parent will allocate the remaining width according to the weights -- so in this case the left element will receive all of the unused space.
I believe the "match_parent" option will push out anything else that is with it in that layout. Try "fill_parent" on the left layout which leaves room for other things.

How does Linear Layout behaves with empty views?

In a linear layout the nested widgets are arranged horizontaly/vertically and according to their width/height.
My question is in the following:
<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"
>
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffff0000"
/>
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff00ff00"
/>
</LinearLayout>
</LinearLayout>
Why do I see only the first view? I was expecting since they were wrap_content either both would display or none. But I see in the design preview:
Also if I add android:layout_weight="2" in the first View and android:layout_weight="1" in the second the second view gets 2/3 of the space even if I add weight_sum=3 in the enclosing layout
You see only one view because you didn't give a numeric width to the views.
Because of that the first view gets all the screen and other one is not seen at all - it is at the right, next to the red one.
if you want that both of them will be with same width, just give each one the same weight, that way they will be equal to each other and will fit to the screen height or width, depends on the layout orientation of the container.
From the documentation:
android:weightSum - Defines the maximum weight sum. If unspecified, the sum is computed by
adding the layout_weight of all of the children.

Set Height of View as Percentage of screen size(Programmatically)

I am using AndroidSlidingUpPanel library.
https://github.com/umano/AndroidSlidingUpPanel
My activity_main.xml has two children. The first child is the main layout. The second child is the layout for the sliding up panel.
here I have posted the layout of the Sliding Up Panel.
There are 4 LinearLayouts defined in the ratio percentage of 15 : 15 : 60 : 10 %.
The first layout will be visible in the panel. Now I want the panel height to be 3/4th of the first layout. So here, the first layout is taking 15% of the screen but the panel height should be around 10-12 % of the screen.
Is there any way or formula that I can use to get the screen size and that sets the panel Height according the 1st layout of the xml file provided here.
I have tried to define the panel height in the Java code. but no success till now.
Sometimes the 2nd layout is also shown in the panel, sometimes only half or 1/4th of the 1st layout.
PS : Is there any way to find a height of a view BEFORE setContentView()?
<LinearLayout
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_weight="1.5"
android:background="#666666" >
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_weight="1.5"
android:background="#888888" >
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="6"
android:background="#eeeeee" >
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#202033" >
</LinearLayout>
It is possible to get the height of the Screen in Pixels. It is also possible to get the density of the screen(DPI).
The ratio of the two will give you the physical height of the screen.
DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
After getting the dpWidth (which is a physical quantity independent of density), you can easily apply percentages to it.

how to create two fixed size views and one view spanned between them in android?

I want to create a screen
with two fixed size areas: one aligned to left, one to the right
and in between them another area which spans all the rest of the area?
If I make the middle view with property fill_parent it will catch all the area to the 3rd child.
what will be the effective property when layout_weight=0.X and layout_width=20dp.?
======
I have a linearLayout with orientation= horizontal.
It has a child with layout_weight=0.X and also layout_width=20dp.
What will be the effective property?
If you have a horizontal LinearLayout with the first child with a fixed width (e.g. layout_width="20dp"), the second child with a non-zero weight (e.g. layout_weight="1") and the third with a fixed width (e.g. layout_width="20dp"), then you should get the first aligned to the left, the third aligned to the right and the third filling the area between them.
It's also possible to do this with a RelativeLayout, but I'll leave that as the above solution should work just fine.
It will be something like this:
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<View android:id="#+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<View android:id="#+id/view3"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:layout_weight="0"/>
</LinearLayout>
You should use android:layout_weight.

Fit a ImageView (and its src) to the layout width and make its height proportional

Can you help me to configure my layout? I don't achieve what I'm looking for:
I've put the imageview background to red for explain what I want:
The image's width is smaller than the layout width. I'd like the image grow proportionally keeping its aspect ratio until reach the aspect at the first image (I modified it manually with photoshop) but when setting width="fill_parent" the result is the second image and setting both width and height to "fill_parent" the result is the third image.
I tried to combine with ScaleType with no success
How can I achieve the first option? Thanks
Use android:adjustViewBounds=true attr in xml for ImageView
This question is solved here by extending the ImageView class.
Android ImageView adjusting parent's height and fitting width
I created a sample. It works for me. Here is the xml layout file.
<?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">
<ImageView android:src="#drawable/hydrangeas"
android:layout_height="wrap_content" android:id="#+id/imageView1"
android:scaleType="centerInside"
android:adjustViewBounds="true"
android:background="#android:color/white"
android:layout_width="wrap_content"/>
</LinearLayout>
It works for fitCenter too. Have a look at the snapshot.
Use the attribute fit_center into your ImageView tag.
<ImageView ... android:scaleType="fitCenter" .. />

Categories

Resources