Android constraintlayout vertical textview alignment - android

I have following layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/dishContainer"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#0ff"
android:clickable="true"
android:focusable="true">
<TextView
android:id="#+id/one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:maxLines="3"
android:background="#ff0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="One line lsfdjslkdf jksdljsdkljf sklksf klsjklsksjskfljsaklfj slkjfslkjfdskljfalskjflksdajfaklsjksadljfksfjksjkslfjsljsk lskjslksj ks flks jklsfjsl lsk slk" />
<TextView
android:id="#+id/two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0f0"
app:layout_constraintStart_toStartOf="#+id/one"
app:layout_constraintTop_toBottomOf="#+id/one"
app:layout_constraintBottom_toTopOf="#+id/three"
tools:text="Two kksldfj lskfd lksd jlkfsd jksld ksldfj sdlks dklfklsffsd klsdfjklsdf kdsflkj skldfsf sdfksdjf jsdfsjklfklskfls fklsf jklsdfjksf lksjdflk sdklsf lksfdjkls fk" />
<TextView
android:id="#+id/three"
android:layout_width="wrap_content"
android:background="#f00"
android:lines="1"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="#+id/two"
app:layout_constraintTop_toBottomOf="#+id/two"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="Third text that dissapears, but should not go below the parent" />
</android.support.constraint.ConstraintLayout>
The problem is that green textview takes too much space and ignores top and bottom constraints. If I set green text view height to 0dp
I get this:
Which is almost what I want, but if I only have very little text I get:
Here my red textview is left at the bottom, even though green text view has enough free space to shrink and let red textview go up.
Basically I want my red view to always be bellow green view, but when red hits the bottom of parent window it should stop there and also stop green textview from expanding.
How do I achieve this?

Try this
(I set layout_width to match_parent..., you can change it if you want)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:id="#+id/one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:background="#ff0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="One line lsfdjslkdf jksdljsdkljf sklksf klsjklsksjskfljsaklfj slkjfslkjfdskljfalskjflksdajfaklsjksadljfksfjksjkslfjsljsk lskjslksj ks flks jklsfjsl lsk slk" />
<TextView
android:id="#+id/two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#0f0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/one"
app:layout_constraintBottom_toTopOf="#id/three"
app:layout_constrainedHeight="true"
tools:text="Two kksldfj lskfd lksd jlkfsd jksld ksldfj sdlks dklfklsffsd klsdfjklsdf kdsflkj skldfsf sdfksdjf jsdfsjklfklskfls fklsf jklsdfjksf lksjdflk sdklsf lksfdjkls fk" />
<TextView
android:id="#+id/three"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#f00"
android:lines="1"
app:layout_constraintHeight_min="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/two"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="Third text that dissapears, but should not go below the parent" />
</android.support.constraint.ConstraintLayout>

While the accepted answer works, I noticed that the height of the bottom TextView will expand to fill the remaining vertical space of the container.
With the help of a Guideline, we can give the bottom TextView a fixed height regardless if it has room to expand.
dimens.xml
<dimen name="bottom_view_height">20dp</dimen>
layout.xml
<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">
<TextView
android:id="#+id/green"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#4CAF50"
android:maxLines="3"
app:layout_constraintTop_toTopOf="parent"
tools:text="#tools:sample/lorem/random"/>
<TextView
android:id="#+id/yellow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFEB3B"
app:layout_constrainedHeight="true"
app:layout_constraintTop_toBottomOf="#id/green"
app:layout_constraintBottom_toTopOf="#id/bottom_guide"
app:layout_constraintVertical_bias="0"
tools:text="#tools:sample/lorem/random"
tools:lines="100"/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/bottom_guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_end="#dimen/bottom_view_height"/>
<TextView
android:id="#+id/red"
android:layout_width="match_parent"
android:layout_height="#dimen/bottom_view_height"
android:background="#F44336"
app:layout_constraintTop_toBottomOf="#id/yellow"
tools:text="#tools:sample/lorem/random"/>
</androidx.constraintlayout.widget.ConstraintLayout>
How it works:
The Guideline serves as the bottom constraint for the middle TextView, which is aligned to its top constraint via layout_constraintVertical_bias="0".
Setting layout_constrainedHeight="true" on the middle TextView ensures it never expands past the guideline. This in turn ensures that the bottom TextView will never go off screen.

I would remove the app:layout_constraintBottom_toTopOf="#+id/three" constraint on TextView #2, there's no need for it and it's probably the reason why you're seeing the 2nd TextView take up the extra space.

We should not use static value for height if content is dynamic.Don't align a view at bottom in constraint layout if you assign views in linear way
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/dishContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#0ff"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:clickable="true"
android:focusable="true">
<TextView
android:id="#+id/one"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="#ff0"
android:maxLines="3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="One line lsfdjslkdf jksdljsdkljf sklksf klsjklsksjskfljsaklfj slkjfslkjfdskljfalskjflksdajfaklsjksadljfksfjksjkslfjsljsk lskjslksj ks flks jklsfjsl lsk slk" />
<TextView
android:id="#+id/two"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#0f0"
app:layout_constraintEnd_toEndOf="#+id/one"
app:layout_constraintStart_toStartOf="#+id/one"
app:layout_constraintTop_toBottomOf="#+id/one"
tools:text="Two kksldfj lskfd lksd jlkfsd jksld ksldfj sdlks dklfklsffsd klsdfjklsdf kdsflkj skldfsf sdfksdjf jsdfsjklfklskfls fklsf jklsdfjksf lksjdflk sdklsf lksfdjkls fk" />
<TextView
android:id="#+id/three"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#f00"
android:lines="1"
app:layout_constraintEnd_toEndOf="#+id/one"
app:layout_constraintStart_toStartOf="#+id/one"
app:layout_constraintTop_toBottomOf="#+id/two"
tools:text="Third text that dissapears, but should not go below the parent" />
</android.support.constraint.ConstraintLayout>

you could try Linear Layout
Edit New Code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:orientation="vertical">
<TextView
android:id="#+id/one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:maxLines="3"
android:background="#ff0"
android:text="One line lsfdjslkdf jksdljsdkljf sklksf klsjklsksjskfljsaklfj slkjfslkjfdskljfalskjflksdajfaklsjksadljfksfjksjkslfjsljsk lskjslksj ks flks jklsfjsl lsk slk"
/>
<TextView
android:id="#+id/two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="#0f0"
android:text="Two kksldfj lskfd lksd jlkfsd jksld ksldfj sdlks dklfklsffsd klsdfjklsdf kdsflkj skldfsf sdfksdjf jsdfsjklfklskfls fklsf jklsdfjksf lksjdflk sdklsf lksfdjkls fk" />
<TextView
android:id="#+id/three"
android:layout_width="match_parent"
android:background="#f00"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="Third text that dissapears, but should not go below the parent" />

Related

Android: Show button just below to the recylerview but always on the screen

On the screen, I want to show RecyclerView which start from the top and at the end of the RecyclerView, there is a button.
When RecyclerView is not occupying the entire screen then the Button will sit just below the RecyclerView.
When RecylerView is scrollable then in this case button will sit on the bottom of the screen.
I tried this code. But the problem here, RecyclerView sits in the centre. In my case, it will always start from the top(after the action bar).
Following code I tried:
main 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#b6d7a8" >
<LinearLayout
android:id="#+id/actionBarTermsAndCondition"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/dark_gray"
android:gravity="center_vertical"
android:minHeight="70dp"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingTop="10dp"
android:paddingEnd="16dp"
android:paddingBottom="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<ImageView
android:id="#+id/closeButton"
android:layout_width="#dimen/spacing_2x"
android:layout_height="#dimen/spacing_2x"
android:layout_gravity="center_vertical"
android:layout_marginEnd="#dimen/spacing_2_5x"
android:clickable="true"
android:contentDescription="#string/close"
android:foreground="?selectableItemBackground"
android:src="#drawable/cross"
android:visibility="invisible" />
<TextView
android:id="#+id/route"
style="#style/ScreenTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:contentDescription="Import Venue"
android:fontFamily="#font/roboto"
android:text="Import Venue"
android:textColor="#color/white"
tools:text="Something" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:name="DataManagementFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="LinearLayoutManager"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toTopOf="#id/constraint_layout_cloud_access"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/actionBarTermsAndCondition"
app:layout_constraintVertical_chainStyle="packed"
tools:itemCount="3"
tools:listitem="#layout/fragment_data_management_list_row" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraint_layout_cloud_access"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FEAB8C"
android:paddingStart="16dp"
android:paddingTop="10dp"
android:paddingBottom="21dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/list">
<TextView
android:id="#+id/text_cloud_access"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/roboto"
android:text="Cloud access"
android:textColor="#3C3C41"
android:textSize="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Cloud access" />
<TextView
android:id="#+id/text_import_venue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/roboto"
android:text="Import venue"
android:textColor="#3C3C41"
android:textSize="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/text_cloud_access"
tools:text="Import place" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
RecyclerView row 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"
xmlns:tools="http://schemas.android.com/tools"
android:background="#fff2cc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="#dimen/spacing_3x"
android:paddingStart="#dimen/spacing_2x"
android:paddingBottom="#dimen/spacing_2_5x"
android:paddingTop="#dimen/spacing_2_5x"
android:orientation="horizontal"
tools:showIn="#layout/fragment_data_management">
<TextView
android:id="#+id/text_floor_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/roboto"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#3C3C41"
android:textSize="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Preloaded" />
<TextView
android:id="#+id/text_venue_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/roboto"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#636367"
android:textSize="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/text_floor_name"
tools:text="ABC" />
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="?android:attr/listChoiceIndicatorMultiple"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView2"
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:srcCompat="?attr/dividerHorizontal" />
</androidx.constraintlayout.widget.ConstraintLayout>
Your RecyclerView is centering between two other layouts. Add
app:layout_constraintVertical_bias="0.0"
to the XML for the RecyclerView to move it to the top. You can look up how bias works in the ConstraintLayout documentation.
I think you can achieve what you want with a guideline. The steps would be the following:
Create an horizontal guideline that sits at the 90% of the screen, meaning that it will be really close to the bottom, on the 10% left is where your button will be when the recycler view becomes scrollable.
Set the bottom constraint of the recycler view to match the top of the guideline and the top of the recycler view to the top of the screen. This will cause that the recycler view appears on the half of your screen.
Set the vertical bias of your recycler view to 0.0, this will stick the recycler view to the top.
Set the top constraint of the button to match the bottom of the recycler view, this will cause that it will stick to the bottom of the recycler view, but since the recycler view (thanks to the guideline) will only grow to 90% of the screen, the button will sit at the bottom of the screen as you want.
It's important to add the following attribute to the recycler view:
app:layout_constrainedHeight="true"
The layout related to the button and recycler view should look something like:
<?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="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/guideline"
app:layout_constraintVertical_bias="0.0"
tools:itemCount="130"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button text"
app:layout_constraintTop_toBottomOf="#+id/list"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.9"/>
</androidx.constraintlayout.widget.ConstraintLayout>
With few items:
With many items:

LinearLayout how to make TextView wrap content with limit?

I want to show 2 TextView in one horizontal LinearLayout, the first TextView is variable and its length may change. The second is always (B). So I want something like this:
|AAA(B)--------|
When A is very long, it should show ellipse in middle:
|AAAA...AAAA(B)|
To solve the problem, I tried wrap content for A:
<LinearLayout orientation="Horizontal" width="match_parent">
<TextView id="#+id/A" width="wrap_content" />
<TextView id="#+id/B" width="wrap_content" />
</LinearLayout>
But there is problem when A is very long, B disappears. It becomes
|AAAAAAAAAAA|
I also tried to add layout_weight:
<LinearLayout orientation="Horizontal" width="match_parent">
<TextView id="#+id/A" width="wrap_content" layout_weight="1" />
<TextView id="#+id/B" width="wrap_content" />
</LinearLayout>
But there is problem when A is very short, there are unwanted space between A and B, It becomes
|AAA-----(B)| ("-" for space)
I don't want space here.
Is there any way to make wrap_content with a max limit?
With a Horizontal LinearLayout you can achieve this using android:layout_weight="1" to the variable TextView A and android:layout_weight="0" to the fixed TextView B. Also the LinearLayout must have android:layout_width="wrap_content".
Xml structure is like below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/A"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:text="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
android:background="#android:color/holo_blue_light"
android:layout_weight="1"
android:singleLine="true" />
<TextView
android:id="#+id/B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:text="B"
android:background="#android:color/holo_red_light"
android:layout_weight="0"
android:singleLine="true"/>
</LinearLayout>
Result when A is Short:
Result when A is Long:
You could use a constraint layout to achieve this.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".presentation.list.CampaignListActivity">
<TextView
android:id="#+id/A"
android:layout_width="0dp"
android:maxLines="1"
android:ellipsize="middle"
android:text="AAAAAAAAAAAAAAAAAAAAAAAA"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="#id/B"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="#+id/B"
android:layout_width="0dp"
android:maxLines="1"
android:ellipsize="middle"
android:text="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="#id/A"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Here You Go !
<androidx.cardview.widget.CardView
android:id="#+id/cardView7"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_A"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="this is a long text field kdsalfj lksadjlfja sdljfljas dlfjlas djflk js dalk and this text is more than 20fj"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/tv_B"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tv_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Less Text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/tv_A"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
And then add below code in your OnCreate method:
if (tvA.text.length > 50) {
tvA.text = "${tvA.text.take(20)}...${tvA.text.takeLast(20)}"
}
You have to add the above code lines somewhere so they get executed as the Activity is lauched (e.g. in OnCreate() Function of the Activity)

Constraint Layout Vertical Align Center - Two Child Views

I have two TextViews, one above the other. I would like the vertical middle of the two TextViews to be at the same position as the vertical middle of the ImageView. (This is so, regardless of the amount of text that may go into either TextView, everything will always look neat, vertically.)
I created what I need perfectly using two LinearLayouts (as the space above the title is the same as the space beneath the description):
But Android Studio was unable to covert it to ConstraintLayout successfully, as it just dumped the TextViews at the bottom of the layout. I've played with a lot of attributes, but could not quite arrive at the desired layout.
My question is similar to this one, except that I am trying to center_vertical align a pair of views rather than a single one - which means I have no view edge to align to the centre of the ImageView/container.
Is it possible to achieve what I'm after with ConstraintLayout? (I expect I may be able to do it with a single RelativeLayout, but I would like to use the layout_constraintDimensionRatio attribute on my ImageView which presumably leave me needing to use ConstraintLayout.)
In case it helps, here's the code for my aforementioned LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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="horizontal">
<ImageView
android:id="#+id/imageView"
android:layout_width="#dimen/resources_list_image_size"
android:layout_height="#dimen/resources_list_image_size"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:layout_gravity="center_vertical"
android:contentDescription="#string/resource_image"
android:scaleType="centerCrop"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="#+id/textViewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/MyTextAppearanceMedium"
tools:text="Title" />
<TextView
android:id="#+id/textViewDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/MyTextAppearanceSmall"
tools:text="Description" />
</LinearLayout>
</LinearLayout>
Update: Solution
Thanks to Ben P's answer, this is my final code:
<?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">
<!-- Add guideline to align imageView to. -->
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.3" />
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="#string/resource_image"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="H,1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="#+id/textViewTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
app:layout_constraintBottom_toTopOf="#id/textViewDescription"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/imageView"
app:layout_constraintTop_toTopOf="parent"
android:textAppearance="#style/MyTextAppearanceMedium"
app:fontFamily="#font/roboto_slab_regular"
app:layout_constraintVertical_chainStyle="packed"
tools:text="#string/enter_title_colon" />
<TextView
android:id="#+id/textViewDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/imageView"
app:layout_constraintTop_toBottomOf="#id/textViewTitle"
app:fontFamily="#font/roboto_slab_light"
android:textAppearance="#style/MyTextAppearanceSmall"
tools:text="Description" />
</androidx.constraintlayout.widget.ConstraintLayout>
It sounds like you could solve this problem by using a packed chain anchored to the top and bottom of the ImageView. You'll also need to use horizontal bias and a constrained width in order to get wrapping to work correctly.
<?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="match_parent">
<View
android:id="#+id/anchor"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="64dp"
android:background="#caf"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="#+id/one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintHorizontal_bias="0"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toTopOf="#id/anchor"
app:layout_constraintStart_toEndOf="#id/anchor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#id/two"/>
<TextView
android:id="#+id/two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_bias="0"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toBottomOf="#id/one"
app:layout_constraintStart_toEndOf="#id/anchor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="#id/anchor"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The important attributes here are:
app:layout_constraintVertical_chainStyle="packed" on the first view, which causes the two textviews to stack right on top of each other
app:layout_constraintHorizontal_bias="0" on both views, which means that when the text is not long enough to reach the edge of the screen it will stick to the edge of the anchor view
app:layout_constrainedWidth="true" on both views, which prevents the textview from ever being wider than its constraints, and so the text wraps to a new line
If you want to use ConstraintLayout you could use something like this:
<?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="match_parent">
<ImageView
android:id="#+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:contentDescription="description"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="#+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="#+id/imageView">
<TextView
android:id="#+id/textViewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Title" />
<TextView
android:id="#+id/textViewDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Description" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
You can use this layout:
<?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/textView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/colorAccent"
android:text="I am 5% of the screen height"
app:layout_constraintBottom_toTopOf="#+id/textView3"
app:layout_constraintEnd_toEndOf="#+id/textView3"
app:layout_constraintHeight_percent="0.05"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="#+id/textView3"
app:layout_constraintTop_toTopOf="#+id/imageView2" />
<TextView
android:id="#+id/textView3"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.15"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="#color/colorPrimary"
android:text="I am 15% of the screen height (And the image is 20% screen size in height) "
app:layout_constraintBottom_toBottomOf="#+id/imageView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView2"
app:layout_constraintTop_toBottomOf="#+id/textView2" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.20"
app:layout_constraintDimensionRatio="1:1"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/rose" />
</android.support.constraint.ConstraintLayout>
It will look like this:
One important thing about this layout:
You can control your aspect ratio (for the image) with app:layout_constraintDimensionRatio="x:y" and by passing "1:1" make it square
And by the way - I am using support library for no reason on this example, you can use androidx

Constraint layout text with button in the bottom

I am doing a constraint layout for screen. And in some small screens is not showing correctly, because the button is over the text.
In the other devices with a bigger screen is showing correctly.
And i don't know how i can solve it.
Thanks
This is my layout (Constraint Layout) with a Linear layout inside.
<?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:background="#color/wf_white">
<LinearLayout
android:id="#+id/ly_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/form_margins"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="parent"
android:background="#color/wf_light_grey">
<TextView
style="#style/wf_text_link"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textAllCaps="true"
android:layout_marginTop="#dimen/form_margins"
android:text="#string/_BIWC_your_agent"/>
<ImageView
android:id="#+id/broker_image"
android:layout_width="#dimen/broker_image_size"
android:layout_height="#dimen/broker_image_size"
android:layout_gravity="center"
android:layout_marginTop="#dimen/text_margin_sides"
android:src="#drawable/img_broker_without_image"
tools:ignore="ContentDescription"/>
<TextView
android:id="#+id/broker_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="#dimen/form_margins_mini"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="#dimen/form_margins_mini"
android:orientation="horizontal">
<ImageView
android:id="#+id/broker_icon_phone"
android:layout_width="#dimen/icons_size_broker"
android:layout_height="#dimen/icons_size_broker"
android:layout_marginTop="#dimen/form_margins_small"
android:layout_marginBottom="#dimen/text_margin_sides"
android:visibility="gone"
android:src="#drawable/icon_action_phone"
tools:ignore="ContentDescription"/>
<ImageView
android:id="#+id/broker_icon_email"
android:layout_width="#dimen/icons_size_broker"
android:layout_height="#dimen/icons_size_broker"
android:layout_marginTop="#dimen/form_margins_small"
android:layout_marginStart="#dimen/icons_margin_broker"
android:layout_marginBottom="#dimen/text_margin_sides"
android:src="#drawable/ic_email"
tools:ignore="ContentDescription"/>
<ImageView
android:id="#+id/broker_icon_location"
android:layout_width="#dimen/icons_size_broker"
android:layout_height="#dimen/icons_size_broker"
android:layout_marginTop="#dimen/form_margins_small"
android:layout_marginStart="#dimen/icons_margin_broker"
android:layout_marginBottom="#dimen/text_margin_sides"
android:visibility="gone"
android:src="#drawable/ic_location"
tools:ignore="ContentDescription"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/broker_introduction_title"
style="#style/wf_text_copy"
android:layout_width="match_parent"
android:gravity="start"
android:layout_marginBottom="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/ly_container"
android:text="#string/_SR_head"/>
<TextView
android:id="#+id/access_code_description"
style="#style/wf_text_hero_copy"
android:layout_width="match_parent"
android:layout_below="#+id/broker_introduction_title"
android:layout_marginLeft=“20dp”
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/broker_introduction_title"
android:gravity="start"
android:text="#string/_BIWC_welcome_message"/>
<Button
android:id="#+id/btn_go_to_register"
style="#style/wf_button_primary"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:descendantFocusability="beforeDescendants"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="#string/_BIWC_create_account"/>
</android.support.constraint.ConstraintLayout>
And also i attach a photo of the problem. Where you can see how the button is over the text, and the user can't read the text.
You should add layout_constraintBottom_toTopOf & layout_constraintTop_toBottomOf.
layout_constraintBottom_toTopOf —> Align the bottom of the desired view
to the top of another.
layout_constraintTop_toBottomOf —> Align the top of the desired view to
the bottom of another.
<TextView
android:id="#+id/access_code_description"
app:layout_constraintBottom_toTopOf"#+id/btn_go_to_register"
android:layout_marginBottom="20dp" //Remove this line
And
<Button
android:id="#+id/btn_go_to_register"
app:layout_constraintTop_toBottomOf="#+id/access_code_description"
FYI
It will be good approach if you use ScrollView ( Where child is TextView).
Set ScrollView as parent layout and ConstraintLayout in it.
ScrollView documentation

How to align buttons next to text that should flow on 2 lines?

So I want to have a title with 2 buttons next to it. These buttons should stick to the left next to the text, and when the text becomes too long, it should flow on 2 lines.
I was able to replicate this by giving the textView a maxwidth, but this causes the textview to take that maxwidth, even if it reflows on 2 lines. Therefore my buttons don't align next to the text anymore.
Like this:
How can I make my textView take the width it needs, not the one I tell it to use as maxWidth?
Here comes the perfectly working answer using ConstraintLayout (as I love this layout).
This is the code.
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.constraint.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/text"
android:layout_marginTop="25dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:maxWidth="300dp">
<TextView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:maxWidth="300dp"
android:text="Some layout is going to be created and whatever I do it won't cross the limit."
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"/>
</android.support.constraint.ConstraintLayout>
<ImageView
android:layout_height="40dp"
android:background="#365987"
android:layout_width="40dp"
android:layout_marginStart="5dp"
android:id="#+id/image"
app:layout_constraintLeft_toRightOf="#+id/text"
app:layout_constraintTop_toTopOf="#+id/text"/>
<ImageView
android:id="#+id/image1"
android:layout_height="40dp"
android:background="#e85f11"
android:layout_width="60dp"
android:layout_marginStart="5dp"
app:layout_constraintBottom_toBottomOf="#+id/image"
app:layout_constraintLeft_toRightOf="#+id/image"
app:layout_constraintTop_toTopOf="#+id/image"/>
</android.support.constraint.ConstraintLayout>
Outputs:
Whatever the text is, it will not cross the maxwidth. And with less width than maxwidth, it's width will be wrap_content.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/tv_male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:text="Male:"
android:textColor="#111111"
android:textSize="12dp" />
<ImageView
android:id="#+id/iv_male"
android:layout_width="#dimen/_42sdp"
android:layout_height="#dimen/_42sdp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:padding="10dp"
android:src="#drawable/block_user" />
<ImageView
android:id="#+id/iv_female"
android:layout_width="#dimen/_42sdp"
android:layout_height="#dimen/_42sdp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:padding="10dp"
android:src="#drawable/blocked_user" />
</LinearLayout>
<TextView
android:id="#+id/tv_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is something Demo Content"
android:layout_marginLeft="#dimen/_15sdp"
android:textColor="#111111"
android:textSize="12dp" />
</LinearLayout>
So you can just add content below the linear layout complete
I Hope it Helps you and you will get your solution.
Try this code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="#+id/zero"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:paddingEnd="100dp"
android:text="Simple textdfddfdf dfdfdfdfdf dfdf Sample Text Sample Text" />
<LinearLayout
android:id="#+id/one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/zero"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/ic_launcher" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/ic_launcher" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
Here, You have to pass android:paddingEnd="100dp". This you can manage from dimens.xml
I hope. This will help full
You should use ConstraintLayout
compile 'com.android.support.constraint:constraint-layout:1.0.2'
Let's take an instance of that Planner part of the image.
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/constraintLayout"
<!-- Other attributes -->
<TextView
android:id="#+id/text"
android:layout_width = "xxxdp"
android:layout_height = "xxxdp"
app:layout_constraintBottom_toBottomOf="#+id/constraintLayout"
app:layout_constraintLeft_toLeftOf="#+id/constraintLayout"
app:layout_constraintTop_toTopOf="#+id/constraintLayout"
<!-- Other attributes --> />
<ImageView
android:id="#+id/image1"
app:layout_constraintBottom_toBottomOf="#+id/text"
app:layout_constraintLeft_toRightOf="#+id/text"
app:layout_constraintTop_toTopOf="#+id/text"
<!-- Other attributes --> />
<ImageView
android:id="#+id/image1"
app:layout_constraintBottom_toBottomOf="#+id/text"
app:layout_constraintLeft_toRightOf="#+id/image1"
app:layout_constraintTop_toTopOf="#+id/image1"
<!-- Other attributes --> />
Definition of Attributes used.
layout_constraintTop_toTopOf — Align the top of the desired view to the top of another.
layout_constraintBottom_toBottomOf — Align the bottom of the desired view to the bottom of another.
layout_constraintLeft_toRightOf — Align the left of the desired view to the right of another.

Categories

Resources