Android ConstraintLayout: Views not respecting margins - android

I am attempting to create a layout where various pieces of data are separated by a line (View), but the design requires an equal top and bottom spacing from the line. I am trying to use margins to accomplish this, but I am not getting the results I expected. Based on the official documentation, as long as the constraints are set for the margin direction, they should be respected. For some reason the top margin gives us the correct spacing, however the bottom margin does not give any spacing at all. I have created a sample containing only the pertinent layout axml to reproduce, along with a large enough margin to visualize the issue:
<?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="match_parent"
android:padding="20dp">
<TextView android:text="NAME"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name_label"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<TextView android:text="Your Name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name"
app:layout_constraintTop_toBottomOf="#+id/account_name_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<View
android:id="#+id/line1"
app:layout_constraintTop_toBottomOf="#+id/account_name"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#000000"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"
/>
<TextView android:text="JOINED"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined_label"
app:layout_constraintTop_toBottomOf="#+id/line1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<TextView android:text="January 1, 2019"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined"
app:layout_constraintTop_toBottomOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</android.support.constraint.ConstraintLayout>
The above results in the following, visually:
Now, I can add the android:layout_marginTop="100dp" to the first TextView after the line View to "fix" this, however I want to reuse the styles for the line View, without having to worry about remembering to add a top margin to whatever happens to be the first View after the line View. What am I missing?
Update: Here is what the layout SHOULD look like:

You need to connect the bottom of account_joined to the bottom of parent and the bottom of account_joined_label to the top of account_joined. So you can try this one:
<?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:padding="20dp">
<TextView android:text="NAME"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name_label"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView android:text="Your Name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name"
app:layout_constraintTop_toBottomOf="#+id/account_name_label"
app:layout_constraintRight_toRightOf="parent" />
<View
android:id="#+id/line1"
app:layout_constraintTop_toBottomOf="#+id/account_name"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#000000"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"/>
<TextView android:text="JOINED"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined_label"
app:layout_constraintTop_toBottomOf="#+id/line1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#+id/account_joined" />
<TextView android:text="January 1, 2019"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined"
app:layout_constraintTop_toBottomOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Some info before the code:
When you use something like android:layout_marginTop="100dp" you are making your layout to a non-responsive one.
Why: In android, different phones got dofferent screen size and what may look good on 1 device with 100dp margin may not look good on another device.
So if possible try not to use large values as fixed sizes, the next part of the question will explain how to handle this.
Here is where the fun begins:
You can simply use Guidelines to fix your margin problems - it will be responsive to all screen sizes and won't have hardcoded value like 120dp.
All you have to do is to constraint "NAME" to the top constraint and "JOINED" to the bottom constraint like this:
<?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">
<TextView
android:id="#+id/account_name_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="NAME"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/guideline9" />
<TextView
android:id="#+id/account_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Your Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/account_name_label" />
<View
android:id="#+id/line1"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:background="#000000"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/account_name" />
<TextView
android:id="#+id/account_joined_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="JOINED"
app:layout_constraintBottom_toTopOf="#+id/guideline8"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/account_joined"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="January 1, 2019"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<android.support.constraint.Guideline
android:id="#+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.85" />
<android.support.constraint.Guideline
android:id="#+id/guideline9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.15" />
</android.support.constraint.ConstraintLayout>
And it will look like this:
Now don't be scared, your layout looks ok - it's just my lame lame skills in editing photos (check this on your device).
The important thing is that you can change the look of your layout by changing the value of this line in your guidelines:
app:layout_constraintGuide_percent="0.15"
If anything was not understandable feel free to ask.

Related

ConstraintWidth_percent looks different in design tab and in practice

I am trying to use ConstraintWidth_percent in my shop_list_item.xml, which is used inside my shopadapter. The problem I encounter is, that the design tab (how it should look like) and the in-app design (how it looks) are totally different. What am I doing wrong here?
How it should look like
How it looks
Code
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="#+id/mcv_product_item"
android:layout_width="0dp"
android:layout_height="210dp"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="#android:color/white"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.40">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_product_image"
android:layout_width="match_parent"
android:layout_height="110dp"
android:contentDescription="TODO"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:loadImage="#{product.images[0]}"
tools:ignore="ContentDescription, HardcodedText"
tools:src="#drawable/ic_calibrate" />
<ImageView
android:id="#+id/iv_service_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:contentDescription="#null"
android:src="#drawable/ic_service"
app:hideView="#{product.hasService}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/tv_product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:maxLines="2"
android:text="#{product.name}"
android:textAlignment="textStart"
android:textColor="#color/color_text_dark"
android:textSize="#dimen/textDescriptionNormal1"
app:layout_constraintEnd_toEndOf="#+id/iv_product_image"
app:layout_constraintStart_toStartOf="#+id/iv_product_image"
app:layout_constraintTop_toBottomOf="#+id/iv_product_image"
tools:text="TEST TITLE TO ENSURE STUFF" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/tv_product_price"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:text="#{product.price}"
android:textColor="#color/color_text_blue"
android:textSize="#dimen/textHeadlineNormal1"
android:textStyle="italic|bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#+id/tv_product_name"
tools:text="4870.00" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/tv_euro"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/currency"
android:textColor="#color/color_text_blue"
android:textSize="#dimen/textHeadlineNormal1"
android:textStyle="italic|bold"
app:layout_constraintBottom_toBottomOf="#+id/tv_product_price"
app:layout_constraintEnd_toEndOf="#+id/tv_product_name"
app:layout_constraintStart_toEndOf="#+id/tv_product_price"
app:layout_constraintTop_toTopOf="#+id/tv_product_price" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Currently not using -->
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.30"/>
<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.70"/>
</androidx.constraintlayout.widget.ConstraintLayout>
When I change constraintWidth_percent to something really high like 0.8, it works like it should (but looks weird in the design tab).
This is a normal behavior as the design preview of Android Studio can have different screen size than your mobile set or the emulator.. You can change the design preview width/height to have similar width/height like your testing emulator/mobile and you'll notice there is no change.
You can change this form:
This can be very obvious as your CardView apparently takes the 40% of the RecyclerView item width. You can notice this will the green guidelines in below pic.
What you can do is to teak the 40% until you feel comfortable with a certain width that can fits for the cart items.
Last thing you can try the below layout for aligning the item in the middle of the RecyclerView item 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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="#+id/mcv_product_item"
android:layout_width="0dp"
android:layout_height="210dp"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="#android:color/white"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.4">
<!-- Add CardView items -->
</com.google.android.material.card.MaterialCardView>
<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.3" />
</androidx.constraintlayout.widget.ConstraintLayout>

Split a Relative Layout with wrap_content

I got a RelativeLayout like this:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
Inside this Layout, there are some TextView and other stuff, through which the height of the Layout is defined, because it is set to wrap_content like you can see above.
Now I want to have have two Views in the RelativeLayout who share the space(in respect to width) but fill the whole Layout. The purpose behind this is, that I want to have two onClickListener. In other words: I want to kind of split the layout in two Views next to another (horizontally).
I tried to put a LinearLayout inside the RelativeLayout like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<TextView
android:id="#+id/togoTrueTrigger"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="#+id/togoFalseTrigger"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
It takes the whole with of the RelativeLayout and one TextView takes the left 50% and the other one the right 50%. That is exactly what I want. BUT I also want them to take the whole Height.
What I can't do: Set the Height of the LinearLayout to match_parent. This is not possible, because the whole thing is inside another layout and this would adjust the Height in relation to this layout.
EDIT: This is my new approach
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp">
<TextView
android:id="#+id/togoTrue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pickup"
android:textAppearance="#style/itemConfiguration"
app:layout_constraintLeft_toLeftOf="parent"/>
<com.bhargavms.podslider.PodSlider
android:id="#+id/togoSwitch"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
app:numberOfPods="2"
app:selectedPodColor="#color/colorAccent"
app:mainSliderColor="#color/colorPrimary"
app:podColor="#ffffff"
android:layout_centerInParent="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="#+id/togoFalse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Vor Ort"
android:textAppearance="#style/itemConfiguration"
app:layout_constraintRight_toRightOf="parent"/>
<View
android:id="#+id/togoTrueTrigger"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<View
android:id="#+id/togoFalseTrigger"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
Unfortunately this still doesn't work.
EDIT:
Here is a sketch of what I want. The first picture is the layout and the second shows the same layout with a blue and a red view. These Views are the ones I try to create.
So there are three views inside of the main layout and two views with 50% width obove of them. I believe this is Your answer:
<?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">
<TextView
android:id="#+id/togoTrue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pickup"
android:textAppearance="#style/itemConfiguration"
app:layout_constraintLeft_toLeftOf="parent" />
<com.bhargavms.podslider.PodSlider
android:id="#+id/togoSwitch"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:mainSliderColor="#color/colorPrimary"
app:numberOfPods="2"
app:podColor="#ffffff"
app:selectedPodColor="#color/colorAccent" />
<TextView
android:id="#+id/togoFalse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Vor Ort"
android:textAppearance="#style/itemConfiguration"
app:layout_constraintRight_toRightOf="parent" />
<View
android:id="#+id/togoTrueTrigger"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#44ffff00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent=".5" />
<View
android:id="#+id/togoFalseTrigger"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#4400ff00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent=".5" />
</android.support.constraint.ConstraintLayout>
Try taking a look at ConstraintLayout.
Though initially a bit intimidating it does everything all the other layouts can do and much more (including what you just asked by using "match_constraint").
It's part of the Support Library as well, so it's usable in older projects.
If I understood you correctly, you want these two Views for the purpose of setting an OnClickListener on them. This is how I would go about it:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/togoTrue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pickup"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/togoSwitch"
app:layout_constraintTop_toTopOf="parent" />
<com.bhargavms.podslider.PodSlider
android:id="#+id/togoSwitch"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
app:numberOfPods="2"
app:selectedPodColor="#color/colorAccent"
app:mainSliderColor="#color/colorPrimary"
app:podColor="#ffffff"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#id/togoTrue"
app:layout_constraintRight_toLeftOf="#id/togoFalse"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/togoFalse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Vor Ort"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#id/togoSwitch"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/togoTrueTrigger"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/togoFalseTrigger"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/togoFalseTrigger"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#id/togoTrueTrigger"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

Text wrapping in Constraint layout

Trying to make a really simple layout for a settings page using ConstraintLayout.
Simple text views to the left one below the other and a switch to the right to the center.
The layout I have works fine for newer devices, but as soon I switch to a Nexus 4 or older, the switch goes below/disappears from the view.
Here is my layout code,
<android.support.constraint.ConstraintLayout
android:id="#+id/locationLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent">
<TextView
android:id="#+id/locationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="#string/location_title"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="16sp"/>
<TextView
android:id="#+id/locationDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/location_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationTitle"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="#id/locationTitle"
app:layout_constraintRight_toLeftOf="#id/guidelineLocationLayout"
android:textSize="12sp"
/>
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="parent"/>
<View
android:id="#+id/viewLocationLayout"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#d6d6d6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationDescription"/>
<android.support.constraint.Guideline
android:id="#+id/guidelineLocationLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="48dp" />
</android.support.constraint.ConstraintLayout>
And here are how the constraints look like for the Pixel 2XL,
Here is how they look on a smaller device,
I have used 0dp width for the long description and defined left and right constraints, anything else I could do?
You can use barriers instead of guidelines because a Barrier references multiple widgets as input, and creates a virtual guideline based on the most extreme widget on the specified side.
According to the Documentation
Similar to a guideline, a barrier is an invisible line that you can
constrain views to. Except a barrier does not define its own position;
instead, the barrier position moves based on the position of views
contained within it. This is useful when you want to constrain a view
to the a set of views rather than to one specific view.
Hope this helps you. I've used barrier instead of guideline.
<?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:id="#+id/locationLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent">
<TextView
android:id="#+id/locationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Save location to the song"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/locationDescription"
android:layout_width="261dp"
android:layout_height="32dp"
android:text="Your location is only requested when a new song is identified. Location details are never sent to the server"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationTitle" />
<android.support.constraint.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="locationDescription,locationTitle" />
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="41dp"
android:layout_height="26dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/barrier"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/viewLocationLayout"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#d6d6d6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationDescription" />
</android.support.constraint.ConstraintLayout>
You need to change the constraints of the switch like this
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
You are constraining the bottom of the switch to the top of the parent and top of the switch to the bottom of the parent. You have to change it to layout_constraintTop_toTopOf and layout_constraintBottom_toBottomOf

How to make view "wrap_content but not larger than" with ConstraintLayout?

I'm having 3 view in a row: title, version and imageview (working as button):
title should be wrap_content but respecting the following rules
version should be wrap_content, to right of the title and to left of imageview
imageview has fixed size and is at right top corner of the parent
The problem is if title is too large, the version is moved to right and rule "version is to the left of imageview" is not respected:
So i need to limit title width and make version visible and not moved to the right.
Here is XML:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:background="#b3b2b2">
<!-- -->
<TextView
android:id="#+id/LibraryWithVersionItem.title"
android:layout_width="0dp"
android:textStyle="bold"
android:textSize="#dimen/fontSize18"
android:textColor="#color/mySecondaryDarkColor"
android:layout_height="wrap_content"
android:ellipsize="middle"
tools:text="ExampleLibrary 01234567890123456789012345"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
/>
<Spinner
android:id="#+id/LibraryWithVersionItem.versions"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:textSize="#dimen/fontSize16"
android:textColor="#color/mySecondaryDarkColor"
tools:listitem="#layout/library_version"
android:layout_marginTop="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
android:layout_marginRight="#dimen/margin8"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="#+id/LibraryWithVersionItem.title"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.info"
app:layout_constraintHorizontal_bias="0.0"/>
<TextView
android:id="#+id/LibraryWithVersionItem.sentence"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/LibraryWithVersionItem.title"
tools:text="Some library description in one sentence\nbut two lines"
android:layout_marginTop="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
android:layout_marginRight="8dp"
app:layout_constraintHorizontal_bias="0.0"/>
<TextView
android:id="#+id/LibraryWithVersionItem.isInstalled"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/LibraryManager.installed"
android:textColor="#1a7c1a"
android:layout_marginTop="#dimen/margin8"
android:layout_marginBottom="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
android:layout_marginRight="#dimen/margin8"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/LibraryWithVersionItem.sentence"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
app:layout_constraintHorizontal_bias="0.0"/>
<!-- information button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin8"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_info_outline_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<!-- install button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.install"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingTop="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_get_app_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.info"/>
</android.support.constraint.ConstraintLayout>
PS 1. layout_width="0dp" + app:layout_constraintWidth_default="wrap" seems to be exactly what i need ("wrap_content but not breaking the constraints") but it does not work (still larger than required):
<TextView
android:id="#+id/LibraryWithVersionItem.title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ellipsize="middle"
android:textColor="#color/mySecondaryDarkColor"
android:textSize="#dimen/fontSize18"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
tools:text="ExampleLibrary 01234567890123456789012345"
PS 2. Setting min constraint width for the version (app:layout_constraintWidth_min="60dp") does not help too - it's invisible as it's moved too right.
Title and version should be in the chain and app:layout_constraintWidth_default="wrap" used:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:background="#b3b2b2">
<!-- information button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin8"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_info_outline_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<!-- -->
<TextView
android:id="#+id/LibraryWithVersionItem.title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="middle"
android:textColor="#color/mySecondaryDarkColor"
android:textSize="#dimen/fontSize18"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
tools:text="ExampleLibrary 01234567890123456789012345"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.versions"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:paddingBottom="1dp"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0.0"/>
<Spinner
android:id="#+id/LibraryWithVersionItem.versions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/fontSize16"
android:textColor="#color/mySecondaryDarkColor"
tools:listitem="#layout/library_version"
app:layout_constraintRight_toLeftOf="#id/LibraryWithVersionItem.info"
app:layout_constraintLeft_toRightOf="#+id/LibraryWithVersionItem.title"
android:layout_marginRight="0dp"
app:layout_constraintBottom_toBottomOf="#+id/LibraryWithVersionItem.title"
android:layout_marginBottom="0dp"/>
<TextView
android:id="#+id/LibraryWithVersionItem.sentence"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.title"
tools:text="Some library description in one sentence\nbut two lines"
android:layout_marginTop="5dp"
android:layout_marginLeft="#dimen/margin8"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
android:layout_marginRight="8dp"
app:layout_constraintHorizontal_bias="0.0"
android:layout_marginStart="#dimen/margin8"
android:layout_marginEnd="8dp"/>
<TextView
android:id="#+id/LibraryWithVersionItem.isInstalled"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/LibraryManager.installed"
android:textColor="#1a7c1a"
android:layout_marginTop="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
android:layout_marginRight="#dimen/margin8"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.sentence"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
app:layout_constraintHorizontal_bias="0.0"
android:layout_marginStart="#dimen/margin8"
android:layout_marginEnd="#dimen/margin8"/>
<!-- install button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.install"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingTop="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_get_app_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.info"/>
</android.support.constraint.ConstraintLayout>
I've tried to align version to title baseline but if the title is 2 or more lines it's aligned to the first line and it's not desired. So i had to align version to title bottom and hardcode title -3 bottom padding.
However, it looks as desired in Android Studio:
but on hardware device it looks different:
When analyzing in Layout Inspector i can see title width is calculated wrong:
Probably it's side effect of using it in RecyclerView but anyway...
You want to set android:layout_width="0dp".
Using wrap_content, the view will grow infinitely with the content. By using 0dp and setting its constraints, the view will have the maximum size as default, and the content will grow inside it reaches the limit.
Using android:layout_width="wrap_content"
Using android:layout_width="0dp"
From here-on, do your magic. You can set the TextView's android:maxLines="1" and android:ellipsize="end", adding three dots when reaching the maximum size.
Final layout xml
<?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="wrap_content">
<TextView
android:id="#+id/item_a_receber_historico"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="John Dreadpool Lennon Of House Stark Man This Name Is Huge!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/item_a_receber_valor"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="#+id/item_a_receber_valor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="R$420,00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
i achieve this by setting layout_width to wrap_content and maxWidth to a value
In ConstraintLayout you can add one or mre guidelines horizontally or vertically which help to divide the screen in sections.
I ussually add the guidelines using the *_pct atribute which set the position as a percentage of the screen width/height.

Imitate TableLayout with ConstraintLayout

I want to do this layout with ConstraintLayout.
But I failed even to do the 1(green) part of it.
What I do is I add 3 TextViews 1,2 and 3 (pink) connect them to the left of parent and tell them to be one under the other. It works.
Then I need to add views 4 and 5 so they always be on the right of 2 and 3 and its content must be aligned vertically to the left edge just as shown on the picture.
The problem that when I add
app:layout_constraintLeft_toRightOf="2 OR 3"
the text in 4 and 5 is not aligned properly. I get this
When I use Guideline I get this
app:layout_constraintLeft_toRightOf="#id/guideline"
Does anyone know what can help with this?
Edit. P.S. layout of 1st attempt
<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"
android:padding="16dp"
android:id="#+id/constraintLayout"
>
<TextView
android:id="#+id/instrument_name"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="AUDUSD"
app:layout_constraintStart_toStartOf="#+id/constraintLayout"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<TextView
android:id="#+id/trade_action_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="BUYjhkjhkjhvg"
app:layout_constraintStart_toStartOf="#+id/instrument_name"
app:layout_constraintTop_toBottomOf="#id/instrument_name"
tools:layout_editor_absoluteX="16dp"
android:layout_marginTop="1dp"/>
<TextView
android:id="#+id/net_pl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Net p/l"
app:layout_constraintStart_toStartOf="#+id/trade_action_label"
app:layout_constraintTop_toBottomOf="#id/trade_action_label"/>
<TextView
android:id="#+id/record_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="123"
app:layout_constraintTop_toTopOf="#id/trade_action_label"
app:layout_constraintLeft_toRightOf="#id/trade_action_label"
tools:layout_editor_absoluteY="33dp"
/>
<TextView
android:id="#+id/pl_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="12"
app:layout_constraintTop_toTopOf="#id/net_pl"
app:layout_constraintLeft_toRightOf="#id/net_pl"/>
</android.support.constraint.ConstraintLayout>
Edit. (screenshot of how the result should look like)
You can use a Barrier to replicate the behavior of the TableLayout.
<?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="match_parent">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="#string/warehouse"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="#string/hospital"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView1" />
<android.support.constraint.Barrier
android:id="#+id/barrier7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="textView2,textView1" />
<TextView
android:id="#+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="#string/lorem_ipsum"
app:layout_constraintStart_toEndOf="#+id/barrier7"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
More info here: https://constraintlayout.com/basics/barriers.html
I took a closer look at what you are trying to do. I think that you need to look into using weighted chains in your ConstraintLayout. See the documentation here.
Make sure you use a version of ConstraintLayout that implements chains.
Update
Here is an example of what you are trying to do. I have simplified your layout to better show what will work. Notice the cross linking of box1<->box2 and box3<->box4. These links establish the chains.
<?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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="81dp">
<TextView
android:id="#+id/box1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="16dp"
android:text="Text box 1 xxxxxxx"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/box2"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#id/box2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="Text box 2 yyyyyyyyyy"
app:layout_constraintLeft_toRightOf="#id/box1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#id/box1" />
<TextView
android:id="#+id/box3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="Text box 3 zzzz"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/box4"
app:layout_constraintTop_toBottomOf="#id/box1" />
<TextView
android:id="#id/box4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="Text box 4"
app:layout_constraintLeft_toRightOf="#id/box3"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#id/box3" />
</android.support.constraint.ConstraintLayout>
Here is an image of the layout.
Use app:layout_constraintHorizontal_weight to effect how much space each view gets.

Categories

Resources