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.
Related
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.
I am wondering if it is possible to make one View adjust it's height to it's parent height when the parent has layout_height="wrap_content". In following example:
<?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="wrap_content"
android:background="#color/red"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/time"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello"/>
</RelativeLayout>
the nested ImageView makes RelativeLayout expand it's height to match it's own parent. What I would like to achieve is that RelativeLayout has height equal to the one of the inner TextView and ImageView should work here as a background spanning only behind the text. Is this possible in pure XML without Java code tricks?
If you use a RelativeLayout (as you do), you can have Views or ViewGroups layout referencing other Views or ViewGroups by id.
In your case, if you assign an id to your TextView android:ud="#+id/tvHello" then you can align the top and bottom of your ImageView to that TextView:
android:layout_alignTop="#+id/tvHello"
android:layout_alignBottom="#+id/tvHello"
For completeness, here's your layout:
<?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="wrap_content"
android:background="#color/red"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignTop="#+id/tvHello"
android:layout_alignBottom="#+id/tvHello"
android:src="#drawable/time"/>
<TextView
android:id="#+id/tvHello"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello"/>
</RelativeLayout>
As you can see, I made the height of the ImageView 0dp. I could've chosen for wrap_content or maybe even match_parent, but because the alignTop and alignBottom overrules it's, it is better to give the view a fixed height. This is due to performance. Now android doesn't have to measure the height of the ImageView, before it's to decide to make it the same height as your TextView after all.
One other way (and perhaps better - depending on how you want your images to scale), is to attach a drawable as background to your RelativeLayout. As such:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/time"
android:orientation="vertical">
I hope this helps you out a little bit and it's helpful (it is my first time answering on stackoverflow).
happy coding!
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.
This question already has answers here:
clipChildren is not working even though set to false?
(6 answers)
Closed 1 year ago.
I have a yellow RelativeLayout containing a taller red LinearLayout.
In order to make the whole LinearLayout visible, I set android:clipChildren="false", but this does not work as expected:
<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="44dp"
android:background="#FFFF00"
android:clipChildren="false" >
<LinearLayout
android:layout_width="50dp"
android:layout_height="100dp"
android:background="#FF0000"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
with android:clipChildren="true":
with the red LinearLayout clipped as expected
with android:clipChildren="false":
where the LinearLayout height is clipped, and the width set in the layout is not respected.
What's wrong?
EDIT
If I wrap the container in a LinearLayout with both dimensions matching its parent, I get the same result (I checked that the LinearLayout container's container fill the whole screen).
<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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#FFFF00"
android:clipChildren="false" >
<LinearLayout
android:layout_width="50dp"
android:layout_height="100dp"
android:background="#FF0000"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
</LinearLayout>
EDIT 2
If I put the android:clipChildren="false" attribute in the parent LinearLayout, I get the following:
android:clipChildren="false" allows each child to draw outside of its own bounds, within the parent. It doesn't allow children to draw outside of the parent itself. For that you would need to set android:clipChildren="false" on the grandparent (as well).
I think what you're seeing with the colors is just because colors have no inherent bounds. If there is nothing clipping them, colors go forever. My theory is that if you used, say, a stretched 1x1 px image instead of a color, things would be different.
Also set
android:clipToPadding="false"
Beside:
android:clipChildren="false"
A trick which can solve your problem is to add some placeholder view
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
android:layout_alignParentBottom="true"/>
in the relative layout and boom!
Explanation
For me the boundary of relative layout seems to be different than the height.
The boundary seems to be where the content ends or where the parent ends. Adding some view to the bottom sets the boudary at the bottom so everything works fine.
First off, this is not a duplicate question, to best of my ability I've tried all (there are many) similar questions. Solutions to such problems appear to be very subjective, specific to a given scenario.
My layout currently appears as follows. Black boxes are images (logo and body, respectively), colours represent each layout:
My XML:
<?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:background="#000"
android:padding="0px"
android:layout_margin="0px"
android:orientation="vertical">
<LinearLayout
android:layout_weight="16"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFF"
android:gravity="top|center"
android:orientation="horizontal">
<ImageView
android:id="#+id/logo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/logo"
android:layout_gravity="top|center" />
</LinearLayout>
<LinearLayout
android:layout_weight="4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00F"
android:gravity="bottom|left"
android:orientation="vertical">
<ImageView
android:id="#+id/body"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/body"
android:layout_gravity="bottom|left" />
</LinearLayout>
</LinearLayout>
Here you can see I have a parent linear layout, split into two children linear layouts. This is because I need the images to be positioned differently within that part of the page.
In a nutshell, I need logo to be vertically aligned to the top, and body horizontally aligned to bottom-left.
Now, a few things that I've tried:
Using RelativeLayout rather than Linear
Switching gravity with layout_gravity for both LinearLayout and ImageView, along with combinations of excluding each
Fairly confident match_parent for width and height is what I want, but I have tried different combinations with wrap_content
What I've come to understand:
gravity:top requires the parent view use orientation:horizontal
gravity:left requires the parent view use orientation:vertical
gravity applies to the children of the view
linear_gravity applies how the child aligns with it's parent
Using the same value for gravity on the parent and linear_gravity on the child might have the same effect (when using one instead of the other)?
Hopefully this is enough information. I'm having a very difficult time wrapping my head around how these layouts work.
Thank you SO much for the help!
I think your problem is you are setting dimensions of the image views to match_parent. I would use a RelativeLayout as it seems to be the most efficient in your case (pseudo-XML-code):
RelativeLayout (width=match_parent, height=match_parent)
ImageView (width=wrap_content, height=wrap_content,
alignParentTop=true, centerHorizontal=true)
ImageView (width=wrap_content, height=wrap_content,
alignParentBottom=true, alignParentLeft=true)
You don't need any gravity setting here. You might want to play with the scaleType attribute depending on your image sizes.