constraintlayout - set a view padding depending on another view - android

I would like to know if I can set the title of TextView_1 to be centered of the parent view but ellipsize end against TextView_2 like picture below by using constraint layout. if the text in TextView_1 gets longer then, make it ellipsized. and below would be the case where I wanted to put "Text to be centered but ellipsize against TextView_2 when it gets longer".
what I have tried are
I programmatically tried to get the width of TextView_2 and set it to padding right of TextView_1. but failed since I wasn't able to get the width of TextView_2(I get 0) since it is set to be 0dp in constraint layout to be stretched.
I tried to find a way to set TextView_1 padding as TextView_2 size in xml file but that doesn't seem to be possible.
I have no more good idea to make it work. is there any work around for it? I will appreciate your help in advance.

You didn't post code, but I don't think you waited for the layout to occur to get the size of textView2. Here is some working code with the following XML. The code runs in the onCreateView() function of the Fragment. After layout, the width of TextView2 is set to the start/left padding of TextView1.
<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:ellipsize="end"
android:maxLines="1"
android:text="Text to be centered but ellipsize against TextView_2 when it gets longer"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/textView2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="TextView2"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/textView1" />
</androidx.constraintlayout.widget.ConstraintLayout>
binding = DataBindingUtil.setContentView(requireActivity(), R.layout.fragment_main)
binding.root.doOnNextLayout {
binding.textView1.updatePadding(binding.textView2.width)
}

Related

Why the vertical TextView taking different spaces -android-

I have a TextView inside CardView. after rotation (-90 or 270), each textView had different space from ImageView
The result is like this:
(https://i.stack.imgur.com/ad9r1.jpg)
XML:
<TextView
android:id="#+id/number"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="123456789"
android:rotation="-90"
app:layout_constraintStart_toEndOf="#id/image_item"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
I tried to put the TextView inside LinearLayout but the output is the same.
if there any solution (using just XML) please tell me.
i found this on stackoverflow :
Vertical TextView taking too much space in Android
but the result is the same and i am looking for solution using XML code
I just changed layout_height to 0dp and modified the layout_constraint, like the code below:
<TextView
android:id="#+id/number"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:text="123456789"
android:rotation="-90"
app:layout_constraintStart_toEndOf="#id/image_item"
app:layout_constraintTop_toTopOf="#id/image_item"
app:layout_constraintBottom_toBottomOf="#id/image_item"/>
Now, no matter the length of the text, it will be attached to view next to it.

Allow TextView to grow until a certain point in constraint layout

There is TextView1 and TextView2. TextView2 should float on the right side of TextView1. TextView1 should grow to the right as long as the total width of both text views do not make TextView2 overlap with the box on the right. When this happens, TextView1 should wrap to a second line.
When there is only one TextView, this is achievable by setting TextView's width to 0dp and constraining the size to the box. But with two text views I don't know how to achieve this.
You can achieve this with the use of the following attributes:
app:layout_constraintHorizontal_bias="0": makes sure the first text view leaves no space on the left.
app:layout_constraintHorizontal_chainStyle="packed": removes spacing between items in the text view chain.
app:layout_constrainedWidth="true": allows the use of wrap_content on the text view while still allowing to wrap if text is too long.
Here's the layout:
<TextView
android:id="#+id/text_view_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="#id/text_view_2"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Very long text in this text"
app:layout_constraintHorizontal_bias="0"
/>
<TextView
android:id="#+id/text_view_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_constraintEnd_toStartOf="#id/box"
app:layout_constraintStart_toEndOf="#id/text_view_1"
app:layout_constraintTop_toTopOf="parent"
tools:text="Text"
/>
<View
android:id="#+id/box"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
I suggest you try removing each attribute to see what effect they have.

How to prevent an imageview to be "pushed" outside the screen by a textview with variable dimensions?

In a constraint layout, I have a textview, with an imageview next to it:
But sometimes the text in the textview can be very long and sometimes span more than one line. In these cases, the imageview get pushed outside the view:
Even addind a constraint between the imageview and the view container, the imageview gets pushed outside the view.
The goal is to always have the image right next to the text and if it grows, the image starts getting pushed to the side as long is not going outside the view. When it touches the boundaries of the view, it should stay there while the text wraps to the next line.
This code block just shows the case of the second picture:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView" android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
tools:text="This is a cat with a lot more text next to it so pay attention "/>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp" tools:srcCompat="#tools:sample/avatars[3]"
android:id="#+id/imageView"
app:layout_constraintStart_toEndOf="#+id/textView" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I've tried usgin barriers and guidelines, but they really do not serve for this case. The textview needs to be wrap_content since its size is variable and it is preferable to use constraint layout, that's why I did not used another one. Chains also did not work here.
You can use a packed chain with a bias of 0 to make it start-aligned and then set app:layout_constrainedWidth="true" for both views so that their constraints are respected when wrapping content.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="Text goes here"
android:textSize="24sp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="#id/image"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/textView"
app:layout_constraintTop_toTopOf="parent"
tools:src="#tools:sample/avatars" />
</android.support.constraint.ConstraintLayout>
The problem is that you are setting textview's wrap_content. Doing so will let the textview decide its own width, ignoring layout constraints such as margins.
You need to set width to 0dp which is interpreted as match_constraint in constraint layout, it allows the layout to decide textview's width which means that textview will be given as much width as necessary after margins and other layout constraints are applied.
Now to your desired effect, first remove all constraints from both views. Select both of them, then right click and select chain option from the options menu. Then Pack them horizontally. This would form a chain.
Why do we need chain?
Because you want the imageview to right of textview and textview to left of image view, this kind of two way constraint cannot be added because TextView won't draw till imageview is drawn and imageview is waiting for textview to draw.
Chain will help you tackle this problem.

How do I center a text inside a chain relative to the whole screen?

I want to create a user name centered TextView with an edit button to the right of the screen. If I specify the TextView to match the start/end of the parent, it will center. However, the text will overflow and paint over the button. I can chain one side of the text to the button, but then the text will not be centered. Here is the example code I have where tvName is not centered due to the button in the horizontal chain:
<TextView
android:id="#+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/pt_name_font_size"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="#id/tvUserMsisdn"
app:layout_constraintEnd_toStartOf="#id/ibChangeName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/aivProfile"
tools:text="B"/>
<TextView
android:id="#+id/tvName2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/pt_name_font_size"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="#id/tvUserMsisdn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tvName"
tools:text="A"/>
<ImageButton
android:id="#+id/ibChangeName"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginEnd="#dimen/default_margin"
app:layout_constraintBottom_toBottomOf="#id/tvName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#id/tvName"
android:background="#android:color/black"/>
This is what it looks like:
I can't use a horizontal bias, since the button has to remain with a static size, and the width of the screen may vary, as well as the size of the font. Ideally, I would be able to specify two app:layout_constraintEnd_toStartOf attributes, one for the whole width of the screen, so the text remains centered, and another one for the button, so it won't overflow.
Ideally, I would be able to specify two app:layout_constraintEnd_toStartOf attributes
I'm sure you already know this, but that is impossible.
The only thing you can do that is like that is to use a Barrier, but that's not helpful here because (in this case) that would be functionally identical to simply constraining the end to the start of the ImageButton.
The best thing you can do here, in my opinion, is to constrain the TextView's start and end to the parent, and then use padding to make sure that long text doesn't overlap the ImageButton. The button has a fixed width (28dp), and a fixed margin (#dimen/default_margin), so you can give the TextView left/right padding equal to 28dp + 2x default_margin. This will make sure that text wraps at least default_margin away from the left edge of the ImageButton.
Put both the TextView and the ImageButton inside a RelativeLayout:
<RelativeLayout
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvName2"
android:layout_alignParentStart="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toStartOf="#+id/ibChangeName"
android:textSize="#dimen/pt_name_font_size"
android:textStyle="bold"
tools:text="A"/>
<ImageButton
android:id="#+id/ibChangeName"
android:layout_alignParentEnd="true"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginEnd="#dimen/default_margin"
android:background="#android:color/black"/>
</RelativeLayout>
This attribute for the TextView
android:layout_toStartOf="#+id/ibChangeName"
ensures that the TextView won't overlap with the ImageButton
Now you have to center the relative layout
If the ImageButton always has a fixed size (28dp in this case) you can use a Space widget with the same dimensions as the button and place it on the left edge of the parent. You can then chain the three Views together and set the chain's style to spread_inside. The TextView's width can be set to match_constraint and its gravity to center or use wrap_content and app:layout_constrainedWidth="true" so it doesn't overlap the other Views if it gets too big.
Example XML to get the general idea:
<?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">
<Space
android:id="#+id/space"
android:layout_width="28dp"
android:layout_height="28dp"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintEnd_toStartOf="#id/textview"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Textview"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="#id/button"
app:layout_constraintStart_toEndOf="#id/space" />
<ImageButton
android:id="#+id/button"
android:layout_width="28dp"
android:layout_height="28dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/textview" />
</android.support.constraint.ConstraintLayout>

Android simple layout of 2 views

Can't understand how to implement simple thing.
I need layout of 2 views with next behaviour:
button should be to right of text when text is short
when text is long it ellipsizes and button always visible and full-width
now I get that button is going out of screen
You can achieve this using ConstraintLayout. Here's a template:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello world"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_default="wrap"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/button"
app:layout_constraintBottom_toBottomOf="parent"/>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HELLO WORLD"
app:layout_constraintLeft_toRightOf="#+id/text"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBaseline_toBaselineOf="#+id/text"/>
</android.support.constraint.ConstraintLayout>
The initial setup is:
Create a horizontal chain including the text and the button
Set the chain style to "packed" so that there's no space between the views
Set the horizontal bias to 0 so that the packed views hug to the left
The magic comes with the TextView's width and the app:layout_constraintWidth_default attribute. By setting the width to 0dp and the "default width" to wrap, we're telling Android to give the view as much space as it needs to hold its contents as long as it fits the constraints. When the text is really long, the constraints will keep it from pushing the button off the right side of the screen.

Categories

Resources