I'm having an issue sizing children in a ConstraintLayout. I have 3 views:
TextView (item_quantity): I want this to grow indefinitely, but not push the TextInputLayout off the screen
TextInputLayout (data_entry_layout): I want this to fill all available horizontal space and have a minimum width of 120dp no matter what
ImageView (camera_scan): This will not grow, just needs to not get pushed off the screen
If item_quantity has short text, I want it to look like the image below. I want data_entry_layout to fill all available space.
If item_quantity has long text, I want it to fill and grow but I want the data_entry_layout to never be smaller than 120dp. I want it to honor the minWidth. So, I want it to look like this:
Here is my current configuration:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<TextView
android:id="#+id/item_quantity"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/data_entry_layout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintVertical_chainStyle="spread_inside"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="90,000 Boxes of Stuff Are Needed"
android:textColor="#color/color_on_background"
android:textSize="#dimen/workflow_item_view_item_quantity_text_size" />
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/data_entry_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="#id/camera_scan"
app:layout_constraintStart_toEndOf="#id/item_quantity"
app:layout_constraintVertical_chainStyle="spread_inside"
android:contentDescription="#string/disable_realwear_asr"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:minWidth="120dp"
app:errorIconDrawable="#null">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/data_entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/activity_instruction_data_entry_text_size"/>
</com.google.android.material.textfield.TextInputLayout>
<ImageView
android:id="#+id/camera_scan"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginEnd="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="#id/data_entry_layout"
app:layout_constraintTop_toTopOf="#id/data_entry_layout"
android:background="#android:color/transparent"
android:clickable="true"
android:foreground="#drawable/ripple_selector"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:src="#drawable/qrcode_scan"
android:visibility="visible"
tools:ignore="ContentDescription,KeyboardInaccessibleWidget" />
</androidx.constraintlayout.widget.ConstraintLayout>
If I set item_quantity's layout_width to 0dp then the UI works with lots of text, but takes up too much horizontal space with short text:
If I set item_quantity's layout_width to wrap_content then the UI works with short text, but pushes the data_entry_layout off the screen with large text:
I must be missing something simple. Is there a way I can get both of these situations to do what I want?
Rather than use the android:minWidth property try using app:layout_constraintWidth_min. ConstraintLayout seems to either ignore or overrule certain properties with the "android" namespace when it comes to sizing of elements.
Related
I am using a ConstraintLayout and I want to create a TextView that takes up 30% of the height of the screen or the size of its content, whichever is greater.
I can use constraints to make it take up 30% of the screen via a horizontal guideline, and I can leave off those constraints to make it grow/shrink with the size of the text. However, I can't get it to do both --- that is, be 30% as a minimum but grow beyond that if needed.
I tried using layout_constraintHeight_min and setting it to a percent, to a guideline, and to a view with a set height, but none of those works. I know it will work if I put in a hardcoded value like 200dp, but I want the value to be proportional --- that is, a percent.
I essentially want something like this, though as I mentioned above, this code doesn't work because technically a guideline has a height of 0:
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintHeight_min="#+id/guideline8"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="MyText" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline8"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.7" />
I also tried
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintHeight_min="#+id/heightGuide"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="MyText" />
<View
android:id="#+id/heightGuide"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="#+id/guideline8"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="invisible"/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline8"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.7" />
but that doesn't work either.
How can I make a view have a minimum height that is a proportion of the parent, but also allow it to grow beyond that height if needed?
I had to deal with a similar situation and finally managed to solve it by adding the following to my view:
android:layout_height="0dp"
app:layout_constraintHeight_min="wrap"
app:layout_constraintHeight_percent="0.66"
Hope this works for you
If I have two textviews vertically aligned where either the one OR the other could contain the longer text, how can I vertically align these so their background image LOOKS like it is one complete background for both TextViews (so one big box no matter which of those views contains the longer text)
Reason is that I use the textviews on top of a picture but need to shadow them in case the picture has the same color as the textview
UPDATE:
As the comments suggested I now used a linear layout like this, but now there is a very small gap between the textviews that wasn't there with ConstraintLayout. Any idea how to fix?
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginEnd="10dp">
<TextView
android:id="#+id/tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/bg_overlay_top"
android:paddingStart="6dp"
android:paddingTop="6dp"
android:paddingEnd="6dp"
android:text="TextView1"
android:textColor="?colorOnPrimary"
android:textSize="13sp"/>
<TextView
android:id="#+id/tv2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="14dp"
android:background="#drawable/bg_overlay_bottom"
android:paddingStart="6dp"
android:paddingEnd="6dp"
android:paddingBottom="6dp"
android:text="TextVie2 long"
android:textColor="?attr/colorOnPrimary"
android:textSize="16sp"
android:textStyle="bold"/>
</androidx.appcompat.widget.LinearLayoutCompat>
UPDATE 2
I now used a complete image as background of the linear layout, but sadly this solution does not work either, the linear layout only constraints to the lower text view, which means if the lower is shorter then the upper, the upper one gets truncated
Here is how you can get the two TextViews to have the same width regardless of which view has the longer text.
<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:background="#android:color/darker_gray"
android:text="Here is some long, long text."
android:textSize="28sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#id/barrierEnd"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="wrap" />
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#android:color/darker_gray"
android:gravity="center"
android:text="Bottom"
android:textSize="28sp"
app:layout_constraintEnd_toEndOf="#id/barrierEnd"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView1"
app:layout_constraintWidth_min="wrap" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrierEnd"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierDirection="end"
app:constraint_referenced_ids="textView1,textView2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This solution was borrowed from here. I took a stab at explaining why it works here.
For one big blue background as you said, you can use a vertical LinearLayout as a container of both TextViews and set its background color to blue.
If you are using a vertical LinearLayout, you could set android:layout_width (of the TextViews) to "match_parent" instead of "wrap_content".
Edit: Into the outer vertical LinearLayout put an another vertical LinearLayout with android:layout_width="wrap_content" and the 2 TextViews inside with android:layout_width="match_parent"
If you're using constraint layout then
app:layout_constraintStart_toStartOf
would be working for you , also using baseline would be very useful too.
How do I remove the spacing on the top and bottom of the texts? I want to the two texts to touch each other or at least reduce the spacing between the texts.
I've looked at other posts recommending setting android:includeFontPadding="false", but that does not work.
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="96sp"
android:text="TEXT1"
android:background="#color/primaryColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="96sp"
android:text="TEXT2"
android:background="#color/secondaryColor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/textView" />
The problem is that's not just empty space - it's the ascent and descent for the font, where things like the lower part of a g goes. The TextView has to have that space because it doesn't know you're not going to be using it. includeFontPadding affects some accents on top of the ascent, so you can remove a little bit of the space, but the rest of it's required.
Short of getting a font with no ascent and descent, honestly I think the best thing you can do is constrain the top of the lower TextView to the top of the upper one, and add a marginTop value that shifts it down where you want it. Use an sp value instead of dp so it stays relative to the user's font size preferences - and if you change the font you'll need to tweak it. And the backgrounds will have to be separate, behind the textviews, if you're using those
If you absolutely want this at any cost, then you can do the following, I have not checked if it will work on different screen sizes . But you can attach both of their top to the same view, can be parent, then make the background transparent, if you chose different colours then this wont work, keep the text in all caps so that the regular alphabets can't go any higher or lower. Keep the margin according to the text size which you will give in dp. This is probably "I want this in any way" approach rather than an acceptable approach.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="95dp"
android:text="TEXT1"
android:background="#android:color/transparent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="0dp"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:text="TEXT2"
android:textSize="95dp"
android:layout_marginTop="75dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
You can do some clever stuff with a Space view to make this work:
<TextView android:id="#+id/textView1"
[other TextView stuff]
app:layout_constraintTop_toTopOf="parent"/>
<Space android:id="#+id/space"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="#id/textView1"/>
<TextView android:id="#+id/textView2"
[other TextView stuff]
app:layout_constraintTop_toBottomOf="#id/space"/>
Then fiddle with the margin parameter in the Space view until the text is where you want it.
I can't figure out how to render my listItems correctly. Everything seems fine until the text title is too long. Looking at the pics below, I have the Title anchored on the left side of the listItem View and to the right of the imageView. I've even tried anchoring the right side to the right edge of the entire view but with no success. If the user enters a title too long the views overlap.
I want the title to be centered between the imageview and the left side of the entire listItem view. I have provided pics of how this all renders. Any help would be greatly appreciated. When the title gets long enough, it wraps the text which is fine. At this point I'd even settle for the trailing ... but I would prefer to have the text wrap. I just don't want to overlap the imageview. I have also posted the xml code
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp"
android:id="#+id/list_item_container">
<TextView
android:id="#+id/match_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textSize="16sp"
tools:text="Match Name"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp"
app:layout_constraintRight_toLeftOf="#+id/imageView"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"/>
<TextView
android:id="#+id/match_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Match Date"
android:textAlignment="center"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintRight_toLeftOf="#+id/imageView"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="#+id/match_name"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"/>
<ImageView
android:id="#+id/imageView"
android:layout_width="60dp"
android:layout_height="45dp"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="8dp"
android:layout_weight="1"
app:srcCompat="#drawable/ic_more_vert_black_24dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginRight="68dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
app:layout_constraintVertical_bias="0.484"/>
<TextView
android:id="#+id/match_id_hidden"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:visibility="invisible"
tools:layout_editor_absoluteY="67dp"
tools:layout_editor_absoluteX="24dp"/>
</android.support.constraint.ConstraintLayout>
Inside the ConstraintLayout try to always use "0dp" for your heights and widths and always set the app:layout_constraint..._to...Of for all 4 sides for all your views. Examine the outcome and then fine tune to get the expected result. Do this in the XML instead of in the visual editor; in my experience it is quicker and it avoids the layout_editor_absolute... settings.
Set android:layout_width="0dp" for both your TextViews. In a ConstraintLayout, a value of "0dp" basically means match the constraints. A value of "wrap_content" doesn't take constraints into account when measuring the views, just when positioning them.
Is there a possibility (in ConstraintLayout) to let a view grow only as long as there is space for another view at his right?
The use case is to have a value and unit TextViews besides each other. The value TextView should be able to grow as long as there is space for the unit. If there is not enough space, the value should be cut.
I've tried it with chains and some other things but can't get it done. The value doesn't stop growing and then the unit is not visible anymore. Here's the current code:
<TextView
android:id="#+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:lines="1"
app:layout_constraintBaseline_toBaselineOf="#+id/unit"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/unit"
tools:text="12533939532" />
<TextView
android:id="#+id/unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toRightOf="#id/value"
app:layout_constraintRight_toRightOf="parent"
tools:text="km" />
yes you can by using match_constraint (0dp) which equal to match_parent for other layout, so by using match_constraint we set weight for first view which will occupies all available space also add
app:layout_constraintWidth_default="wrap"
to apply default width behavior as wrap_content
here is code with change
<?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">
<TextView
android:id="#+id/value"
android:layout_width="0dp"
app:layout_constraintWidth_default="wrap"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:lines="1"
app:layout_constraintBaseline_toBaselineOf="#+id/unit"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/unit"
tools:text="12533939532" />
<TextView
android:id="#+id/unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintLeft_toRightOf="#id/value"
app:layout_constraintRight_toRightOf="parent"
tools:text="km" />
</android.support.constraint.ConstraintLayout>
got some explanation from site
Better view dimension controls
The new available behaviors when a dimension is set to 0dp (MATCH_CONSTRAINT). As before, both endpoints (left/right or top/bottom) need to be connected to targets.
layout_constraintWidth_default = spread (default, similar to the previous behavior)
layout_constraintWidth_default = wrap
layout_constraintHeight_default = spread
layout_constraintHeight_default = wrap
Wrap provides a significant new behaviour, with the widget resizing as if wrap_content was used, but limited by the connected constraints. A widget will thus not grow beyond the endpoints.
http://tools.android.com/recent/constraintlayoutbeta5isnowavailable