How to get Android layout_weight to work? - android-layout

I'm so frustrated with Android's layout scaling/positioning. I can't get the OS to properly "weigh" my layouts. The base layout is a LinearLayout, and the child layouts have weights set correctly. But when it's run, these proportions aren't maintained. Example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#38921c">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="0.1"
android:orientation="vertical"
android:layout_centerVertical="true">
...(views omitted)
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="0.2"
android:orientation="vertical"
android:layout_centerVertical="true">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/zero" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/zero" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="0.7"
android:orientation="vertical"
android:layout_centerVertical="true">
...(views omitted)
</LinearLayout>
</LinearLayout>
When I run this, the screen (tablet and phone) gives way too much space to the second (0.2 weight) layout, and squeezes the layout(s) below into too small a space. What am I missing regarding proper scaling using layout_weight? Thanks.

android:layout_weight is to specify a size ratio between multiple views.
In this case, it seems you have multiple views. After you have decided how many percentage of the screen supposed to be allocated for each views then you can set it.
Example: You want to divide screen into 3 as 2/10, 3/10 and 5/10(half of the screen), then weight in order is 2, 3, 5. (e.g android:layout_weight="2")
Important: To get it work you also have to set the height or width (depending on your orientation) to 0px. Otherwise, all weight measures will be assumed garbage.

Related

GridLayout with variable row height in Xamarin

I have a fairly simple Xamarin app with a primary interface that consists of two ImageViews, one overlayed on the other. The images are the same size, and I want them to expand to fill the screen. Except that I want the bottom 100 pixels (about) reserved for a banner ad.
Without the ad, I found this simple. I used a RelativeLayout, set the layout_height and layout_width to match_parent, put both images in it, and set layout_CenterInParent to true for both of them. It works great.
And then I went to put the banner in. I tried using a GridLayout with one column and two rows, putting the prior RelativeLayout inside the top cell and the banner inside the bottom cell. But unless I restrict the height of the RelativeLayout to a fixed height, it expands until the banner is invisible. And I don't want to restrict it to a fixed height, because I want to expand it to the full height minus the banner height.
I realize that there's a basic contradiction between filling a space and restricting the height, but I'm hoping that there's some solution for this.
In css, I can use heights like wh-100 to be the full window height minus 100 pixels. Is there anything similar in Xamarin? Failing that, is there any trick I can use to achieve what I'm trying to do?
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="2"
android:columnCount="1"
android:id="#+id/gridLayout1">
<RelativeLayout
android:minWidth="25px"
android:minHeight="25px"
android:id="#+id/relativeLayout1"
android:layout_width="wrap_content"
android:layout_height="400px"
android:layout_rowWeight="1"
android:background="#ffff44">
<ImageView
android:id="#+id/img1"
android:src="#drawable/img1"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ImageView
android:id="#+id/img2"
android:src="#drawable/img2"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
<RelativeLayout
android:minWidth="100px"
android:minHeight="100px"
android:layout_height="100px"
android:id="#+id/relativeLayout2"
android:layout_width="wrap_content"
android:background="#ccff44">
<ImageView
android:id="#+id/banner_placeholder"
android:src="#drawable/banner_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
Thanks for any help.
At first, if you use the GridLayout , you can set the control's height as the parent's - 100 in the xml. But you can use the row height to set the control's height such as:
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="2"
android:columnCount="1"
android:id="#+id/gridLayout1">
<RelativeLayout
android:minWidth="25px"
android:minHeight="25px"
android:id="#+id/relativeLayout1"
android:layout_width="wrap_content"
android:layout_height="400px"
android:layout_row="0"
android:layout_rowWeight="3"
android:background="#ffff44">
<ImageView
android:id="#+id/img1"
android:src="#drawable/img1"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ImageView
android:id="#+id/img2"
android:src="#drawable/img2"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
<RelativeLayout
android:minWidth="100px"
android:minHeight="100px"
android:layout_height="100px"
android:layout_row = "1"
android:layout_rowWeight="3"
android:id="#+id/relativeLayout2"
android:layout_width="wrap_content"
android:background="#ccff44">
<ImageView
android:id="#+id/banner_placeholder"
android:src="#drawable/banner_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
This will set the first RelativeLayout's height as 3/4 of the parent and the second as the 1/4.
If you still want to set the first RelativeLayout's height as parent's - 100, you can use the ConstraintLayout instead of the GridLayout. And you need to install the package named Xamarin.AndroidX.ConstraintLayout at first.
And then:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:id="#+id/layout1"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="match_parent"
android:layout_height="100dp"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp" // in the ConstraintLayout the odp means use the rest area in the parent
app:layout_constraintBottom_toTopOf="#+id/layout1"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
In addition, the ConstraintLayout is the most using layout in the native android, it can design many effects which is hard for the other layouts to implement.

android layout: constant size of bottom view

I just started learning Android and got a problem implementing a special layout. I read a lot about layouts and tried everything that crossed my mind, but i couldnt solve it. Probably its very easy and I would be very grateful for your help!
I need a simple layout, having a bigger view at the top and a smaller one at the bottom. The lower view should have a constant size of 150dp, the upper view should be variable in height and fill the rest . It is no problem giving the upper one a constant size and the lower one the rest - but thats not the way i need it...
Thats a simplified screenshot how it should look like:
Screenshot
Thanks a lot!
Here you go:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rl_layout_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_blue_light"
android:layout_above="#+id/rl_layout_two">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"
android:layout_centerInParent="true"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/rl_layout_two"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#android:color/darker_gray"
android:padding="15dp"
android:layout_alignParentBottom="true">
</RelativeLayout>
</RelativeLayout>
This matches your expectation. Howerev, i would like to point out that generally, layout height or width are not specified.It is bad practice. I would suggest another option, using LinearLayouts with weights, find the code below.
<?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="1">
<RelativeLayout
android:id="#+id/rl_layout_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_blue_light"
android:layout_weight="0.4">
</RelativeLayout>
<RelativeLayout
android:id="#+id/rl_layout_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:padding="15dp"
android:layout_weight="0.6">
</RelativeLayout>
</LinearLayout>
Hope these help.
EDIT 1:
Check the 1st solution, it was missing the layout_above attribute, that is why it took the whole screen space and centered the image according to the whole screen space. Now, it will not, since layout one is above layout two, it will center your image according to layout one.

How to keep the aspect ratio when changing device?

I need to manage my layout with the dp, not with match_parent, or wrap_content.
This is my XML code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="1"
android:orientation="vertical"
android:paddingBottom="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:background="#drawable/backprova"
android:adjustViewBounds="true"
tools:context="com.example.settingavatar.MyAvatar" >
<!-- layer per categoria A -->
<LinearLayout
android:id="#+id/llyA"
android:layout_width="34dp"
android:layout_height="34dp"
android:layout_column="0"
android:layout_marginLeft="110dp"
android:layout_marginTop="126dp"
android:layout_gravity="center_horizontal|top"
android:layout_row="0"
android:orientation="vertical"
android:visibility="visible"
android:background="#drawable/cata1" >
</LinearLayout>
<!--anteprima dell'avatar -->
<ImageView
android:id="#+id/anteprimaAvatar"
android:layout_width="145dp"
android:layout_height="352dp"
android:layout_weight="1"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="43dp"
android:layout_marginLeft="0dp"
android:src="#drawable/avatar"
android:adjustViewBounds="true" />
<!-- other things -->
</RelativeLayout>
When I change devices, the LinearLayout and ImageView don't keep the proportions with the background image (only the aspect ratio between them).
I think the problems are height and width layout.
I have the background image file for every drawable_dpi, but the avatar and the cata1 image only for hdpi, could that be the problem?
In case you want to manage the layout just by using dp, try using an absolute layout, because the basis of using relative layout is to avoid maintaining all the views on dp basis..

Layout not working out as planned. Weights are set but going over edge of screen

I'm trying to create a new layout. My last layout that I used was GridLayout and basically created a table with 3 columns and 8 rows. With rowspan I was able to achieve the look that I wanted within Eclipse however, my screen is a little longer on my phone then Eclipse is and it shows that column 1 and 2 look good, but 3 was stretched to the right.
The new layouts looks like this:
** You can see the arrow on the right side is well over the edge of the screen and I don't know why. I'm trying to create a layout that when used on different devices will scale appropriately.
The XML code is as follows:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TableRow
android:id="#+id/tableRow1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightsum="1.0" >
<ImageView
android:id="#+id/arrowLeft"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".33"
android:src="#drawable/arrowleftoff" />
<Space
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".34" />
<ImageView
android:id="#+id/arrowRight"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".33"
android:src="#drawable/arrowrightoff" />
</LinearLayout>
</TableRow>
<TableRow
android:id="#+id/tableRow2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</LinearLayout>
</TableRow>
<TableRow
android:id="#+id/tableRow3"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</LinearLayout>
</TableRow>
</TableLayout>
The issue was caused by a lack of understanding how Eclipse works regarding layout. First, the screen shown in the Eclipse visual layout editor is an "example" of what it would look like given the selected device at the top of the window (in my case Nexus S).
Second, the Layout I was using was not anchoring to certain elements or to the parent. Therefore when the screen dimensions changed, the layout changed with it.
Conclusion: I am now using and understanding RelativeLayout and it works wonders once you figure it out.
Here is a great resource which really helped me understand what was going on: Mobile Tuts Plus: Layout Basics

Place WebView below GridView in Android Layout?

Below is the xml layout for my Android App. I am trying to positions a webview below the gridview on the screen.
Can anyone help explain what I need to do to get that to work?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/db1_root"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/HomePage"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<GridView
android:id="#+id/Grid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:scrollbars="vertical" />
<WebView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/webView1" />
</LinearLayout>
</LinearLayout>
Thanks
I think two minor changes will help make this work for you. First, when creating a LinearLayout, the android:orientation attribute is required to indicate whether the children should be added horizontally or vertically. Since you want one view on top of the other, add android:orientation=vertical to the HomePage LinearLayout. Second, your GridView currently has a android:layout_height of fill_parent. This will cause it to expand vertically and fill up the entirety of the LinearLayout, which will keep your WebView from being displayed. Try changing this attribute to wrap_content.
Making the height of both children wrap_content could possibly cause you to have some empty space in your app. If you need either the GridView or WebView to take up all of the empty space in the view, you can use the android:layout_weight attribute. Assign the view you want to expand to fill all remaining space after the rest are drawn the attribute like this: android:layout_weight=1. (Here, the 1 represents 100% of the remaining space) If you want more granular control over what percentage of the parent your children occupy, look into using decimal values with the android:layout_weight attribute or android:weightSum on the parent in conjunction with a android:layout_weight on each of the children. Hope this helps!
Use android:layout_height="wrap_content" in Gridview
Set orientation attribute in inner linear layout.
android:orientation="vertical"
Give fixed height of WebView and set android:layout_weight="" in both child.
Try below code and change according to your webview height and grid view height.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/db1_root"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/HomePage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="2"
android:orientation="vertical">
<GridView
android:id="#+id/Grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_weight="1"
android:scrollbars="vertical" />
<WebView
android:layout_width="fill_parent"
android:layout_height="200dp"
android:layout_weight="1"
android:id="#+id/webView1"
/>
</LinearLayout>
</LinearLayout>
In above code I give Height of WebView 200dp change according to your requirement.

Resources