I am trying to learn constraint layout by converting a list item from a linear + relative layout. I have a checkbox and 3 text views arranged in a line followed by a recyclerview underneath.
Phone preview:
Tablet preview:
Code:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBaseline_toBaselineOf="#+id/line_item_qty"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/line_item_qty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="8dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="#+id/line_item_name"
app:layout_constraintStart_toEndOf="#+id/checkBox"
tools:text="5 x" />
<TextView
android:id="#+id/line_item_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceBody2"
app:layout_constraintEnd_toStartOf="#+id/line_item_price"
app:layout_constraintStart_toEndOf="#+id/line_item_qty"
app:layout_constraintTop_toTopOf="parent"
tools:text="Club sandwich with ranch dressing and extra mustard" />
<TextView
android:id="#+id/line_item_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceBody1"
app:layout_constraintBaseline_toBaselineOf="#+id/line_item_name"
app:layout_constraintEnd_toEndOf="parent"
tools:text="€4.50" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/item_mods_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/line_item_name"
tools:itemCount="3"
tools:listitem="#layout/item_line_modifier"
tools:orientation="vertical" />
</androidx.constraintlayout.widget.ConstraintLayout>
As you can see the preview renders fine but when I run the code, the name of the item is gone (it's width needs to be 0dp, if it's wrap_content then on phones it just previews as one line of text and overlaps the qty and price text views).
Image from device (tablet):
Is it because I am aligning baselines to the name and the name itself has no bottom constraint?
Add app:layout_constraintStart_toEndOf="line_item_name" to your line_item_price, so your price will be always come after your item name
<TextView
android:id="#+id/line_item_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceBody1"
app:layout_constraintBaseline_toBaselineOf="#+id/line_item_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="line_item_name" //Add this
tools:text="€4.50" />
It's good that you are learning new things and trying to implement them.
Below is the code that will give you your desired output.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/line_item_qty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="8dp"
app:layout_constraintTop_toTopOf="#+id/checkBox"
app:layout_constraintBottom_toBottomOf="#+id/checkBox"
app:layout_constraintStart_toEndOf="#+id/checkBox"
android:textAppearance="?attr/textAppearanceBody2"
android:textStyle="bold"
tools:text="5 x" />
<TextView
android:id="#+id/line_item_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceBody2"
app:layout_constraintEnd_toStartOf="#+id/line_item_price"
app:layout_constraintStart_toEndOf="#+id/line_item_qty"
app:layout_constraintTop_toTopOf="#+id/line_item_qty"
app:layout_constraintBottom_toBottomOf="#+id/line_item_qty"
tools:text="Club sandwich with ranch dressing and extra mustard" />
<TextView
android:id="#+id/line_item_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceBody1"
app:layout_constraintTop_toTopOf="#+id/line_item_name"
app:layout_constraintBottom_toBottomOf="#+id/line_item_name"
app:layout_constraintEnd_toEndOf="parent"
tools:text="€4.50" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/item_mods_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/checkBox"
tools:itemCount="3"
tools:listitem="#layout/item_line_modifier"
tools:orientation="vertical" />
</androidx.constraintlayout.widget.ConstraintLayout>
Do let me know if you have any queries on this.
Output :
Related
I am trying to use constraint flow. I need to arrange the TextView one after another on the screen.
Here is my code:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[AAAAAAAA]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[BBBBBBBB]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[CCCCCCCC]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[DDDDDDDD]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[EEEEEEEE]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF]"
tools:ignore="MissingConstraints" />
<androidx.constraintlayout.helper.widget.Flow
android:id="#+id/flow1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="10dp"
app:constraint_referenced_ids="text1,text2,text3,text4,text5,text6"
app:flow_horizontalBias="0"
app:flow_horizontalGap="10dp"
app:flow_horizontalStyle="packed"
android:layout_marginEnd="20dp"
app:flow_verticalBias="0"
app:flow_wrapMode="chain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginEnd="20dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
Everything works well except for the last TextView. Since the text is very long, some of the text goes off the screen (See the picture below). I am trying to set margin, but it doesn't work.
I added TextView in xml for clarity. I need to add them dynamically at runtime, so I can't set the width of my TextView to match_parent, because I don't know if the content will fit within the screen.
Please help me. I need a margin on the right, regardless of the length of the text in the TextView.
Note: TextViews can also be added dynamically. I need add TextView at runtime. Therefore, I cannot set the width of the TextView to match_parent in runtime, because I don’t know if the text can fit within the width of the screen or not.
Here is my code to add View programatically:
private fun addViews() {
val list = generateChipButtons()
list.forEach { button ->
val view = LayoutInflater.from(baseContext).inflate(R.layout.chip_view, constraintContainer, false).apply {
id = View.generateViewId()
this.findViewById<TextView>(R.id.tvChipText).text = button.text
}
constraintContainer.addView(view)
flowView.addView(view)
}
}
Set 0dp at width and add a contrast to set the size ratio for width. The code above is shown with wrap_content, with the width exceeding the text size.
<TextView
android:id="#+id/text6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="[FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF]"
tools:ignore="MissingConstraints"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
Use match_parent for TextView text6. Try below code
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[AAAAAAAA]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[BBBBBBBB]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[CCCCCCCC]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[DDDDDDDD]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[EEEEEEEE]"
tools:ignore="MissingConstraints" />
<TextView
android:id="#+id/text6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="[FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF]"
tools:ignore="MissingConstraints" />
<androidx.constraintlayout.helper.widget.Flow
android:id="#+id/flow1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="10dp"
app:constraint_referenced_ids="text1,text2,text3,text4,text5,text6"
app:flow_horizontalBias="0"
app:flow_horizontalGap="10dp"
app:flow_horizontalStyle="packed"
app:flow_verticalBias="0"
app:flow_wrapMode="chain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginEnd="20dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
Just set the width match_parent of textView #+id/text6
<TextView
android:id="#+id/text6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="[FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFaslkfjadflskjflasdkjfsdlajkfasdlfjkasdlfjkaslkdfjasdflkjasdfasdlfjksdafFFFFsdflkfdaslkfjsdafkljsdlafkjdasfljk]"
tools:ignore="MissingConstraints" />
i Have similar issue i just set to match parent and margin working fine code snippet
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="#dimen/_20sdp"
android:layout_marginBottom="#dimen/_22sdp"
android:fontFamily="#font/font_muli"
android:text="#string/welcome_msg"
android:textColor="#color/white"
android:textSize="#dimen/_11sdp"
app:layout_constraintBottom_toTopOf="#+id/btn_login"
app:layout_constraintEnd_toEndOf="#+id/btn_login"
app:layout_constraintStart_toStartOf="#+id/btn_login" />
Where btn_login is MaterialButton.
Im curently working on an app which has localization. One of the strings is fairly long, and when testing the app on both AVD and physical device, the text gets cut off when reaching the end of the screen.
How do you break the text, making it go on a new line, when the text reaches the display maximum width?
Code:
item_settings.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/rvCard"
android:layout_width="40dp"
android:layout_height="40dp"
android:elevation="0dp"
android:layout_margin="15dp"
app:cardBackgroundColor="#121212"
app:cardCornerRadius="90dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/rvIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="#drawable/ic_colored_settings"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="#+id/rvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:text="Title"
android:textColor="#android:color/white"
android:textSize="15sp"
app:layout_constraintBottom_toTopOf="#id/rvDescription"
app:layout_constraintStart_toEndOf="#+id/rvCard"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/rvDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:text="Description"
android:textColor="#color/colorUnselected"
android:textSize="15sp"
android:singleLine="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/rvCard"
app:layout_constraintTop_toBottomOf="#+id/rvTitle" />
</androidx.constraintlayout.widget.ConstraintLayout>
Since you are using TextView try this:
android:singleLine="false"
android:maxLines="xxx" //replace xxx with the max number of lines you want to have dynamically.
And change your TextView width to 0dp and do app:layout_constraintStart_toEndOf="parent"
your final code would look like
<TextView
android:id="#+id/rvDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:text="Description"
android:textColor="#color/colorUnselected"
android:textSize="15sp"
android:singleLine="false"
android:maxLines="xxx"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/rvTitle" />
Hope it helps!
I'm trying to implememnt the following layout in Android using ConstraintLayout.
However, the two username TextViews need to expand until they reach the max width, which depends on each phone's screen.
The first username should be visible, as much as possible, it should have an 8dp margin and then the "reply arrow" which has a fixed width, and then, if it fits, as much of the "reply to username" TextView should be visible.
The dot separator, date and likes TexViews should awlays be visible, at wrap_content.
In iOS we have managed to implement such a layout by using content hugging and content compression resistance priorities. Are there similar features in Android?
Here's my XML layout for reference:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/newspaperLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="#+id/commentDepthView"
android:layout_width="2dp"
android:layout_height="0dp"
android:layout_marginStart="#dimen/default_margin"
android:background="#color/blueDark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/commentAuthorTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/default_margin"
android:layout_marginTop="#dimen/default_margin"
android:ellipsize="end"
android:lines="1"
android:textColor="#color/blue"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="#id/commentTextView"
app:layout_constraintEnd_toStartOf="#id/replyToArrowImageView"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="#+id/commentDepthView"
app:layout_constraintTop_toTopOf="parent"
tools:text="Username"/>
<ImageView
android:id="#+id/replyToArrowImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/default_margin"
android:layout_marginEnd="8dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#id/commentAuthorTextView"
app:layout_constraintEnd_toStartOf="#id/commentReplyToTextView"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/commentAuthorTextView"
app:layout_constraintTop_toTopOf="#id/commentAuthorTextView"
app:srcCompat="#drawable/reply_to_arrow"/>
<TextView
android:id="#+id/commentReplyToTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/default_margin"
android:ellipsize="end"
android:lines="1"
android:textColor="#color/blue"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/commentAuthorTextView"
app:layout_constraintEnd_toStartOf="#+id/dotSeparatorTextView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="#id/replyToArrowImageView"
app:layout_constraintTop_toTopOf="#id/commentAuthorTextView"
tools:text="Reply To Username"
/>
<TextView
android:id="#+id/dotSeparatorTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/default_margin"
android:layout_marginEnd="8dp"
android:text="#string/dot_separator"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#id/commentAuthorTextView"
app:layout_constraintEnd_toStartOf="#+id/commentDateTextView"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/commentReplyToTextView"
app:layout_constraintTop_toTopOf="#id/commentAuthorTextView"/>
<TextView
android:id="#+id/commentDateTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/default_margin"
android:layout_marginEnd="#dimen/default_margin"
app:layout_constraintBottom_toBottomOf="#+id/commentAuthorTextView"
app:layout_constraintEnd_toStartOf="#id/commentLikesTextView"
app:layout_constraintStart_toEndOf="#id/dotSeparatorTextView"
app:layout_constraintTop_toTopOf="#+id/commentAuthorTextView"
tools:text="1/1/1970"/>
<TextView
android:id="#+id/commentLikesTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/default_margin"
android:layout_marginEnd="#dimen/default_margin"
app:layout_constraintBottom_toBottomOf="#+id/commentAuthorTextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/commentDateTextView"
app:layout_constraintTop_toTopOf="#+id/commentAuthorTextView"
tools:text="0 Likes"/>
<TextView
android:id="#+id/commentTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/default_margin"
android:layout_marginTop="#dimen/default_margin"
android:layout_marginEnd="#dimen/default_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/commentDepthView"
app:layout_constraintTop_toBottomOf="#+id/commentAuthorTextView"
tools:text="This is test comment that is really relly long. Well not that long, but it's long enough, don't you think?"/>
<View
android:id="#+id/separatorView"
android:layout_width="0dp"
android:layout_height="0.5dp"
android:layout_marginStart="#dimen/default_margin"
android:layout_marginTop="#dimen/default_margin"
android:layout_marginEnd="#dimen/default_margin"
android:background="#color/grey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/commentDepthView"
app:layout_constraintTop_toBottomOf="#+id/commentTextView"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Any suggestion is welcome, even using a different layout than ConstraintLayout. Thank you very much.
Give first username
android:layout_width="0dp"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_default="wrap"
and to second
android:layout_width="0dp"
rest is wrap_content and chain them
I am attempting to set up what I thought should be a simple layout with a ConstraintLayout I have a series of text entries, with labels whose size can change from language to language. There is a barrier to the right side of the labels so the text entries stay aligned even when the label lengths change.
I want the text entries to be a nominal size (200dp for the top one and 150dp for the others in this example) but to be able to shrink as needed to fit the screen if the labels are long and the screen is small. In landscape mode, or on a larger screen, the entries should be their max size and aligned left against the barrier.
After a lot of trial and error, I got the layout below to work, by setting two of the chains to "spread_inside" and the last one to "packed". Setting them all to spread_inside messes up the layout (entry_2 shrinks to its minimum size).
This smells like something that will stop working this way in a future ConstraintLayout update (this is using com.android.support.constraint:constraint-layout:1.1.0-beta5). The behavior of this layout is different using beta4 (also wrong, but differently wrong, beta4 aligns them all on the right side of the screen).
Am I missing something here? Does anyone else have similar chain patterns that have worked? Is there a better way of doing 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"
android:padding="16dp"
tools:context="com.mypackage.testapp.MainActivity">
<TextView
android:text="Label 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/entry_1"
app:layout_constraintBottom_toBottomOf="#+id/entry_1"
android:id="#+id/label_1" />
<EditText
android:id="#+id/entry_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:inputType="text"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintHorizontal_weight="100.0"
app:layout_constraintLeft_toRightOf="#+id/guideline"
app:layout_constraintRight_toLeftOf="#+id/space_1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="200sp"
app:layout_constraintWidth_min="100sp" />
<Space
android:id="#+id/space_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="#+id/entry_1"
app:layout_constraintHorizontal_weight="0.01"
app:layout_constraintTop_toTopOf="#+id/entry_1"
app:layout_constraintBottom_toBottomOf="#+id/entry_1"/>
<TextView
android:text="Label 2 Is very very long"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/entry_2"
app:layout_constraintBottom_toBottomOf="#+id/entry_2"
android:id="#+id/label_2" />
<EditText
android:id="#+id/entry_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:inputType="text"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintHorizontal_weight="100.0"
app:layout_constraintLeft_toRightOf="#+id/guideline"
app:layout_constraintRight_toLeftOf="#+id/space_2"
app:layout_constraintTop_toBottomOf="#+id/entry_1"
app:layout_constraintWidth_max="150sp"
app:layout_constraintWidth_min="100sp" />
<Space
android:id="#+id/space_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="#+id/entry_2"
app:layout_constraintHorizontal_weight="0.01"
app:layout_constraintTop_toTopOf="#+id/entry_2"
app:layout_constraintBottom_toBottomOf="#+id/entry_2"/>
<TextView
android:text="Label Three"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/entry_3"
app:layout_constraintBottom_toBottomOf="#+id/entry_3"
android:id="#+id/label_3" />
<EditText
android:id="#+id/entry_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:inputType="text"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="100.0"
app:layout_constraintLeft_toRightOf="#+id/guideline"
app:layout_constraintRight_toLeftOf="#+id/space_3"
app:layout_constraintTop_toBottomOf="#+id/entry_2"
app:layout_constraintWidth_max="150sp"
app:layout_constraintWidth_min="100sp" />
<Space
android:id="#+id/space_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="#+id/entry_3"
app:layout_constraintHorizontal_weight="0.01"
app:layout_constraintTop_toTopOf="#+id/entry_3"
app:layout_constraintBottom_toBottomOf="#+id/entry_3"/>
<android.support.constraint.Barrier
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:barrierDirection="right"
app:constraint_referenced_ids="label_1,label_2,label_3" />
</android.support.constraint.ConstraintLayout>
Edit:
I reported this issue to the ConstraintLayout team at Google and they confirmed that it is a bug. Once fixed, I should be able to do this without the complicated chains.
The Android dev team confirmed this is a bug, and it has been fixed in the beta6 release. The layout now works without the need for any chains or spaces (the solution below is what they suggested in the ticket).
https://issuetracker.google.com/issues/74469361
<TextView
android:id="#+id/label_1"
android:tag="48,103,136,57"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Label 1"
app:layout_constraintBottom_toBottomOf="#+id/entry_1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/entry_1" />
<EditText
android:id="#+id/entry_1"
android:tag="505,63,512,136"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginStart="8dp"
android:inputType="text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="200sp"
app:layout_constraintWidth_min="100sp" />
<TextView
android:id="#+id/label_2"
android:tag="48,254,442,57"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Label 2 Is very very long"
app:layout_constraintBottom_toBottomOf="#+id/entry_2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/entry_2" />
<EditText
android:id="#+id/entry_2"
android:tag="505,214,450,136"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginStart="8dp"
android:inputType="text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/guideline"
app:layout_constraintTop_toBottomOf="#+id/entry_1"
app:layout_constraintWidth_max="150sp"
app:layout_constraintWidth_min="100sp" />
<TextView
android:id="#+id/label_3"
android:tag="48,405,218,57"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Label Three"
app:layout_constraintBottom_toBottomOf="#+id/entry_3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/entry_3" />
<EditText
android:id="#+id/entry_3"
android:tag="505,365,450,136"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginStart="8dp"
android:inputType="text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/guideline"
app:layout_constraintTop_toBottomOf="#+id/entry_2"
app:layout_constraintWidth_max="150sp"
app:layout_constraintWidth_min="100sp" />
<android.support.constraint.Barrier
android:id="#+id/guideline"
android:tag="490,48,0,0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:barrierDirection="right"
app:constraint_referenced_ids="label_1,label_2,label_3" />
My guess would be the fact that you're not really setting up a chain.
https://developer.android.com/training/constraint-layout/index.html
A chain works properly only if each end of the chain is constrained to another object on the same axis
For a proper chain, your labels would need to be part of it as well. You can probably just ditch the chain attributes and constrain the edit texts to the barrier and the parent rights.
Hope that helps.
Try it with Relative Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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">
<TextView
android:id="#+id/label_1"
android:text="Label 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"/>
<EditText
android:id="#+id/entry_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_alignBaseline="#+id/label_1"
android:layout_toEndOf="#+id/label_1"
android:maxLength="20"
android:textSize="20sp"
android:inputType="text" />
<TextView
android:id="#+id/label_2"
android:text="Label 2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textSize="20sp"
android:layout_below="#+id/label_1"/>
<EditText
android:id="#+id/entry_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_alignBaseline="#+id/label_2"
android:layout_toEndOf="#+id/label_2"
android:maxLength="20"
android:textSize="20sp"
android:inputType="text" />
<TextView
android:id="#+id/label_3"
android:text="Label 3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textSize="20sp"
android:layout_below="#+id/label_2"/>
<MultiAutoCompleteTextView
android:id="#+id/entry_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_alignBaseline="#+id/label_3"
android:layout_toEndOf="#+id/label_3"
android:maxLength="200"
android:textSize="20sp"/>
</RelativeLayout>
Edit: This should be your basic structure for form, provided if ConstraintLayout is not the only option.
Just use Relative Layout, Table Layout is not necessary here
Set value for android:maxLength
For including more text-characters use MultiAutoCompleteTextView
I'm using ConstraintLayout where I will show as below
I would like to hide First (using gone), and which the view I expect to be as below (where ElasticBody will stretch over to use up the original First view space as well.
However, when I actual set First to gone, my view turn out to be as below (all image as from Android Studio Design view). My Elastic Body is missing as well, and the height expanded weirdly.
My layout code as below
<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"
android:padding="16dp">
<TextView
android:id="#+id/txt_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0ff"
android:text="First"
android:visibility="gone"
android:textSize="26sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/txt_body"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txt_body"
android:layout_width="0dp"
android:background="#f0f"
android:layout_height="wrap_content"
android:text="Elastic Body"
android:textSize="26sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/txt_tail"
app:layout_constraintStart_toEndOf="#+id/txt_first"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txt_tail"
android:background="#ff0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tail"
android:textSize="26sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/txt_body"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
(Note, if you remove the gone, you'll get the first image view).
Why is this so? How could I fix it where when my First is gone, I could the Elastic Body stretch out correctly?
p/s: I know how to do it in LinearLayout and RelativeLayout... but wonder if this is a limitation on ConstraintLayout?
Try following.
Set the first view's left and top constraints to "parent". After that:
set the txt_body textview width to "0dp"
set the left constraint to the first view's right side
set the right constraint to the tail view's left side.
So, whenever you set the first view's visibility to "gone", the body view will be stretched like how you want it.
<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"
android:padding="16dp">
<TextView
android:id="#+id/txt_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0ff"
android:text="First"
android:textSize="26sp"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="#+id/txt_body"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="#+id/txt_body"
android:layout_width="0dp"
android:background="#f0f"
android:layout_height="wrap_content"
android:text="Elastic Body"
android:textSize="26sp"
app:layout_constraintRight_toLeftOf="#+id/txt_tail"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="#+id/txt_first"
/>
<TextView
android:id="#+id/txt_tail"
android:background="#ff0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tail"
android:textSize="26sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
Update
If you want to do using barrier then also you can do it.
<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"
android:padding="16dp">
<TextView
android:id="#+id/txt_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0ff"
android:text="First"
android:textSize="26sp"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="#+id/barrier"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txt_body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#f0f"
android:text="Elastic Body"
android:textSize="26sp"
app:layout_constraintStart_toEndOf="#+id/barrier"
app:layout_constraintEnd_toStartOf="#+id/txt_tail"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txt_tail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff0"
android:text="Tail"
android:textSize="26sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="start"
app:constraint_referenced_ids="txt_body,txt_first" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="txt_body,txt_tail" />
</androidx.constraintlayout.widget.ConstraintLayout>
Say, you want to have a picture like this:
Here you have indents between the title and "Nice work", between "Nice work" and time, also horizontal indent to "Opinions". They are centered vertically.
"Opinions" is attached to the star, so that can be multilined and stay centered. I show results for 2 variants: in the first row opinions are multilined, while in the next row it is a single line. In columns you can see 4 variants of showing/hiding 2 labels.
A more simple and preferrable way is to wrap both labels into LinearLayout and insert it into parent ConstraintLayout. Then you can set vertical gravity, show or hide labels, hide the LinearLayout itself.
If you don't want to have nested layouts, use Barriers and Groups. It is a difficult task that can waste many hours. A key is having additional Views for aligning. Here I have 2 hiding labels ("Nice work" and "Opinions"), and I have to add 2 views (spaces).
The height of the right space is equal to the height of the star (14dp).
To simplify hiding several views, I joined them into groups.
You can see horizontal dotted lines - they are Barriers. I align them on tops and bottoms of the most big views (barrier_2 is similar):
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="left_text,opinion" />
Vertical aligning is based on these 2 additional Spaces (see marginTop="10dp"):
<Space
android:id="#+id/left_text_space"
android:layout_width="25dp"
android:layout_height="10dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toEndOf="#id/left_text"
app:layout_constraintTop_toBottomOf="#id/title" />
It is difficult to cover all situations, so see the following 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="match_parent"
android:paddingLeft="15dp"
android:paddingTop="5dp"
android:paddingRight="15dp"
android:paddingBottom="5dp">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lineSpacingExtra="4sp"
android:lines="1"
android:paddingBottom="5dp"
android:text="«Title text»"
android:textColor="#333333"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="left_text,opinion" />
<TextView
android:id="#+id/left_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#112233"
android:paddingLeft="5dp"
android:paddingTop="4dp"
android:paddingRight="5dp"
android:paddingBottom="4dp"
android:text="Nice work"
android:textColor="#ffffff"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="#id/barrier_2"
app:layout_constraintStart_toStartOf="#id/title"
app:layout_constraintTop_toTopOf="#id/left_text_space" />
<Space
android:id="#+id/left_text_space"
android:layout_width="25dp"
android:layout_height="10dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toEndOf="#id/left_text"
app:layout_constraintTop_toBottomOf="#id/title" />
<androidx.constraintlayout.widget.Group
android:id="#+id/left_text_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="left_text,left_text_space" />
<Space
android:id="#+id/opinion_space"
android:layout_width="1dp"
android:layout_height="14dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="#id/left_text_space"
app:layout_constraintTop_toBottomOf="#id/title" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="left_text,opinion" />
<ImageView
android:id="#+id/opinion_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:contentDescription="#null"
app:layout_constraintBottom_toBottomOf="#id/barrier_2"
app:layout_constraintStart_toEndOf="#id/left_text_space"
app:layout_constraintTop_toTopOf="#id/opinion_space"
app:srcCompat="#drawable/ic_filled_rate_star" />
<TextView
android:id="#+id/opinion"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:lineSpacingExtra="1sp"
android:text="1. Opinion 1.\n2. Opinion 2.\n3. Opinion 3.\n4. Opinion 4."
android:textColor="#1122aa"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="#id/opinion_icon"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="#id/opinion_icon"
app:layout_constraintTop_toTopOf="#id/opinion_icon" />
<androidx.constraintlayout.widget.Group
android:id="#+id/opinion_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="opinion_icon,opinion,opinion_space" />
<ImageView
android:id="#+id/time_icon"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_gravity="center_vertical"
android:layout_marginTop="8dp"
android:contentDescription="#null"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/barrier_2"
app:srcCompat="#drawable/ic_time" />
<TextView
android:id="#+id/time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
android:layout_marginLeft="7dp"
android:ellipsize="end"
android:lineSpacingExtra="1sp"
android:lines="2"
android:paddingBottom="7dp"
android:text="17:00"
android:textColor="#9e9e9e"
android:textSize="11sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="#id/time_icon"
app:layout_constraintTop_toTopOf="#id/time_icon" />
</androidx.constraintlayout.widget.ConstraintLayout>
Then in your activity you can show/hide labels. Hide Groups, not views inside, because strangely inside a Group views are always visible.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
left_text_group.visibility = View.GONE
opinion_group.visibility = View.VISIBLE
}
An answer has already been given linking to Barriers. I will provide an example of how I've actually implemented it:
<TextView
android:id="#+id/textView1"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:text="Some text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView2"
app:layout_constraintTop_toBottomOf="#id/textView1"
app:layout_constraintLeft_toLeftOf="parent"
android:text="Some other text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="textView1,textView2" />
This example shows 2 TextViews either of which can be gone. The Views are on stacked from top to bottom, so barrierDirection is set to bottom. Should you need another direction, just change that line accordingly.
Setting any of the 2 TextViews to gone, will result in the Barrier shifting to the bottom of the other, and if we set both to gone, it'll just shift up to the element that textView1's top constraint was referencing, in this case, the parent.
Note: If your textView1's top constraint is something else, i.e. it's below another element, the barrier will end up there if both views are set to gone.