Fixed proportion of layout on screen - android

In my app, I have 2 linear layouts: one at the top, one at the bottom.
I'd like that whatever is inside these layout, the layout of the top occupies 60% of the height of the screen and the layout of the bottom 40%.
Here is my XML code:
<?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:layout_weight="1.0" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:orientation="vertical"
android:id="#+id/layout_top">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="0.4"
android:id="#+id/layout_bottom">
</LinearLayout>
</LinearLayout>
When these layouts are empty, no problem, they have the good proportion.
The problem is that if I put a small listview in the top layout for e.g. then the layout will take the size of the listview and won't preserve the 60/40% proportion.
I'd like that even if my listview is small (only 3 item for eg), the layout preserve it's 60% and so put some empty space under my listview.
I've tried to change android:layout_height to match_parent but it doesn't change anything.

Try using this Layout it works for me
<?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:layout_weight="1.0" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="6"
android:orientation="vertical"
android:id="#+id/layout_top"
android:background="#FF0000">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:orientation="vertical"
android:layout_weight="4"
android:id="#+id/layout_bottom"
android:background="#FF00FF">
</LinearLayout>
</LinearLayout>
The trick is to set up a layout_height="0dip" instead of wrap_content in portrait mode and layout_with="0dip" instead of wrap_content in Landscape mode you can use layout-land folder for that.

layout_weight specify extra space in the layoutfot the view. you should try measuring your screen first like:
Display display = ((WindowManager)
getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getHeight();
and then doing some calculation like width*0.6 and 0.4 , this way your layout will always have 60 40 ratio.
Hope This Helps

try layout_height = 0dp in both the children LinearLayouts. Its happening because you have wrap_content which is probably overriding the layout_weight effect.

Simply in your parent layout, replace android:layout_weight="1.0" with android:weightSum="1.0"
This works by setting the weight sum of the parent layout and the weights of the children layouts. The weight of the children should be equal to the weight sum of the parent. Take a look at this http://blog.stylingandroid.com/archives/312

Related

How can I ignore a child element's margins?

Background
I'm developing a custom notification layout by injecting an OS-generated notification view into my own layout. My layout must be as short as possible, which is 50dp in Android 10.
Problem
The view that I'm injecting into my view has margins that cause it to stretch my layout from 50dp to 66dp.
Code
The following layout is a simplification of what's going on to demonstrate the problem:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="#+id/activity_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:orientation="horizontal"
>
<TextView
android:id="#+id/full_height_view"
android:layout_width="10dp"
android:layout_height="match_parent"
android:background="#android:color/holo_blue_bright"
/>
<TextView
android:id="#+id/bad_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="46dp"
android:layout_marginBottom="20dp"
android:background="#android:color/holo_red_light"
>
</TextView>
</LinearLayout>
</FrameLayout>
Note that container has minHeight of 50dp, which I don't want to be exceeded. The problem is the margins from bad_view sum up to 66dp and stretch the parent to 66dp.
Question
How can I prevent the margins on bad_view from stretching the parent beyond its minimum height? I cannot set a fixed height on the parent because the exact height is OS-dependent. And I cannot modify bad_view because it's generated by the OS.
I ended up solving this by setting the visibility of bad_view to gone.
I found another solution: use GridLayout vertical weights to override the problematic view's height. This gave me the flexibility of a weighted horizontal LinearLayout but with the addition of vertical weights.

two views with match_parent in linear_layout in scrollview

Is it possible to have two views that are the same height of the activity screen inside of a linear_layout inside of a scrollview? I tried achieving this like so:
<?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"
android:fillViewport="true">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</ScrollView>
The only thing that appears one button with the height of the screen. The other button seems to have disappeared.
I suppose it is paradoxical to have two views to with the attribute match_parent.
However, I was hoping to get two views the same size of the available screen using xml, and having the scrollview make both views accessible. I am aware that it can be done via java, but I want an answer for xml.
In Linear Layout you have to define two things...
1 .android:orientation="vertical"
2 .android:weightSum="2"
weightSum is sum of all element in it's parent layout.It Enable you to define the proportion of width/height a element should take in a layout..
For further details go to weightSum
<ScrollView 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:layout_below="#+id/textView1"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="2" >
<Button
android:id="#+id/but1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="but 1" />
<Button
android:id="#+id/but2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="but 1" />
</LinearLayout>
</ScrollView>
output
You cannot achieve this in XML only.
As android support multiple screen sizes, At runtime you need to check for each device , the height for each device can be calculated like this
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int height = size.y;
With above code you will get the height of screen and you need to set this height in dp to your view at runtime.
Do this in your activity for both the buttons:
// get view you want to resize
Button but1= (Button) findViewById(R.id.but1);
LinearLayout.LayoutParams listLayoutParams = new LinearLayout.LayoutParams(
height , LinearLayout.LayoutParams.MATCH_PARENT);
but1.setLayoutParams(listLayoutParams);

Set width of parent linear layout as percentage of the screen

I am building an android application and I have a dialog fragment. The dialog fragment has a set width. However, the issue is that when the app is run on a device with a different screen size, the dialog fragment isn't centered properly.
Initially, what I had was:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="500dp"
android:layout_height="wrap_content">
<-- code goes here -->
</RelativeLayout>
As you can see, I have a relativeLayout with a defined width. Since I know that you can't use layout_weight in a relative layout, what I did was I wrapped that parent relative layout in a linear layout as such:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:weightSum="1">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</RelativeLayout>
</LinearLayout>
However, that doesn't work since the dialog fragment is cut when I run the application on a device with smaller screen size.
How can I set the width a dialog fragment as a percentage of the screen size? Is this possible at all or would I have to resort to setting it programmatically?
This is a correct way, if you want RelativeLayout have 40% width of the screen, but this technique cant apply to the parent layout, because parent layout doesn't have parent layout and android:layout_weight doesn't affect
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="100">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="40">
</RelativeLayout>
Since I know that you can't use layout_weight in a relative layout
We can use layout_weight in any view and layout, if it direct child of a LinearLayout
With the new percent support library, you can now use a PercentRelativeLayout.
Check out this link
The code below will make relative layout 1/2 of the parent and will position it horizontally centered:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="0.5"
android:layout_height="wrap_content">
</RelativeLayout>
</LinearLayout>
Hope it helps.

layout_weight meaning in the case of nested LinerLayout

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

How to make several RelativeLayouts each occupying a potion of the screen?

I want to have a relative layout inside another full-screen relative layout, occupying full width but 50% of its parent's height, preferably done with XML and not java code.
I have figured out how how to align parent's center, and how to fill up the width, but is there a way to get 50% of parent's height? What about 30%? 6.2834%?
<?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">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="??????????"
android:layout_centerInParent="true" >
The reason I'm trying to do percentage is that, if I specify it with "dip", while the object will remain the same size, the layout will look a lot different on different screen sizes (e.g. a phone and a tablet).
EDIT:
Thank you for all the answers about using LinearLayout and weighting. I have looked at that before, too. I feel I might have over-simplified the problem. Say I need something like this:
I suppose I could use complicated LinearLayout and weighting to outline the center square, then having the center square to fill_parent, like so:
But then what should I do with the other 3 squares (layouts)? Can I have another "layer" of LinearLayout for another square? Or should I divide up the whole screen into many, many small cells and having these sublayouts span over multiple cells (not sure if this is even possible)?
Try to use LinearLayout with weightSum
<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:weightSum="2"
android:gravity="center_vertical"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FF0000">
</RelativeLayout>
</LinearLayout>
If you don't absolutely need it nested in one RelativeLayout you can use weight in a LinearLayout as others have pointed out. I just added in an additional RelativeLayout above and below so you can use the rest of the screen if you are trying to. If not, just remove the other RelativeLayouts.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/ParentLinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="10" >
<RelativeLayout
android:id="#+id/RelativeLayoutTop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:background="#color/torange" >
</RelativeLayout>
<RelativeLayout
android:id="#+id/RelativeLayoutMid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="5"
android:background="#color/tpurple"
android:padding="8dp" >
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/describe"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/RelativeLayoutBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:background="#color/torange" >
</RelativeLayout>
I usually go with a LinearLayout for this and set the weight to a certain percentage :
<?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">
<View
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="25"/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="50">
</RelativeLayout>
<View
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="25"/>
</LinearLayout>
To your edit:
At some point you need to determine the layout. Start by taking the layout in groups. Look for patterns. In your simple explanation we have devised a way using a linearlayout to group 3 objects with one in the middle. With your new layout, could you group those items in any way?
Once you have simple layout patterns set, maybe add specific spacing that you are looking for by defining weights. Then you might want to add a relative layout and start anchoring views to specific views. Ask yourself do they overlap? Does one view always position on top of other views or on the sides. What defines the bounds of your views and then take it from there using linear layouts, weights, relative layouts, toLeftOf, toRightOf, bellow, above, margins, and padding.
Here is an example of what I mean by grouping like objects. It's by no means the best solutions but that all depends on how you define the positioning parameters.
Yellow = vertical linear layout
Green = horizontal linear layouts
You have 1 large vertical layout and inside two horizontal layouts with multiple objects inside of that. From there you can break it down into easier to manage portions on how to arrange and item within that layout. Now with relative layouts you could position items relative to another object, you could remove some of the work handled by the linear layouts but you will then be defining their distance relative to the other objects and might have to fiddle to get the layout to adjust properly on different screen sizes (reason to not use static positioning).
Maybe try using a LinearLayout with 3 layouts inside with android:layout_weight set to 1, 2, 1.
<?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" >
<RelativeLayout
android:background="#FF0000"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dip" >
</RelativeLayout>
<RelativeLayout
android:background="#00FF00"
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="0dip" >
</RelativeLayout>
<RelativeLayout
android:background="#FF0000"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dip" >
</RelativeLayout>
</LinearLayout>
RelativeLayout does not support percentage of width and height for children. Use LinearLayout with android:layout_weight attribute.

Categories

Resources