A common use for LinearLayout is to evenly space (weight) views, for example:
How do you implement evenly spaced views like this using the new ConstraintLayout?
ConstraintLayout links for reference: blog post, I/O session video
There are two ways to accomplish this using ConstraintLayout: Chains and Guidelines. To use Chains, make sure you are using ConstraintLayout Beta 3 or newer and if you want to use the visual layout editor in Android Studio, make sure you are using Android Studio 2.3 Beta 1 or newer.
Method 1 - Using Chains
Open the layout editor and add your widgets as normal, adding parent constraints as needed. In this case, I have added two buttons with constraints to the bottom of the parent and side of the parent (left side for Save button and right side for Share button):
Note that in this state, if I flip to landscape view, the views do not fill the parent but are anchored to the corners:
Highlight both views, either by Ctrl/Cmd clicking or by dragging a box around the views:
Then right-click on the views and choose "Center Horizontally":
This sets up a bi-directional connection between the views (which is how a Chain is defined). By default the chain style is "spread", which is applied even when no XML attribute is included. Sticking with this chain style but setting the width of our views to 0dp lets the views fill the available space, spreading evenly across the parent:
This is more noticeable in landscape view:
If you prefer to skip the layout editor, the resulting XML will look like:
<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">
<Button
android:id="#+id/button_save"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/button_save_text"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="4dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="#+id/button_share"
app:layout_constraintHorizontal_chainStyle="spread" />
<Button
android:id="#+id/button_share"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/button_share_text"
android:layout_marginStart="4dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintLeft_toRightOf="#+id/button_save"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>
Details:
setting the width of each item to 0dp or MATCH_CONSTRAINT lets the views fill the parent (optional)
the views must be linked together bidirectionally (right of save button links to share button, left of share button links to save button), this will happen automatically via the layout editor when choosing "Center Horizontally"
the first view in the chain can specify the chain style via layout_constraintHorizontal_chainStyle, see the documentation for various chain styles, if the chain style is omitted, the default is "spread"
the weighting of the chain can be adjusted via layout_constraintHorizontal_weight
this example is for a horizontal chain, there are corresponding attributes for vertical chains
Method 2 - Using a Guideline
Open your layout in the editor and click the guideline button:
Then select "Add Vertical Guideline":
A new guideline will appear, that by default, will likely be anchored to the left in relative values (denoted by left-facing arrow):
Click the left-facing arrow to switch it to a percentage value, then drag the guideline to the 50% mark:
The guideline can now be used as an anchor for other views. In my example, I attached the right of the save button and the left of the share button to the guideline:
If you want the views to fill up the available space then the constraint should be set to "Any Size" (the squiggly lines running horizontally):
(This is the same as setting the layout_width to 0dp).
A guideline can also be created in XML quite easily rather than using the layout editor:
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/guideline"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
To create 2 views in same line, equal width, just need to define
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="#+id/button1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button 1"
app:layout_constraintEnd_toStartOf="#+id/button2"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/button2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button 2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/button1" />
</android.support.constraint.ConstraintLayout>
Note
width = 0dp (MATCH_CONSTRAINT)
Constraint of button1 and button2 must like above
Result
MORE
If you want View1 bigger than View2 you can use weight or percent.
Example, View1 width = 2 *View2 width use weight
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:id="#+id/button3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button 3"
app:layout_constraintEnd_toStartOf="#+id/button4"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toStartOf="parent"
/>
<Button
android:id="#+id/button4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button 4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="#+id/button3"
/>
</android.support.constraint.ConstraintLayout>
Result
Example, View1 width = 2 *View2 width use percent
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:id="#+id/button5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button 5"
app:layout_constraintEnd_toStartOf="#+id/button6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintWidth_percent="0.667"
/>
<Button
android:id="#+id/button6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button 6"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/button5"
app:layout_constraintWidth_percent="0.333"
/>
</android.support.constraint.ConstraintLayout>
Result
Well if it helps someone
the key is here app:layout_constraintHorizontal_weight="1" and
the best thing about constraint layout is that it supports circular dependency and here this is what I have done using exactly that.
For first child
app:layout_constraintEnd_toStartOf="#+id/textInputSecondChild"
For second child
app:layout_constraintLeft_toRightOf="#+id/textInputFirstChild"
here is the complete demo
<android.support.design.widget.TextInputLayout
android:id="#+id/textInputParent"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<EditText
android:id="#+id/editTextParent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/state" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="#+id/textInputFirstChild"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="#+id/textInputSecondChild"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textInputParent">
<EditText
android:id="#+id/editTextChildOne"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/pin_code" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="#+id/textInputSecondChild"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="#+id/textInputFirstChild"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textInputParent">
<EditText
android:id="#+id/editTextChildSecond"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/country" />
</android.support.design.widget.TextInputLayout>
You shoul read about weighted chains. An example of code is here.
<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/figure_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintEnd_toStartOf="#id/figure_2"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
tools:text="1"
/>
<TextView
android:id="#+id/figure_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintEnd_toStartOf="#id/figure_3"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="#id/figure_1"
tools:text="2"
/>
<TextView
android:id="#+id/figure_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintEnd_toStartOf="#id/figure_4"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="#id/figure_2"
tools:text="3"
/>
<TextView
android:id="#+id/figure_4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="#id/figure_3"
tools:text="4"
/>
</android.support.constraint.ConstraintLayout>
So, set android:layout_width="0dp", app:layout_constraintHorizontal_weight="1" and link every view with neighbours like:
app:layout_constraintStart_toEndOf="#id/figure_2"
app:layout_constraintEnd_toStartOf="#id/figure_4"
Once you have your chained items, you can still use weights on them like relative layout to keep them evenly spaced. The example below shows how to keep them evenly spaced with different size textViews.
<TextView1
app:layout_constraintHorizontal_weight="1" />
<TextView2
app:layout_constraintHorizontal_weight="1" />
<TextView3
app:layout_constraintHorizontal_weight="1" />
<TextView4
app:layout_constraintHorizontal_weight="1" />
Related
As you can see in the image below, I'm looking for a way to have 2 views, and I need that when both are visible, view 2 behave as a wrap_parent, but when view 1 is gone, I will like to view 2 to take the remaining of the space.
I know constraint layout can accomplish this; I haven't found a way to do it.
Here is an example of what I'm looking for
Edit 1
Neither of these views is view groups.
Place both views into a horizontal chain that is spread_inside. Set the width of both views to 0dp. For View 2, specify app:layout_constraintWidth_min="wrap". For View 1 set the layout weight (app:layout_constraintHorizontal_weight) to 1.
The following XML is an example:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:background="#android:color/holo_green_light"
android:text="View 1"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/textView2"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="#android:color/holo_blue_light"
android:text="View 2"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/textView1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="wrap" />
</androidx.constraintlayout.widget.ConstraintLayout>
When both views are visible, we see this:
With View 1 gone, we see this:
I have the following XML code , I couldn't make 'summaryViewPager' fill the remaining space vertically, until the bottom of the screen :
<?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">
<com.google.android.material.card.MaterialCardView
android:id="#+id/mainCardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:background="#666266"
android:padding="10dp"
app:cardCornerRadius="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:layout_marginLeft="3dp"
android:layout_marginTop="2dp"
android:text="#string/category"
android:textColor="#FFBA93"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="#+id/cardView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:background="#666266"
android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/mainCardView">
<Button
android:id="#+id/shareButton"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:background="#drawable/ic_share"
app:layout_constraintEnd_toStartOf="#+id/copyButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/seenImageView"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="3dp"
android:layout_marginLeft="3dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:contentDescription="#string/todo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/favoriteButton"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/unseen" />
</com.google.android.material.card.MaterialCardView>
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/summaryViewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/cardView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
The above code doesn't show the PageViewer at all below cardView2 , however when I set android:layout_height="500dp it does show PageViewer, but it doesn't fill the whole screen.
Initial Thoughts
I copy pasted your Layout into Android Studio 4.x, replaced all #string references with "something", and all #drawables with an existing one (from #android:drawable/) so my layout would render.
From what I see, it looks correct:
I noticed some inconsistencies in your Layout.
CardView Number 1 (top)
Careful with Padding on a CardView (don't know your min/max API so, not sure if this applies to you).
Your CardView has no constrain for its BOTTOM, it's left to "whatever size you compute after wrapping" (Height = wrap, Bottom_To = null).
This ^ means that for the CardView to have a height, all its innerwidgets must compute their sizes, so the top card view knows how much size + margin + padding it needs. It doesn't depend on OTHER widgets (that are not children) because its constrains are all to the parent. (rather it only needs its parent).
CardView Number 2 (bottom)
This cardView wraps all its dimensions but has the same issue as the one above, it doesn't constraint its height (except to be pinned at the bottom of the previous one, CardView 1). Again, this is fine, so as long as nobody depends on this (which is not true). This one has to wait on more widgets to know its size, because it has to wait on the CardView1 to know how much space is left, and also needs to know how much its children need. It's not too hard because both (the ImageView and the Button) have fixed sizes (20 and 30 dp respectively) + margins/padding.
The children of a MaterialCardView cannot/should not/must not use constraints because a CardView is not a ConstraintLayout, rather a glorified FrameLayout, which can only hold ONE child (or if it has more, it will put them on on top of the other). So all those constraints (for the shareButton and seenImageView) are ignored.
The solution to the above, is to have an inner ConstraintLayout as the sole child of a CardView, and inside this inner CL, put all your children and their constraints. The inner ConstraintLayout should have its width/height as either wrap_content or match_parent so they use the constraints of the parent. Since htey have fixed sizes, this is not an issue. (and if they didn't it wouldn't be an issue, but would need another measure pass).
Regardless of this, this second CardView is able to calculate its height, because its children are reporting a size of 20+30 (overlapped) + 15 margin top (image) so.. all this combined is likely 45dp~ of height (since they overlap only the biggest numbers apply here).
All the constraints are ignored for these two children.
ViewPager (bottom)
Finally we reach the VPager. This viewPager is match_parent for its width (since you have constraints to the start/end, you should just use 0dp). And it has wrap_content for its height.
layout_height=wrap_content -> this is a problem here. Because the viewPager doesn't (at the time of layout pass/measure) yet know what its contents are going to be. So you probably want this to be 0dp and let the ViewPager use all available space after the above has been calculated.
The marginTop you have here, will not work as it is, because the CardView 1 and 2 have no bottom constrain, so this one would have to create yet another layout/measure pass after it's all said and done to be able to apply a margin (that's how it works).
Ok Enough Rant - what can you do?
I'd "fix" the layout by adding the correct constraints and -if needed- use a VerticalChain and biasing for all widgets.
I'd fix the middle (Cardview 2) contents by wrapping the textview and imageView in a ConstraintLayout.
I'd remove left/right and replace with start/end (unless you target API 16 or below).
I'd set the ViewPager to 0dp on both dimensions.
The children of your CardView2 refer to copyButton and favoriteButton but these don't exist in the Layout you pasted, so I assume you have more buttons there).
Full Version (modified)
And in case you wonder, here's what I did ( I added a color to the VP's background so it was easier to "see").
<?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">
<com.google.android.material.card.MaterialCardView
android:id="#+id/mainCardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintVertical_chainStyle="packed"
android:background="#666266"
android:padding="10dp"
app:cardCornerRadius="20dp"
app:layout_constraintBottom_toTopOf="#id/cardView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:layout_marginTop="2dp"
android:text="Category"
android:textColor="#FFBA93"
android:textSize="20sp"
android:textStyle="bold" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="#+id/cardView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:background="#666266"
android:padding="10dp"
app:layout_constraintBottom_toTopOf="#id/summaryViewPager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/mainCardView">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/innerCardView2Root"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/shareButton"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="5dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="5dp"
android:background="#android:drawable/ic_menu_share"
app:layout_constraintEnd_toStartOf="#+id/seenImageView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/seenImageView"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="3dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="5dp"
android:contentDescription="#null"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/shareButton"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#android:drawable/ic_menu_search" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/summaryViewPager"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="2dp"
android:background="#color/colorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/cardView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
I have 2 views in a layout - TextView and Button. TextView is aligned/anchored to the left side and the button is to the right side.
What I'm trying to achieve is the natural "wrap behavior" of the Button. When TextView will be wide enough so that there won't be space for the button (in the same line), it should move below the TextView, while still anchored to the right.
Here are 3 scenarios for the layout which I want to achieve:
I was trying to make this with FlexBoxLayout, but the button appears on the left side after wrapping.
<com.google.android.flexbox.FlexboxLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexDirection="row"
app:flexWrap="wrap"
app:justifyContent="space_between"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="text text"
android:gravity="start"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Button"
/>
</com.google.android.flexbox.FlexboxLayout>
So how can I do that? It doesn't need to be FlexBox, I can use any layout, even 3rd party.
Use justifyContent="flex_end" in the parent and set layout_flexGrow to the children like this works for me.
<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="300dp"
android:layout_height="wrap_content"
app:flexDirection="row"
app:flexWrap="wrap"
app:justifyContent="flex_end">
<TextView
android:id="#+id/textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="blah blah"
app:layout_flexGrow="1" />
<TextView
android:id="#+id/textview3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="( . )( . )"
app:layout_flexGrow="0" />
</com.google.android.flexbox.FlexboxLayout>
No need for a 3rd party layout.
ConstraintLayout should be more than enough - with a small tweak in code.
Your TextView will have straightforward constraints, set to parent layout (start, top, end).
<?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"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Text text text text text text" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/text" />
</android.support.constraint.ConstraintLayout>
In the code, just check the width of the TextView and compare it with the width of the parent (basically check it should overlap with the button).
If it does change(you will have to do this in code but this is the principle):
app:layout_constraintTop_toTopOf="#+id/text"
to
app:layout_constraintTop_toBottomOf="#+id/text"
If you need to do this dynamically ConstraintLayout has neat feature "Keyframe animations" that creates awesome looking animations when you are changing constraints.
Doesn't seem like there is a way to do it with Flexbox. I would just do it programmatically when you've inflated the resource (in onCreateView() or something like that). The parent of both of the views would be a RelativeLayout, with the Button aligned to the TextView top when the widths combined don't exceed the width of the RelativeLayout, and aligned to the bottom of the TextView when the widths are larger than that.
I have an arbitrary length textview+icon (icon+text) that needs centering on the screen. On the same row, there is a button aligned to the right side of the screen. (X)
| icon+text | X |
Using a LinearLayout I can center it with the view, but the button on the right shifts it left.
With a relative layout, I can achieve what I want but if the text is too long the button overlaps the text.
What's the right way to do this? I haven't used constraintLayout before, would that solve it?
I suggest you to use a constraint layout,
Example:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".YourActivity">
<TextView
android:id="#+id/my_text_view"
android:text="My Long Text That must not overlap the button"
android:layout_width="0dp"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/my_btn"
app:layout_constraintTop_toTopOf="#+id/my_btn"
app:layout_constraintBottom_toBottomOf="#+id/my_btn"/>
<Button
android:id="#+id/my_btn"
android:layout_marginTop="16dp"
android:text="My Nice Button "
android:layout_marginEnd="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#id/my_text_view"
app:layout_constraintEnd_toEndOf="parent"/>
</android.support.constraint.ConstraintLayout>
Example Output:
You can set it like this,
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:drawableLeft="#mipmap/ic_launcher"
android:text="Click" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="TextView" />
</LinearLayout>
just use a Relative Layout.
Center your Textview
and put toRightOf=txtViewsName on the button.
//UPDATED Forcing Widths in DP to ensure text is always centered and never overlaps button.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#mipmap/ic_launcher"
android:maxWidth="230dp"
android:layout_centerHorizontal="true"
android:ellipsize="end"
android:text="My text to show test abcdefghyijkldkf here" />
<Button
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Button" />
</RelativeLayout>
You will need to adjust the button width and textview maxwidth to match your design, and confirm on preview all resolutions, but dp should cover you pretty well in this case.
NOTE*
This simply answers your issue, but does not do any funny behavior, i.e. if text grows too much ignore center command and start moving to the left, this does not do that. If that is your desire, please update your question.
//Centering Text in left view and using weight to ensure text area takes proper percentage of the space (based on your comments, not the layout you are looking for, but I'll leave it in case it helps someone else).
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="10">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="7"
android:drawableLeft="#mipmap/ic_launcher"
android:gravity="center"
android:text="My text to show here" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="Button" />
</LinearLayout>
for best practice i think ConstraintLayout is the best solution for designing and yes of course it helps you for what are you looking for.
for more info check this Build a Responsive UI with ConstraintLayout and this
ConstraintLayout.
Since your ImageButton on right has a fixed width (let's say 40dp for the purpose of this example) you can achieve the desired result by adding a margin of the same width at the end of your TextView to ensure that they're not overlapping. To keep the TextView centered on the screen you have to add the same margin at the start as well:
<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/textview"
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="#+id/button"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constrainedWidth="true"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/textview"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
If you want to center the text within the TextView use android:gravity="center":
If the ImageButton's width was wrap_content then this approach wouldn't work, because there is no way to constraint the end of the TextView both to the end of the parent (so it's centered on the screen) and to the start of the ImageButton (so they don't overlap if the text gets long) at the same time.
In the end I ended up using RelativeLayout per Sam's suggestion with maxWidth and margin set on the TextView.
I have had a couple of my layouts blow up since changing over to ConstraintLayout version 1.1.0-beta4. Before I make any changes, I want to get a better understanding of how margins work in ConstraintLayout chains. In the following, I compare a layout in ConstraintLayout version 1.0.2 to version 1.1.0-beta4, but I believe that the issue first arose in 1.1.0-beta2.
My goal is to have some text views stretch across the screen with gaps between the 1st and 2nd text views and the 2nd and 3rd text views. The background should show in these margins. To do this, I create a horizontal chain and specify an end margin from the left text view to the center text view and an end margin from the center text view to the right text view. The horizontal chain style is spread_inside.
Example 1 - Using ConstraintLayout version 1.0.2
This is how things look in version 1.0.2 and is what I expect.
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#android:color/holo_blue_light">
<TextView
android:id="#+id/tvLeft"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="#android:color/white"
android:gravity="center"
android:text="Text1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/tvCenter"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/tvCenter"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="#android:color/white"
android:gravity="center"
android:text="Text2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/tvRight"
app:layout_constraintStart_toEndOf="#+id/tvLeft"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/tvRight"
android:layout_width="0dp"
android:layout_height="35dp"
android:background="#android:color/white"
android:gravity="center"
android:text="Text3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/tvCenter"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</android.support.constraint.ConstraintLayout>
Example 2 - Using ConstraintLayout version 1.1.0-beta4
This same layout looks like the following in version 1.1.0-beta4 of ConstraintLayout. Notice that the margins have disappeared. I expect that this should look the same as example 1, but it doesn't.
Example 3 - Using ConstraintLayout version 1.1.0-beta4 with start margin
If I take this same layout and simply add a start margin of 8dp to the right text view (tvRight), my margins reappear not only between the center and right text views but also between the left and center textviews although I have not changed the margins there.
This is more than just the previously set margins suddenly being honored. If I set the start margin on the rightmost text view to '48dp', what appears to be a 48dp margin also appears between the left and center text views.
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#android:color/holo_blue_light">
<!-- TextViews tvLeft & tvRight not shown but are the same as above.-->
<TextView
android:id="#+id/tvRight"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="48dp"
android:background="#android:color/white"
android:gravity="center"
android:text="Text3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/tvCenter"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</android.support.constraint.ConstraintLayout>
So, my question is, "Why am I seeing these results?" How are margins handled in ConstraintLayout chains, especially spread_inside chains? Has there been a change in the way chain margins are handled, or am I missing something? I am looking for an explanation or a reference to some documentation that explains all this.
I can find no documentation that gives an authoritative answer to this exact question. However, there is a little bit of discussion about margins in the API documentation for ConstraintLayout:
If side margins are set, they will be applied to the corresponding constraints (if they exist)
In the specific instance of a chain, you have two-way constraints between each view. That is, not only is View A's end constrained to View B's start, but View B's start is also constrained to View A's end.
In your posted layout, View A has an end constraint and an end margin, but View B has a start constraint with no start margin. As far as I can tell, this means you have conflicting rules in your layout (View A wants to be 8dp away from View B, but View B wants to be 0dp from View A). Perhaps different versions of the ConstraintLayout library have different strategies for (a) determining whether this even counts as a conflict and (b) resolving the conflict if so.
Via experimentation, here is how I've found margins to work in chains on different ConstraintLayout library versions:
Version 1.0.2
Side margins on each view in the chain don't depend on or affect other views in the chain. This has (at least) two visible effects on behavior. First, adding margin to one view will push the other view away by that amount, regardless of that view's margins. Second, adding margin to one view will not affect margins of views farther down the chain (e.g. putting 8dp end margin on your first view does not by itself also cause 8dp worth of space to appear between your second and third views).
Version 1.1.0-beta4
Side margins on each view in the chain both depend on and affect other views in the chain. Again, this has two visible effects on behavior. First, adding margin to one view will not push the other view away unless it also has a margin of that same amount*. Second, adding margin between the first and second view of the chain will also affect the spacing between the second and third view of the chain**.
*: It seems that 1.1.0-beta4 allows just a start margin to push the views apart, while just an end margin will have no effect. Regardless, I recommend matching the margins.
**: I suspect this is because the chain is trying to allocate "space" evenly. The margins between views A and B create a gap, and since the chain wants to enforce a consistent spacing it adds a similar gap between views B and C.
Examples:
Stripped way down, here's a layout just like your original, with the margins changed slightly. I've left every other attribute unchanged.
<android.support.constraint.ConstraintLayout>
<TextView
android:layout_marginEnd="8dp"/>
<TextView
android:layout_marginStart="8dp"/>
<TextView/>
</android.support.constraint.ConstraintLayout>
v1.0.2:
v1.1.0-beta4:
This should illustrate the two differences between the library versions. Again, I've been completely unable to find official documentation that explains all this, but it appears to be true just based on experimentation.
Expanding on Ben P.'s answer, I have determined the following regarding margins in ConstraintLayout chains. This information applies to ConstraintLayout version 1.1.0-beta4.
General Observations
Within a chain, all start margins (android:layout_marginStart) are honored. This means that the spacing between the views will not be less than the specified start margin. However, the spacing may be greater as explained below.
End margins (android:layout_marginEnd) have no relevance and seem to be ignored. This does not apply to the end margins of the view at the end of the chain but only to the interior margins where views are cross-linked to create the chain.
When a chain is centered within its constraints, the chain is centered between the start margin of the chain's head and the end margin of the chain's tail.
In the examples below, views "A","D" ang "G" are constrained to the parent start. Views "C", "F" and "I" are constrained to the parent end.
Chain Style: packed
If the chain style is "packed," all views are placed end-to-end separated by the specified start margins. The spacing between the views can vary according to how the start margins are defined. In the following image, the width of the views are match_constraints and the margins are set as indicated.
If the widths of the views are set to something other than match_constraints, the views are still packed with the specified margins but the chain is centered between the start margin of the chain's head and the end margin of the chain's tail.
I came to this interpretation instead of considering the end margin to be attached to the end view because the Android Studio designer has this same interpretation:
Chain Style: spread
In the "spread" chain style, all views are distributed between the start and end constraints such that the space before and after each view is the same and equal to the greatest start margin defined. If the width of each view is match_constraints, then all the views will have the same width by default.
Chain Style: spread_inside
The spread_inside style of chains will take the first view of the chain and anchor it to its start constraint while honoring its start margin. The end view will be anchored to its end constraint while honoring its end margin. Interior views will be distributed with equal spacing between the views like spread chains.
Below is the same layout with various margins set. Views "F" and "I" have a start margin of 8dp set but the gap has expanded to 16dp. View "G", "H" and "I" are all of equal width although they don't appear to be.
The XML for this layout is presented at the end of this post.
Of interest but of no real importance: The different chain types are indistinguishable if the views have a width of match_constraints and all margins are zero.
The information above also applies to vertical chains. Substitute android:layout_marginTop for android:layout_marginStart and android:layout_marginBottom for android:layout_marginEnd.
Layout
<android.support.constraint.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_blue_light">
<TextView
android:id="#+id/heading1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="packed, match_constraints"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/textA"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginTop="8dp"
android:background="#android:color/white"
android:gravity="center"
android:text="A"
android:textColor="#android:color/black"
app:layout_constraintEnd_toStartOf="#+id/textB"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/heading1"
tools:ignore="HardcodedText" />
<View
android:layout_width="8dp"
android:layout_height="35dp"
android:background="#ff00cc"
app:layout_constraintEnd_toStartOf="#id/textB"
app:layout_constraintTop_toTopOf="#id/textB" />
<TextView
android:id="#+id/textB"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="8dp"
android:background="#android:color/darker_gray"
android:gravity="center"
android:text="B"
android:textColor="#android:color/white"
app:layout_constraintEnd_toStartOf="#+id/textC"
app:layout_constraintStart_toEndOf="#+id/textA"
app:layout_constraintTop_toTopOf="#+id/textA"
tools:ignore="HardcodedText" />
<View
android:id="#+id/view16dpOnC"
android:layout_width="16dp"
android:layout_height="35dp"
android:background="#fffb00"
app:layout_constraintEnd_toStartOf="#id/textC"
app:layout_constraintTop_toTopOf="#+id/textC" />
<TextView
android:id="#+id/textC"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="16dp"
android:background="#android:color/white"
android:gravity="center"
android:text="C"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/textB"
app:layout_constraintTop_toTopOf="#+id/textA"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/heading2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="spread, match_constraints"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/textA"
tools:ignore="HardcodedText" />
<View
android:layout_width="16dp"
android:layout_height="35dp"
android:background="#00ff19"
app:layout_constraintEnd_toStartOf="#id/textD"
app:layout_constraintTop_toTopOf="#id/textD" />
<TextView
android:id="#+id/textD"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginTop="8dp"
android:background="#android:color/white"
android:gravity="center"
android:text="D"
android:textColor="#android:color/black"
app:layout_constraintEnd_toStartOf="#+id/textE"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/heading2"
tools:ignore="HardcodedText" />
<View
android:layout_width="16dp"
android:layout_height="35dp"
android:background="#fffb00"
app:layout_constraintEnd_toStartOf="#id/textE"
app:layout_constraintTop_toTopOf="#id/textE" />
<TextView
android:id="#+id/textE"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="16dp"
android:background="#android:color/darker_gray"
android:gravity="center"
android:text="E"
android:textColor="#android:color/white"
app:layout_constraintEnd_toStartOf="#+id/textF"
app:layout_constraintStart_toEndOf="#+id/textD"
app:layout_constraintTop_toTopOf="#+id/textD"
tools:ignore="HardcodedText" />
<View
android:layout_width="8dp"
android:layout_height="35dp"
android:background="#003cff"
app:layout_constraintStart_toEndOf="#id/textE"
app:layout_constraintTop_toTopOf="#+id/textE" />
<View
android:layout_width="8dp"
android:layout_height="35dp"
android:background="#ff00cc"
app:layout_constraintEnd_toStartOf="#id/textF"
app:layout_constraintTop_toTopOf="#id/textF" />
<TextView
android:id="#+id/textF"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="8dp"
android:background="#android:color/white"
android:gravity="center"
android:text="F"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/textE"
app:layout_constraintTop_toTopOf="#+id/textD"
tools:ignore="HardcodedText" />
<View
android:layout_width="16dp"
android:layout_height="35dp"
android:background="#00ff19"
app:layout_constraintStart_toEndOf="#id/textF"
app:layout_constraintTop_toTopOf="#id/textF" />
<TextView
android:id="#+id/heading3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="spread_inside, match_constraints"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/textD"
tools:ignore="HardcodedText" />
<View
android:layout_width="8dp"
android:layout_height="35dp"
android:background="#003cff"
app:layout_constraintEnd_toStartOf="#id/textG"
app:layout_constraintTop_toTopOf="#+id/textG" />
<TextView
android:id="#+id/textG"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:background="#android:color/white"
android:gravity="center"
android:text="G"
android:textColor="#android:color/black"
app:layout_constraintEnd_toStartOf="#+id/textH"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/heading3"
tools:ignore="HardcodedText" />
<View
android:layout_width="16dp"
android:layout_height="35dp"
android:background="#fffb00"
app:layout_constraintEnd_toStartOf="#id/textH"
app:layout_constraintTop_toTopOf="#id/textH" />
<TextView
android:id="#+id/textH"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="16dp"
android:background="#android:color/darker_gray"
android:gravity="center"
android:text="H"
android:textColor="#android:color/white"
app:layout_constraintEnd_toStartOf="#+id/textI"
app:layout_constraintStart_toEndOf="#+id/textG"
app:layout_constraintTop_toTopOf="#+id/textG"
tools:ignore="HardcodedText" />
<View
android:layout_width="8dp"
android:layout_height="35dp"
android:background="#003cff"
app:layout_constraintStart_toEndOf="#id/textH"
app:layout_constraintTop_toTopOf="#id/textH" />
<View
android:layout_width="8dp"
android:layout_height="35dp"
android:background="#ff00cc"
app:layout_constraintEnd_toStartOf="#id/textI"
app:layout_constraintTop_toTopOf="#id/textI" />
<TextView
android:id="#+id/textI"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="8dp"
android:background="#android:color/white"
android:gravity="center"
android:text="I"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/textH"
app:layout_constraintTop_toTopOf="#+id/textG"
tools:ignore="HardcodedText" />
<View
android:layout_width="8dp"
android:layout_height="35dp"
android:background="#ff00cc"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="#id/textC"
app:layout_constraintTop_toTopOf="#id/textC" />
<View
android:id="#+id/view8dp"
android:layout_width="8dp"
android:layout_height="35dp"
android:layout_marginStart="24dp"
android:background="#ff00cc"
app:layout_constraintBottom_toTopOf="#id/view8dpGap"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textG"
app:layout_constraintVertical_bias="0.100000024"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="#+id/text8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="8dp start margin"
app:layout_constraintBottom_toBottomOf="#+id/view8dp"
app:layout_constraintStart_toEndOf="#id/view8dp"
app:layout_constraintTop_toTopOf="#+id/view8dp"
tools:ignore="HardcodedText" />
<View
android:id="#+id/view8dpGap"
android:layout_width="8dp"
android:layout_height="35dp"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:background="#003cff"
app:layout_constraintBottom_toTopOf="#+id/view16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view8dp" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="8dp gap not defined by start margin"
app:layout_constraintBottom_toBottomOf="#+id/view8dpGap"
app:layout_constraintStart_toEndOf="#+id/view8dpGap"
app:layout_constraintTop_toTopOf="#+id/view8dpGap"
tools:ignore="HardcodedText" />
<View
android:id="#+id/view16dp"
android:layout_width="17dp"
android:layout_height="35dp"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:background="#fffb00"
app:layout_constraintBottom_toTopOf="#+id/view16dpGap"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view8dpGap" />
<TextView
android:id="#+id/text16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="16dp start margin"
app:layout_constraintBottom_toBottomOf="#+id/view16dp"
app:layout_constraintStart_toEndOf="#+id/view16dp"
app:layout_constraintTop_toTopOf="#+id/view16dp"
tools:ignore="HardcodedText" />
<View
android:id="#+id/view16dpGap"
android:layout_width="17dp"
android:layout_height="35dp"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:background="#00ff19"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view16dp" />
<TextView
android:id="#+id/text16dpGap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="16dp gap not defined by start margin"
app:layout_constraintBottom_toBottomOf="#+id/view16dpGap"
app:layout_constraintStart_toEndOf="#+id/view16dpGap"
app:layout_constraintTop_toTopOf="#+id/view16dpGap"
tools:ignore="HardcodedText" />
</android.support.constraint.ConstraintLayout>