Unusual value for layout_weight for a view - android

I was going through sample code for media effects in Android samples for API level 23 and found an unusual value (0.93) being assigned to layout_weight for one of the views contained in a LinearLayout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.opengl.GLSurfaceView
android:id="#+id/effectsview"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.93"/>
Since the layout is not having any other childviews other than android.opengl.GLSurfaceView , does this value (or android:layout_weight itself) has any significance? I tried to change this value randomly and as expected it did not have any impact on layout.
Edit : Added sample code link

If you don't have any more views with weigths nothing would happen. It's depends on it what android:layout_weight exactly does:
With layout_weight you can specify a size ratio between multiple views. E.g. you have a MapView and a table which should show some
additional information to the map. The map should use 3/4 of the
screen and table should use 1/4 of the screen. Then you will set the
layout_weight of the map to 3 and the layout_weight of the table
to 1.
To get it work you also have to set the height or width (depending on your orientation) to 0px.
Read this: What does android:layout_weight mean?
So according to your question if you don't have more views with weight, you can also delete this line of code.
EDIT: Thanks for the link. Now I know the reason of this attribute.
Mysterious fragment_media_effects.xml layout file might be already inherited in activity_main.xml, where two others views has also weights. If I am right the value of this view should change, not in Layout Editor, but when you open an app with this fragment.

Related

Tips to create a layout

I'd like to create a Layout like this.
What is the best way to perform this?
There are several ways to do it, first and common step is define border around parent layout and define margin for child layouts. after that in second step you can use one of the following to achieve this.
you can use Linearayouts with orientation vertical and then by using weightsum and weights you can achieve this.
another approach is by using Relative. in relative layout you can provide other views position relating to other layout component position.
third approach is by using Constraint layouts, provide constraints and you will achieve this.
You can use this code to make that design:
<?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:weightSum="2"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#android:color/black"
android:layout_weight="0.4"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.6"></RelativeLayout>
</LinearLayout>
You can change values of layout_weight to change the rate.
Some of the ways to achieve this layout and a few a performance cautions with these are stated below:-
1.With a linear layouts using the weights parameters will cause a performance hit, as the it would cause the views to be measured twice before being layout.And we has a deeper heirarchy with linear layouts which again causes slow rendering.
With relative layouts , even though we get a flat heirarachy but the views are measured twice before drawn, again a nested relative layout (relative layout with in another relative layout) will cause the rendering time to increase as now, the view would be measured 4 times.
3.It would be better to use constraint layout to get the better performance with flater view heirarachy.
4.You might also want to consider using fragments if the inner layout has a menu structure causing changes in first child , with frame layout as the root parent.
A few links to understand about the performance benefits:-
Android Layout Tricks #1
Understanding the performance benefits of ConstraintLayout

Android - White space on the right and the left of a LinearLayout

When I add element into a layout(in this case a LinearLayout), there is a white space on the two side of the element, but the attribute layout_width is "match_parent". Why?
Here's a screenshot:
http://s32.postimg.org/o4vr8kzbp/device_2016_07_30_001720.png
The code:
<?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:layout_width="match_parent"
android:layout_height="500dp"
android:background="#color/blue"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
I found this lines somewhere on this site and it might be worth checking;
This is possibly because you are using the auto-generated layout files in Android Studio when starting a new project, which by default adds a margin of 64dp to tablet screens (the value found inside values-w820dp\dimens). – PPartisan 6 hours ago
Maybe you should check your layout's parent's layout in the host activity for one more time.
It is possible that the root layout does not fill the parent or that the child you are adding has a margin, to know exactly whats going on use the android tool called DDMS or Android Device Monitor (you can launch it from Eclipse or Android Studio) then click on Dump View Hierarchy. This will give you details on the size, padding, margin and other properties of every view on the view hierarchy
You should to check your code, may be you update margins of layout at your classes.
And try to check layouts of home activity, may be they are contains layout_marginLeft(layout_marginStart) and layout_marginRight(layout_marginEnd).
Also parent layouts may contains any white views on the sides or parameter layout_weight with specific value.

How to set no height for a widget in Android Studio?

I am learning Android development and I'm trying to make a simple calculator. I am having some problems with layout of the calculator. In my opinion, it would be too clunky to post the whole xml code, so I'm just going to post the snippets that matter in my opinion.
I made a vertical LinearLayout as the top-most parent, which then has 2 children, a horizontal LinearLayout, (which consists of a textView which shows your input and a button that tells to calculate) and a GridLayout, which would be 0-9 buttons and operators.
The problem is, the grid layout would be a 4x4 grid with buttons and when I want to set the First row of buttons, each button needs to get layout_height, which can't be left empty and if I set it's value to match_parent, then that button alone would fill up the whole screen.
So how can I solve this problem with layout_height, is there some workaround or would it be better to make multiple LinearLayouts for the grid? If you have any additional questions, feel free to ask so I can explain.
Here is the children LinearLayout and GridLayout xml code:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_weight="1"
android:background="#color/colorLight"
android:orientation="horizontal">
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="8"
android:background="#color/colorLight"
android:>
Sorry, I misunderstand your question.
If you use API 21 or newer, you can use columnCount to get it.
Please refer to that answer or that answer
The best way to sort this out for various screen sizes is to use the weight attribute. For GridLayout, there is none, according to the documentation.
Check out this answer for ideas, such as subbing nested LinearLayouts.
GridLayout (not GridView) how to stretch all children evenly

Using layout_gravity="bottom" to place at bottom of LinearLayout

I would like to place a layout on the bottom of a LinearLayout, but I can't seem to get it to work. I know that I can use RelativeLayout to do this, but I should be able to use LinearLayout, shouldn't I?
EDIT: Actually this is more confusing than I thought. The layout below is simplified. In reality, I'm using fragments on a pre-3.0 device, with the compatibility layer.
I used Hierarchy Viewer to examine what's going on, and found that an android.support.v4.app.NoSaveStateFrameLayout was added to my layout, and that layout has layout_height set to wrap_content. That seems to be what's causing my problem, but I haven't yet figured out how to fix it.
Specifically, why doesn't this work? Shouldn't the layout_gravity place it at the bottom?
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
... stuff here ...
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="horizontal">
... more stuff here ...
</LinearLayout>
</LinearLayout>
BTW, changing layout_height to fill_parent or setting layout_weight don't seem to work either. I just want to better understand what is going on, because clearly I'm missing something important. Thanks.
First of all nice question.
Android behaves we can say weird in the situation like this.
if you have selected your parent linear layout's orientation horizontal then you can set its child component at bottom by setting its layoug_gravity=bottom. suppose you have added 2 text views in that horizontal linear layout and second textview's layout_gravity is bottom then it will set to bottom but it work like it is set at bottom in other column then the first text view. NOTE : you can set textview's layout_gravity = "left" or "right" when its parent linearlayout is horizontal but you cant see its result.
Oppositely, if you have selected parent linearlayout's orientation vertical then you can set its child component at left or right by using layout_gravity. but the second textview will shown in you can say next row with left or right gravity as you have set. NOTE you can set textview's layout_gravity = "top" or "bottom" when its linear layout is vertical but you can not see its result.
Try to make sample xml design as i have stated above so you get better idea.
Strange but True!!! Try to understand this behavior. :)
Just add space between what you want at the bottom and all the rest:
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
So I resolved the problem. It's a two-part solution:
First, the way to do this without using LinearLayout is to provide weight to the element above so that it takes up all of the empty space. BTW, you can see this example in the API demos: http://developer.android.com/resources/samples/ApiDemos/res/layout/linear_layout_3.html
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
... stuff here ...
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weight="1"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
... more stuff here ...
</LinearLayout>
</LinearLayout>
This by itself didn't solve my problem, as I had a NoSaveStateFrameLayout with layout_width="wrap_content" as a parent view, and so I needed to get that fixed first. I'm using code based on the wonderful Google I/O App, and when I searched the code for NoSaveStateFrameLayout, I found this:
// For some reason, if we omit this, NoSaveStateFrameLayout thinks we are
// FILL_PARENT / WRAP_CONTENT, making the progress bar stick to the top of the activity.
mRootView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
Thanks for an awesome comment Google!!! I added this into my source and everything worked great!
The moral of the story: Hierarchy Viewer and comments are your friends.
LinearLayout will just stack things as they are placed in there. Since it is vertical, it will keep placing items one after the next in a vertical manner. Can you change the android:gravity of the linearLayout and not the layout_gravity of the nested one and see if that works.
RelativeLayout of course should be the first way but you stated you didnt want to do that. Is there reason for that?
It could be that, as per https://stackoverflow.com/a/13366783/513038, you need to set the parent LinearLayout to have android:baselineAligned="false". Worked in my case.

Snapping elements / conditional layouts

Sorry for the extremely bad title, I have no other idea what to call this question. What I'm trying to do is this: have a RelativeLayout which has two children:
one with layout_centerInParent="true"
one with layout_alignParentBottom="true"
However, when the device is in landscape mode, element (1) appears slightly over or under element (2). But, element (1) has enough space above it to appear above element (2). How could I make the layout so that if the screen is too small to center element (1) and make both elements not overlap, then align element (1) above (as in layout_above) element (2)?
This should work to give you a layout where the text1 item fills the available space above text2, and is centered vertically and horizontally in that space; and text2 is on the bottom, centered horizontally.
<LinearLayout
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<TextView
android:id="#android:id/text1"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Centered"
android:gravity="center_vertical|center_horizontal"
/>
<TextView
android:id="#android:id/text2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Bottom"
android:gravity="center_horizontal"
/>
</LinearLayout>
The important parts are android:layout_weight, combined with android:gravity.
Alright here's a leftfield suggestion that might work if your element (1) isn't too resource intensive.
Have two versions of element (1), the first with layout_centerInParent="true" and the second with layout_above="#id\element2". Default them both to android:visibility="invisible". In your onCreate Post a Runnable that inspects the Y dimension of both elements, and sets View.VISIBLE on the element with the smallest value.
New idea:
This is another idea that's sort of a workaround in that it's not very elegant, but it's very simple. Put element (1) in its own < LinearLayout > configured like so:
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" // More on this line below
android:layout_alignParentTop="true"
android:layout_above="#id/element2"
android:gravity="center">
That linear layout will always span from the top of screen to just above element (2), and since its gravity is "center", element (1) will always be in the middle of whatever space is available for it. Note: The line android:layout_height="..." is required, but doesn't seem to actually do anything. Whether it's fill_parent or wrap_content, its height is overridden by the lines anchoring its top to the ParentTop and its bottom to element(2). However, not having the line makes it crash with a Runtime exception.
Original, not very good idea:
Another less-than-ideal solution is to use two layout files. Put the portrait layout xml in your layout folder and the landscape layout in a new folder called layout-land. Android then automatically selects the right one based on the orientation of the phone. I think you could use layout-port, but putting the portrait one in just layout makes sure it knows which one to use by default.

Categories

Resources