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.
I'm trying to understand the UI behavior when parent layout_width/layout_height is set to wrap_content while in son layout_width/layout_height is set to match_parent. I found a old question in stackoverflow combining wrap_content on parent and fill_parent on child
But the post writer tried to achieve that all his sons (buttons in his case) will be at the same height, the response refereed to this purpose and not to how this conflict is set.
For example in the following code i have written:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="25dp"
android:layout_margin="#dimen/cardview_compat_inset_shadow">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textStyle="bold" />
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
I ran this code and CardView width take occupied all the screen (it seems that layout_width (match_parent) in CardView overcome on layout_width (wrap_content) in RelativeLayout. While CardView height occupied only both TextViews and not all the screen ( it seems that layout_width (wrap_content) in RelativeLayout overcome on layout_width (match_parent) in CardView
I can't find any "rule" how the conflict should be set.
I hope someone can help me understanding the logic or facts on how this conflict is set?
I have a problem in my Activity. The ScrollView doesn't scroll down to the bottom.
Here's my XML layout of the ScrollView:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/test"
android:paddingRight="#dimen/layoutsPadding"
android:paddingTop="#dimen/layoutsPadding"
android:paddingLeft="#dimen/layoutsPadding"
android:paddingBottom="#dimen/scrollViewLayoutsPadding">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/tab_introduction_background"
android:orientation="vertical"
android:padding="#dimen/layoutsPadding">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/tab_introduction_title"
android:textSize="#dimen/bigFont"></TextView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="#dimen/gap_titleAndText">
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/tab_introduction_description"
android:textSize="#dimen/smallFont"></TextView>
</LinearLayout>
</ScrollView>
What Can I do?
Since removing LinearLayout's padding worked, but you want it to have padding, why not just surround it with another LinearLayout and let only this outer LinearLayout to have a padding. And remove the inner LinearLayout's padding. This is probably not a very good style, but worth a try.
If you want to avoid this, you can also try removing the padding from the LinearLayout and adding a margin to all it's children.
EDIT: Since you really need that padding, adding an empty view at the bottom will definitely solve your problem, but it's not a good solution either:
<View
android:layout_width="fill_parent"
android:layout_height="30dp" />
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!
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/messageLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/messageSender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"/>
<TextView
android:id="#+id/messageSenderName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/messageSender"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="false"
android:textColor="#color/list_text_color"
android:textSize="16dp"
android:layout_marginTop="5dp" />
<TextView
android:id="#+id/messageContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/messageSender"
android:layout_below="#id/messageSenderName"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="false"
android:textColor="#color/codeFont"
android:textSize="13dp"/>
</RelativeLayout>
In my layout I have problem. When I set marginTop="5dp" it's fine, but when I use marginBottom nothing happens in my layout. Also when I set padding in RelativeLayout it does not work either. What is the problem here? Could you give me any solution?
marginBottom has no effect if you set android:layout_height="wrap_content" for <RelativeLayout>, instead set it as match_parent and check.
It is realy just a bug of the <RelativeLayout>, so you could try to wrap the RelativeLayout inside of a <LinearLayout> and set the margin there.
I am not sure in which revision of android you are experiencing this issue. I looked at RelativeLayout in Android 4.2.2 (https://android.googlesource.com/platform/frameworks/base/+/android-4.2.2_r1.1/core/java/android/widget/RelativeLayout.java) and I believe there is a bug in the onMeasure.
In lines 486 to 488, we have following code:
if (isWrapContentHeight) {
height = Math.max(height, params.mBottom);
}
In my opinion, the above should read:
if (isWrapContentHeight) {
height = Math.max(height, params.mBottom + params.bottomMargin);
}
With android:layout_height="wrap_content", RelativeLayout does not appear take into account the bottomMargin of the last vertically laid out view.
I suggest you try one of the following:
*) Add a dummy view that will be the very last vertically laid out view, and ensure that it has the android:layout_below attribute. Note that the dummy view does not have a bottom margin, it is there so that RelativeLayout considers the bottom margin of views laid out above it. For your case, the dummy view would look like this:
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="#id/messageSender"
/>
*) As others have mentioned, achieve the same effect in other ways, such as Padding.
*) A not-so-trivial solution is bring in RelativeLayout, its platform style definitions and Pool management classes into your project, perform the bug fix I mentioned above and use this anywhere you would normally use RelativeLayout.
*) File a bug with Google
Hope this helps.
Maybe you can set android:paddingBottom="" of <RelativeLayout> to get the same effect.
Make sure the layout_height of your root container is set to match_parent instead of wrap_content.
I had a <View> inside a <RelativeLayout> and the marginBottom on that view did not work. I found out that my chain of layout_below was broken, so therefore it makes sense that the layout did not know from which view the margin should be calculated.
If you chain it properly using layout_below or the other positioning tools, you do not need to worry about wrap_content or match_parent like others are suggesting. 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">
<View
android:id="#+id/separator"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginBottom="11dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/separator">
...
In some case you have lots of attributs or you just missed that you included earlier :
android:layout_margin="xdp"
You can't use it with specific layout margination
It works if you use android:layout_marginBottom with android:layout_alignParentBottom="true".
For example :
android:layout_alignParentBottom="true"
android:layout_marginBottom="50dp">