I tried this answer.
But I get Nested weights are bad for performance. Is there anyway to solve this or should I continue with this warning?
Here is the layout necessary to solve this with ConstraintLayout:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<View
android:id="#+id/one"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#333"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#id/two"
app:layout_constraintBottom_toTopOf="#id/three"/>
<View
android:id="#+id/two"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#444"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="#id/one"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#id/four"/>
<View
android:id="#+id/three"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#555"
app:layout_constraintTop_toBottomOf="#id/one"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#id/four"
app:layout_constraintBottom_toBottomOf="parent"/>
<View
android:id="#+id/four"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#666"
app:layout_constraintTop_toBottomOf="#id/two"
app:layout_constraintStart_toEndOf="#id/three"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
However, that performance warning is safe to ignore. Nested weights are bad for performance, but this will only be noticeable when you have lots of nested weights on many views all being updated frequently (e.g., flinging a RecyclerView where each item uses nested weights).
You can try this bunch of xml code below: (I've tested it no warning...)
Here is the main content xml file, test.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:weightSum="2"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="#layout/test_1"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"/>
<include
layout="#layout/test_2"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"/>
</LinearLayout>
As I used same xml code for the two nested files test_1.xml and test_2.xml; I am sharing the common code below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:weightSum="2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="#color/colorAccent"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="#android:color/holo_purple"/>
</LinearLayout>
And guess what, I found a responsive layout as you want to achieve.
Here is the output:
You can use ConstraintLayout with guidelines. For example, if you want the layout split into 4 equal parts horizontally, you'd use 3 vertical guidelines, one set at 0.25, one set at 0.50 and one set at 0.75. If you want it split vertically, you'd use the same guideline percents but with horizontal guidelines.
You would then position your views with constraints to the guidelines and the parent.
Related
I would like to create this simple layout:
I wrote this:
<?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:background="#color/purple_200">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.3"
android:background="#color/black" />
</LinearLayout>
But doing so I don't see any black view appearing. What am I missing?
There is a new way called ConstraintLayout which is preferred. You can use layout_constraintHeight_percent property of it.
Example
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/purple_200"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Output:
All you have to do is to add
android:weightSum="1"
to your parent's layout, so
<?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"
android:background="#color/purple_200">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.3"
android:background="#color/black" />
</LinearLayout>
I suppose you thought it's 1 by default, but it's not, you have to specify it, otherwise, it's calculated as the sum of the children's weights, so in this case, it was 0.3.
From the android:weightSum's definition:
Defines the maximum weight sum. If unspecified, the sum is computed by
adding the layout_weight of all of the children. This can be used for
instance to give a single child 50% of the total available space by
giving it a layout_weight of 0.5 and setting the weightSum to 1.0.
Other solution is androidx.constraintlayout.widget.Guideline. You can add a guideline to a constraintLayout, and you can change app:layout_constraintGuide_percent variable between 0..1 range. You can change orientation too.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
Consider the following layout:
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
/>
<TextView
android:id="#+id/primary_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#color/white"
android:textSize="24sp"
tools:text="Primary!"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<TextView
android:id="#+id/secondary_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#color/white"
android:textSize="24sp"
tools:text="Secondary!"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
/>
</LinearLayout>
See the screenshot below for the result. The layout works fine, but Android Studio warns me that the FrameLayouts are considered useless and should be removed. However, they're not useless. I use layout_weight here. The idea is that the space between and around the two TextViews are relative with weights 2:1:3.
How can I rewrite my layout that results in the same weighted positioning of the views without having to use empty FrameLayouts?
You can get rid of the first two FrameLayout by setting the height of your TextView to 0dp and their weight to the values you set for your FrameLayout.
FrameLayout is a container that is supposed to have children. For a gap, a View is sufficient. I replaced each empty FrameLayouts with:
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
and the linter warning was gone.
I have two constraint layouts in a linear layout. I want the constraint layouts to occupy 30% and 70% of the screen respectively on all devices. What attribute inside the Linear Layout do I need to set in order to achieve this?
This should give the desired result. Setting a weightSum attribute to the parent linear layout and then accordingly giving the weights helps
<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" >
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.3"/>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.7"/>
</LinearLayout>
You have to take Parent Layout as ConstraintLayout and then after you have to use GuideLine to set 30 and 70 percent of screen.
<?xml version="1.0" encoding="utf-8"?><?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:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.3" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/holo_green_light"
app:layout_constraintBottom_toTopOf="#+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/darker_gray"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline" />
</androidx.constraintlayout.widget.ConstraintLayout>
Output
Use WeightSum attribute on LinearLayout to achieve the Output you are expecting, Which is more easier than other methods.
<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="3" >
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3">
//Child layouts on 30% of layout
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="7">
//Child layouts on 70% of layout
</android.support.constraint.ConstraintLayout>
If you want make something like that use
android:layout_weight="any number"
but you must make the same height for the both of them it doesn't matter if the height wrap_content or match_parent
The layout will occupy more form screen if the number less than the other one
I'm trying to create a layout of a list which starts on the bottom of a button and it's 3/4 of screen's width.
Just like this:
First, I used nested Linear layouts a horizonal and a vertical one, but then I read here that Constraint layouts are more responsive and I was impressed and gave it a try.
So, I tried to replace the outer layout to a constraint layout but now, I can't constraint the list to start at the bottom of the button and it starts at top of the screen.
I tried to see what would happen if I replaced the whole linear layout with a button just to see that the attributes are correctly implemented and it worked, so I understood that the Constraint layout does'nt effect the sons of the Linear layout although it should be effecting the whole layout (as I see it).
my code is the following:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageButton
android:id="#+id/settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FFFFFF"
android:src="#drawable/ic_menu_black_32dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/list_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/settings_button"
app:layout_constraintTop_toBottomOf="#+id/settings_button">
<ListView
android:id="#+id/listview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
My current layout looks like this:
I really appriciate the helpers!
You need to change layout height of linear layout to 0dp, I will put here the layout for you. Also consider migrating to androidx :)
<?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:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FFFFFF"
android:src="#drawable/ic_menu_black_32dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/list_linear_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:weightSum="4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/settings_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/settings_button">
<ListView
android:id="#+id/listview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I think, that using match_parent as width or height of child and adding any constraint is wrong here.
Edited xml (change margins if you want):
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageButton
android:id="#+id/settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:layout_marginTop="24dp"
android:backgroundTint="#FFFFFF"
android:src="#drawable/ic_menu_black_32dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/list_linear_layout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="24dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#+id/settings_button"
app:layout_constraintTop_toBottomOf="#+id/settings_button"
app:layout_constraintWidth_percent="0.75">
<ListView
android:id="#+id/listview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
</LinearLayout>
Using XML with relative layout as root layout , is there way that I can tell the image view to use 80% of screen and center it in the middle.
If I use wrap content or numeric dp then the image might be too small on big screens or too big for small screens. I want it to be 80‰ no matter what the screen looks like?
Please let me know how you would approach this thanks
You use PercentRelativeLayout, import this
dependencies {
...
compile 'com.android.support:percent:23.3.0'
...
}
In XML, you use <android.support.percent.PercentRelativeLayout> instead <RelativeLayout>, it will support below code for those child
app:layout_heightPercent="80%"
app:layout_widthPercent="80%"
With android:layout_width/height, you can use "wrap_content", or without using, no problem.
Well ,you can't do this on XML cause these mathematical operations can't be done there. You can just use MATCH_PARENT in the XML.
And then programmatically get the particular Views MeasuredWidth() and then set the width to be 80% of that.
Much easier and cleaner this way.
You can use PercentRelativeLayout
<android.support.percent.PercentRelativeLayout
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="match_parent">
<ImageView
app:layout_widthPercent="80%"
app:layout_heightPercent="80%"
android:layout_centerInParent="true"/>
</android.support.percent.PercentFrameLayout>
You can create using weight in linear layout like following
<?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"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="8"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="8">
<ImageButton
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</RelativeLayout>