Android RelativeLayout sync width - android

I have a LinearLayout which contains two other RelativeLayouts (orientation horizontal). I don't know the width of the left RelativeLayout at runtime. Is it possible to sync both layouts? If the left RelativeLayout has the width of 100dp, the right RelativeLayoutshould also be 100dp. Or both should be 50dp.
Can I handle this in the XML file or have I to do it via code and setting the LayoutParams to the same values?

set width of 0dp and weight of 1 in each RelativeLayout
<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="100dp"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" >
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
</RelativeLayout>
</LinearLayout>

If it's a dynamic width - there is no xml way of doing that.
In xml you can only:
set a fixed width for both relative layouts
set a fixed width of linear layout (or match parent) and for relative layouts use width="0dp" and weight=1

If the width of the first layout is unknown, you need to use some tricks like that:
firstRelativeLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
secondRelativeLayout.getLayoutParams().width=firstRelativeLayout.width;
secondRelativeLayout.requestLayout();
}
});

Related

Parent View height is ignored

I have custom LinearLayout, which is parent of my child views. I'm adding child views into this parent View using parent.addView() by inflating child layout. This LinearLayout is wrapped in ScrollView, so I can scroll child views if there is more there. Problem is that LinearLayout height is ignored if I add child views there (it stretched to full screen height for some reason). This behaviour is completely destroying need of ScrollView. Any reason why is it happening? I need some maxHeight parameter for this to work. It should stretch only to max of 200dp.
Layout:
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/resultList"
android:layout_width="match_parent"
android:layout_height="200dp"
android:paddingTop="#dimen/padding_medium"
android:paddingStart="#dimen/padding_medium"
android:paddingEnd="#dimen/padding_medium"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
You can achieve this behaviour by using a root of a ConstraintLayout with a child of a ScrollView with height to wrap_content and a maximum height to 200dp using the property app:layout_constraintHeight_max="200dp" and the ScrollView child will be the LinearLayout with layout_height to wrap_content.
Below is the xml layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ScrollView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_dark"
app:layout_constraintHeight_max="200dp"
app:layout_constraintVertical_bias="0"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:id="#+id/resultList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/padding_medium"
android:paddingStart="#dimen/padding_medium"
android:paddingEnd="#dimen/padding_medium"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
And the result after adding 3 child Views of 50dp height with different colours to LinearLayout with a total height smaller than 200dp will be like below (No Scroll required):
And the result after adding 9 child Views of 50dp height with different colours to LinearLayout with total height greater than 200dp will be like below (Scroll is required) (ScrollView has its max height to 200dp):
It is not clear from your question what the goal of your layout is. It seems to me that ScrollView is making some assumption about the height of its child being unbounded (and it can have only one child.) If you want the LinearLayout to have a specific height, set that height on the ScrollView itself.

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.

Let Linearlayout width be 650dp if parent is over 650dp, otherwise match parent

I'm creating a LinearLayout inside a FrameLayout, the LinearLayout needs to be centered inside FrameLayout, but the width of LinearLayout needs to change as follows:
If parent FrameLayout is over 650dp, then set LinearLayout width to 650dp, this leaves some margin at left and right of linear layout.
If parent FrameLayout is under 650dp, then set Lineralyout width to match parent.
Parent FrameLayout width will change on orientation change, I tried to use OnLayoutChangeListener, OnGlobalLayoutListener, OnAttachStateChangeListenerto detect the width after screen rotates, but none of them works.
Am I on the right track by trying to find the width of parent view?
Or is it possible to use parent view as ConstraintLayout and make the LinearLayout inside comply 650 when possible and expand to parent when width is not enough?
(Note I can't use different values under different layout res folders like sw600 or sw600-land, as the parentview is not necessarily occupying the entire screen, it might just be one of the two columns on the screen)
The appropriate way to handle this is to create another layout file under layout-land and use a 650dp width for that. And for more description on supporting different screens see the official training here.
For any one interested, I solved it with a ConstraintLayout per Eugen's comment. This will make sure the LinearLayout's width matches parent on smaller screens(<650dp) and cap the width to 650dp on bigger screen sizes
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/row_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintWidth_max="650dp"/>
</android.support.constraint.ConstraintLayout>
<LinearLayout
android:layout_width="300dp"
android:layout_height="100dp"
android:background="#f00"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:maxWidth="200dp"
android:minWidth="200dp"
android:background="#00f"
>
</LinearLayout>
</LinearLayout>
Result when parent width = 150dp

How do I achieve the following layout - one fixed height views at the middle and two equal height views in the top and bottom?

How do I achieve the following vertical layout in Android ?
View1
View2
View3
All three views have width that fits the screen.
View2 height is fixed (= 100).
View1 height is equal to view3's height.
Am I able to achieve this with LinearLayout, RelativeLayout, ConstraintLayout?
I'd appreciate if there is a programmatical solution, instead of the XML layout.
Try this using LinearLayout
<?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">
<View
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="#color/colorAccent"/>
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/colorDarkBlue"/>
<View
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"/>
</LinearLayout>
OUTPUT
Not sure this is what you want but you can get screen height.
Subtract View2's height and just set heights of View1 and View3 to half of your result.
You need to use RelativeLayout and sort them as you want.

Fixed proportion of layout on screen

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

Categories

Resources