How to Make Constraintlayout Work with Percentage Values

How to make ConstraintLayout work with percentage values?

You can currently do this in a couple of ways.

One is to create guidelines (right-click the design area, then click add vertical/horizontal guideline). You can then click the guideline's "header" to change the positioning to be percentage based. Finally, you can constrain views to guidelines.

Another way is to position a view using bias (percentage) and to then anchor other views to that view.

That said, we have been thinking about how to offer percentage based dimensions. I can't make any promise but it's something we would like to add.

ConstraintLayout: percentage based dimensions

If you want the button to take all the horizontal space between two guidelines, then make its width be 0dp and constraint button's left and right edges to appropriate guidelines.

<Button
android:layout_width="0dp"
app:layout_constraintStart_toEndOf="@id/guideline3"
app:layout_constraintEnd_toStartOf="@id/guideline4"
... />

You'll get this output for portrait:

And this for landscape:

For addressing the vertical space, make the height 0dp and constraint button's top and bottom edges to appropriate guidelines.

<?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="com.satizh.android.constraintlayouttest.MainActivity">

<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"

android:layout_marginTop="0dp"
android:layout_weight="68"
android:text="5%V30%H"
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
app:layout_constraintRight_toLeftOf="@+id/guideline4"
app:layout_constraintTop_toTopOf="@+id/guideline2" />

<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:text="box"
app:layout_constraintBottom_toTopOf="@+id/guideline8"
app:layout_constraintLeft_toLeftOf="@+id/guideline5"
app:layout_constraintRight_toLeftOf="@+id/guideline6"
app:layout_constraintTop_toTopOf="@+id/guideline7"
app:layout_constraintHorizontal_bias="0.0" />

<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.17" />

<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline2"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.05" />

<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline3"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.2" />

<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline4"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.53" />

<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline5"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.6510417" />

<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline6"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8802083" />

<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline7"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.2994129" />

<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline8"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.42" />

</android.support.constraint.ConstraintLayout>

Corresponding output:

Sample Image

Set percentage value with constraint layout

give an id to the guidelines, and set the constraints Start -> StartOf @id/guidelines1
hope i've answered your question.

percentage margin with constraintlayout?

There're two ways to add percentage margin using ConstraintLayout.

#1 Guideline

Simply add vertical guideline to your layout and constraint view to that guideline:

<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="match_parent">

<View
android:id="@+id/view"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="@color/colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.9" />

</android.support.constraint.ConstraintLayout>

#2 Constraint weight

Add Space, place it on the very left side of parent, group your view and Space into "spread" chain and set app:layout_constraintHorizontal_weight="90" to your view and app:layout_constraintHorizontal_weight="10" to Space. It works very similar to LinearLayout's weight.

<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="match_parent">

<View
android:id="@+id/view"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="@color/colorAccent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintHorizontal_weight="90"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/space"
app:layout_constraintBottom_toBottomOf="parent" />

<Space
android:id="@+id/space"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_weight="10"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />

</android.support.constraint.ConstraintLayout>

As a result, your view has end margin with value of 10% of parent width:

Result view

How to give percentage weight in constraint layout android

If the views that you have defined have a defined height (either wrap_content or a specified height) then the question is how to distribute the left-over space. If I read your question correctly, you want 40% of the left-over space to be at the top, 20% in the middle and 40% at the bottom for a total of 100% of the space and 100% of the space is the height of the ConstraintLayout less the combined heights of the widgets.

You can use weights in a ConstraintLayout chains to distribute weights, but the weights will be assigned to Space widgets as follows. All the views must be part of a vertical chain constrained to the top and bottom of the ConstraintLayout.

<androidx.constraintlayout.widget.ConstraintLayout 
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Space
android:id="@+id/space40.1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/view1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_weight="40" />

<View
android:id="@+id/view1"
android:layout_width="100dp"
android:layout_height="125dp"
android:background="@android:color/holo_blue_bright"
app:layout_constraintBottom_toTopOf="@+id/space20"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/space40.1" />

<Space
android:id="@+id/space20"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/view2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view1"
app:layout_constraintVertical_weight="20" />

<View
android:id="@+id/view2"
android:layout_width="300dp"
android:layout_height="50dp"
android:background="@android:color/holo_blue_bright"
app:layout_constraintBottom_toTopOf="@+id/view3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/space20" />

<View
android:id="@+id/view3"
android:layout_width="300dp"
android:layout_height="50dp"
android:layout_marginTop="16dp"
android:background="@android:color/holo_blue_bright"
app:layout_constraintBottom_toTopOf="@+id/view4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view2" />

<View
android:id="@+id/view4"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_marginTop="32dp"
android:background="@android:color/holo_blue_bright"
app:layout_constraintBottom_toTopOf="@+id/space40.2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view3" />

<Space
android:id="@+id/space40.2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view4"
app:layout_constraintVertical_weight="40" />
</androidx.constraintlayout.widget.ConstraintLayout>

The layout displays as follows:

Sample Image

How to set a layout width percentage of one third on ConstraintLayout?

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android" >
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="3"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="2"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="3"/>
</LinearLayout>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="3"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="4"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="5"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="6"/>
</LinearLayout>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="3"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="7"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="8"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="9"/>
</LinearLayout>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="3"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="10"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="11"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="12"/>
</LinearLayout>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="3"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="13"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="14"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="15"/>
</LinearLayout>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="3"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="16"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="17"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="18"/>
</LinearLayout>
</LinearLayout>

ConstraintLayout max width percentage

I achieved the max width percentage using two attributes:

app:layout_constraintWidth_max="wrap"
app:layout_constraintWidth_percent="0.4"

Example:

<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Helo world"
android:textAlignment="viewStart"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="wrap"
app:layout_constraintWidth_percent="0.4" />

The text width will increase to 40% of parent and then wrap if the content exceeds that.

How to set minimum percentage width of View in a ConstraintLayout

There is no straightforward way to do what you want that I know of with any standard XML code and the standard ConstraintLayout attributes. You might be able to do something with a nested layout, but, in general, that should be avoided with ConstraintLayout. I think that the way you devised is probably going to be the way to go.

However, if you want to do this all in XML, you could create a shadow button that is a replica of the primary button in all aspects (position, style, text, etc.) except that it is invisible. A barrier can then ride to the left of the shadow button and the center guideline. The visible primary button can now be constrained to the barrier since the barrier is not dependent upon the primary button. The primary button will at least be 1/2 the width of the ConstraintLayout but can expand beyond.

A second approach would be to create a custom view for the primary button. This custom view can implement an attribute that specifies a minimum width for the button based on the width of the ConstraintLayout.

ButtonMinWidthOfParent.kt

class ButtonMinWidthOfParent @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : MaterialButton(context, attrs) {

private var minWidthOfParent = 0f

init {
context.theme.obtainStyledAttributes(
attrs,
R.styleable.ButtonMinWidthOfParent,
0, 0
).apply {
try {
minWidthOfParent = getFloat(R.styleable.ButtonMinWidthOfParent_minWidthOfParent, 0f)
} finally {
recycle()
}
}
}

@Override
override fun getSuggestedMinimumWidth(): Int {
return maxOf(
super.getSuggestedMinimumWidth(),
((parent as ViewGroup).measuredWidth * minWidthOfParent).toInt()
)
}
}

attrs.xml

<resources>
<declare-styleable name="ButtonMinWidthOfParent">
<attr name="minWidthOfParent" format="float"/>
</declare-styleable>
</resources>

activity_main

<androidx.constraintlayout.widget.ConstraintLayout 
android:layout_width="match_parent"
android:layout_height="match_parent">

<View
android:id="@+id/detail"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/secondaryButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Secondary Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/primaryButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/detail" />

<com.example.secondarybutton.ButtonMinWidthOfParent
android:id="@+id/primaryButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Primary Button that is a little bit longer"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/detail"
app:minWidthOfParent="0.5" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/middleGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />

<View
android:id="@+id/view"
android:layout_width="2dp"
android:layout_height="0dp"
android:background="@android:color/holo_red_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Sample Image

Sample Image

There are undoubtedly other ways, but the XML way has the advantage of being a pure XML implementation with a little trickery while the custom view is a more standard way to extend view capabilities.



Related Topics



Leave a reply



Submit