Android display a square image view next to two stacked views - android

I am trying to display an image view next a label and a text box. The end result should look like this:
The height of the image view should be the same as whatever space the label and the text box take up and the width should be the same as the height so it is a square.
I have looked at this question to make an image view with equal width and height.
I have also looked at this other question which is similar to mine but using weightSum and layout_weight made the image view take up too much space or become distorted. I have also tried combining answers from the two questions but nothing worked.

You can achieve this very simply using ConstraintLayout:
<?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="#f4f4f4"
tools:context="MainActivity">
<Button
android:id="#+id/button2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.3"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.3"
android:elevation="6dp"
android:layout_margin="8dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintBottom_toBottomOf="#+id/button2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/button2"
android:background="#color/colorAccent"/>
<TextView
android:id="#+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:elevation="6dp"
android:layout_marginLeft="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView2"
app:layout_constraintTop_toTopOf="#+id/imageView2" />
<EditText
android:id="#+id/editText4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:elevation="6dp"
android:ems="10"
android:layout_marginLeft="8dp"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintBottom_toBottomOf="#+id/imageView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
This will look like this
The important attributes:
To make your image square:
app:layout_constraintDimensionRatio="1:1"
To make your views responsive:
app:layout_constraintWidth_percent
app:layout_constraintHeight_percent
Together with:
android:layout_width="0dp"
android:layout_height="0dp"
To make your views over the container so it looks like they are inside it (in this example I have used a button but feel free to use any kind of view)android:elevation="6dp"

Related

Strange constrained_width behaviour with TextView

basically I have an layout as shown in the image. I am using a Guideline to restrict the width of the blue box. This means the ConstraintLayout itself hase full screen width and the blue box has its layout_constraintEnd_toStartOf="#id/guideline".
The blue box is just the background color of the TextView with the text, there aren't any additional containers or anything.
In order for the blue box to respect the constraints for its width calculations I have to set layout_constrainedWidth="true" on the box. As you can see the width is then restricted but the problem is that wrap_content does not work correctly afterwards.
The first box shows that if the text is only a single line, then the behaviour is as expected but if the text spans multiple lines (as in the second box) wrap_content breaks and the box is always "full width" (start of screen until the guideline).
Did somebody experience something similar? Is this a bug or did I misunderstood something. The same broken behaviour can be observed with the grey box on the right side.
I assume this has to do with the breaking behaviour of the TextView but is there a fix or workaround? As far as I know outside of an ConstraintLayout the width would be equal to the text so I assume this is a bug.
Edit XML code:
This is the basice code of one of the "bubbles" and as already mentioned I would like the view to really be as wide as the text.
<?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">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/chat_message_history_receiver_background"
android:fontFamily="#font/nunito_semibold"
android:includeFontPadding="false"
android:paddingStart="15dp"
android:paddingTop="10dp"
android:paddingEnd="15dp"
android:paddingBottom="10dp"
android:textColor="#FFFFFF"
android:textSize="17sp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/guideline"
app:layout_constraintStart_toEndOf="#id/profile_image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
app:layout_constraintWidth_max="wrap"
tools:text="Just testing something, somehowthisisnotworking" />
<app.jooy.messenger.ui.components.generic.profile_image.ProfileImage
android:id="#+id/profile_image"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="10dp"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="1"
app:backgroundColor="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<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.85" />
</androidx.constraintlayout.widget.ConstraintLayout>
And here is the output of this particular xml code:
Try with this, adjust margin and padding as per your need. and change the android:layout_marginBottom of the guide as per your need.
<?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:paddingStart="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#color/colorPrimaryDark"
android:includeFontPadding="false"
android:paddingStart="15dp"
android:paddingTop="10dp"
android:paddingEnd="15dp"
android:paddingBottom="10dp"
android:textColor="#FFFFFF"
android:textSize="17sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guide"
app:layout_constraintWidth_percent=".8"
tools:text="Just testing something, Some how this is not working" />
<app.jooy.messenger.ui.components.generic.profile_image.ProfileImage
android:id="#+id/profile_image"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginStart="5dp"
app:backgroundColor="#color/colorPrimary"
app:layout_constraintStart_toStartOf="#id/text"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/guide"
android:layout_width="0dp"
android:layout_height="0.2dp"
android:layout_marginBottom="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="#id/profile_image"
app:layout_constraintVertical_bias="1"
app:layout_constraintTop_toTopOf="#id/profile_image" />
</androidx.constraintlayout.widget.ConstraintLayout>

ConstraintLayout Prevent Overlap of Top and Bottom Widgets

I am trying to create a layout with three groups of widgets. I want one group constrained to the top, one to the bottom, and one to float in the middle of the space between the two groups. The layout will be used in a fragment, so it could become squashed, especially when the keyboard is shown. I am having trouble figuring out how to prevent overlap of the two groups, while keeping the top and bottom constrained to the top and bottom of the layout.
I thought of several ways to do it, but I couldn't figure out how to implement any of the properly.
Using app:layout_constraintVertical_bias or app:layout_constraintVertical_weight to pull widgets together or spread them apart.
Using one chain, but having breaks in between the groups. I couldn't figure out how to split the chain part way through to allow the different groups to spread out.
Specify a minimum height that is dependent upon the contained widgets. (It will be contained in a ScrollView so it if the height is constrained it will work)
Create groups of packed chains where the packed chains are in a spread chain.
Or is there a better way than these to get what I want?
Note: I would prefer that the top and bottom groups aren't right against the parent layout, but I couldn't figure out how to get those groups to dynamically distance themselves from the parent layout without also spreading the group apart. I want the top and bottom groups close to the parent layout, but not necessarily right against it. It is better to have them right against the parent layout than close to the middle. Ideally I would be able to use app:layout_constraintVertical_bias or app:layout_constraintVertical_weight for this.
Code
<?xml version="1.0" encoding="utf-8"?>
<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" >
<EditText
android:id="#+id/edit_text_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/edit_text_horizontal_margin"
android:layout_marginRight="#dimen/edit_text_horizontal_margin"
android:layout_marginTop="#dimen/edit_text_vertical_margin"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/edit_text_2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:hint="Edit Text 1"
android:selectAllOnFocus="true" />
<EditText
android:id="#+id/edit_text_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/edit_text_horizontal_margin"
android:layout_marginRight="#dimen/edit_text_horizontal_margin"
android:layout_marginTop="#dimen/edit_text_vertical_margin"
android:layout_marginBottom="#dimen/edit_text_vertical_margin"
app:layout_constraintTop_toBottomOf="#id/edit_text_1"
app:layout_constraintBottom_toTopOf="#id/button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:hint="Edit Text 2"
android:selectAllOnFocus="true" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/edit_text_2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:enabled="false"
android:text="Button" />
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/progress_bar_margin"
app:layout_constraintTop_toBottomOf="#id/button"
app:layout_constraintBottom_toTopOf="#id/clickable_text_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:visibility="gone" />
<TextView
android:id="#+id/clickable_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/text_button_horizontal_margin"
android:layout_marginRight="#dimen/text_button_horizontal_margin"
android:layout_marginTop="#dimen/text_button_vertical_margin"
android:layout_marginBottom="#dimen/text_button_vertical_margin"
android:paddingLeft="#dimen/text_button_horizontal_margin"
android:paddingRight="#dimen/text_button_horizontal_margin"
android:paddingTop="#dimen/text_button_vertical_margin"
android:paddingBottom="#dimen/text_button_vertical_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="Clickable Text View"
android:clickable="true"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Images
- - - -
Here is what I have, and how I want it to look. - - - - - Here is the overlapping problem.
for the textview add a constraint top to bottom of the button ie app:layout_constraintTop_toBottomOf="#+id/button". IMO always constraint all 4 angles wherever possible; start top end bottom. In that way when your view is 'squashed', it will still adhere to the constraint set
Here, try 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"
tools:context=".MainActivity">
<EditText
android:id="#+id/emailId"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="36dp"
android:hint="Enter email ID"
android:inputType="textEmailAddress"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="36dp"
android:hint="Enter password"
android:inputType="textPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/emailId" />
<Button
android:id="#+id/signInBtn"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:background="#color/colorAccent"
android:text="Sign in"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/password" />
<TextView
android:id="#+id/analyticsLog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="Click me to create a log"
android:textColor="#android:color/holo_blue_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I believe that you can use Guidelines together with app:layout_constraintHeight_percent to solve your problem.
Consider this 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">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:enabled="false"
android:text="Button"
app:layout_constraintBottom_toTopOf="#+id/guideline3"
app:layout_constraintHeight_percent="0.1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/edit_text_2" />
<EditText
android:id="#+id/edit_text_2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:hint="Edit Text 2"
android:selectAllOnFocus="true"
app:layout_constraintBottom_toTopOf="#id/button"
app:layout_constraintHeight_percent="0.1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/edit_text_1" />
<EditText
android:id="#+id/edit_text_1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:hint="Edit Text 1"
android:selectAllOnFocus="true"
app:layout_constraintBottom_toTopOf="#id/edit_text_2"
app:layout_constraintHeight_percent="0.1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="#id/clickable_text_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/button" />
<TextView
android:id="#+id/clickable_text_view"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:clickable="true"
android:gravity="center"
android:text="Clickable Text View"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHeight_percent="0.1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".35" />
Every view height is equal to 10% of the screen height, that's because of the app:layout_constraintHeight_percent="0.1" attribute. This will solve the overlapping problem for you because you will be able to tell your view what height to be relative to the screen size.
I was using guidelines as well with the app:layout_constraintGuide_percent=".35" attribute to tell the guideline were to be on the screen, by doing that I can constrain different views to it and you won't have to stick your views to the top of bottom of the screen as you mentioned (I would prefer that the top and bottom groups aren't right against the parent layout)
Your layout will look like this:(this is preview image for better understanding guidelines)
for who has same problem. use app:layout_constraintVertical_chainStyle="packed" with app:layout_constraintVertical_bias="1" to attach the view to botom. if use app:layout_constraintVertical_bias="0"the view will attach to top.
<TextView
...
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/button"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintVertical_bias="1"/>

constraintlayout wraps its content width with children match_constraint

I have a simple side bar with 2 buttons vertical chained and i want my side bar to wrap largest button while smaller button expands to match largest one.
Here is a capture where i want "AAA" button to match "VALIDATE" button width
Of course what poped my mind is to use match contraint width for both buttons but when using a wrap_content container this leads to:
my 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:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:background="?attr/colorSurface"
android:padding="#dimen/screen_padding">
<com.google.android.material.button.MaterialButton
android:id="#+id/redo_button"
style="#style/AppStyle.Button.OutlinedButton.SecondaryVariantStroke"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/spacing_normal"
android:text="aaa"
app:layout_constrainedWidth="false"
app:layout_constraintBottom_toTopOf="#+id/validate_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<ImageView
android:layout_width="32dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:background="#drawable/shape_circle_secondary_variant"
android:padding="7dp"
android:src="#drawable/ic_camera"
android:tint="#android:color/white"
app:layout_constraintBottom_toBottomOf="#+id/redo_button"
app:layout_constraintDimensionRatio="h,1:1"
app:layout_constraintEnd_toEndOf="#+id/redo_button"
app:layout_constraintStart_toEndOf="#+id/redo_button"
app:layout_constraintTop_toTopOf="#+id/redo_button"
tools:ignore="ContentDescription" />
<com.google.android.material.button.MaterialButton
android:id="#+id/validate_button"
style="#style/AppStyle.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/global_valid"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/redo_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
If you know which button is going to be wider, then you can make that button wrap_content and constrain the other button to it as follows:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:background="#android:color/darker_gray"
android:padding="16dp">
<Button
android:id="#+id/redo_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="aaa"
app:layout_constrainedWidth="false"
app:layout_constraintBottom_toTopOf="#+id/validate_button"
app:layout_constraintEnd_toEndOf="#+id/validate_button"
app:layout_constraintStart_toStartOf="#+id/validate_button"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<Button
android:id="#+id/validate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Validate"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/redo_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
If this solves your problem, stop here.
Things get a little more complicated if you don't know in advance which button will be wider. (Maybe due to language changes.) In that case, you can check the sizes programmatically and explicitly expand the narrower button. You may consider this less than ideal.
As for accomplishing this in XML, I have looked at this type of problem in the past and the problem always reduces to some kind of circular reference issue. (In fact, this is the problem that you are having with match_constraints widgets in a wrap_content container. The widgets are as wide as the container and the container is as wide as the widgets! What?)
If you don't know which button will be wider, you can create an invisible button that has two lines of text that correspond to the labels of your buttons (assuming single line labels.)
Now that there is a dummy button that is the right width, constrain the sides of your buttons to the sides of the dummy button and make their width match_constraints.
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:background="#android:color/darker_gray"
android:padding="16dp">
<Button
android:id="#+id/dummyForSizing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aaa\nValidate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/redo_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="aaa"
app:layout_constrainedWidth="false"
app:layout_constraintBottom_toTopOf="#+id/validate_button"
app:layout_constraintEnd_toEndOf="#+id/dummyForSizing"
app:layout_constraintStart_toStartOf="#+id/dummyForSizing"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<Button
android:id="#+id/validate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Validate"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/dummyForSizing"
app:layout_constraintStart_toStartOf="#+id/dummyForSizing"
app:layout_constraintTop_toBottomOf="#+id/redo_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
You would, of course, make the dummy button invisible.

ImageView inside ConstraintLayout does not work

I have a problem with correct display of ImageView. I want to display ImageView inside ConstraintLayout. On preview it looks exactly as i need, but when i'm starting it on device it looks completly dirrerent. This layout is places inside recycle view. What is wrong with this code?
<?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"
android:id="#+id/promotionRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="10dp"
android:background="#fff"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp">
<android.support.constraint.ConstraintLayout
android:id="#+id/promotionImageLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintHeight_default="spread"
android:background="#color/colorPrimary">
<ImageView
android:id="#+id/promotionImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#mipmap/ic_start_promotion"
android:background="#mipmap/ic_start_promotion"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHeight_min="150dp" />
<ImageView
android:id="#+id/fadeGradientImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="#drawable/fade_image_background" />
<TextView
android:text="Sample title"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="6dp"
android:textColor="#ffffff"
android:id="#+id/promotionNameTextView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:paddingBottom="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
<TextView
android:id="#+id/promotionDescriptionTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13sp"
android:layout_marginTop="12dp"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:text="Sampe description" />
</LinearLayout>
EDIT: Deep explanation:
I want to create row for RecycleView. Each row have to contains image, title and description. Title have to be in the left bottom corner of the image. Description have to be below the image. After that i have to put gradient (black in the bottom) into the image. Screen with "Preview" is exactly what i need.
EDIT2: Everything with this layout is ok. It is working as expected, i forget that i made some changes in kotlin code... Sory for problem.
First things first, every view should apply the attribute rules of its parent ViewGroup. ConstraintLayout doesn't support match_parent. It supports the 0dp value which means "match constraint". This way the view will expand to fill the constraint bounded space.
Next, ConstraintLayout was created to achieve a flat view hierarchy for better layout performance. So, never nest it inside a LinearLayout as it has the chains feature to get the same behavior in a more flexible way. Plus, you can achieve the structure with a ConstraintLayout at the top level .
Another thing, If you are going to define the same margin in all directions, you can just use layout_margin.
Finally, you have overdraw problems. ConstraintLayout is flexible enough to allow us to position views as backgrounds and help us avoid overlapped backgrounds.
Here's a solution:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/promotionRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="#+id/promotion_image"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/promotion_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="#mipmap/ic_start_promotion"
app:layout_constraintHeight_min="150dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/shadow"
android:layout_width="0dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:background="#drawable/fade_image_background"
app:layout_constraintBottom_toBottomOf="#+id/promotion_image"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="#+id/promotion_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="Sample title"
android:textColor="#android:color/white"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/promotion_image"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="#+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:padding="12dp"
android:text="Sampe description"
android:textSize="13sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/promotion_image" />
</android.support.constraint.ConstraintLayout>
Try it. Hope this helps!
First of all, trying to write more presicely what do you want? Display image view inside layout it's somthing common words. As for your code, beside you don't have any constraints. You have strange view height, for second ImageView:
android:layout_height="match_parent"
It may overlay all other children view, it's very strange parameter.

Text wrapping in Constraint layout

Trying to make a really simple layout for a settings page using ConstraintLayout.
Simple text views to the left one below the other and a switch to the right to the center.
The layout I have works fine for newer devices, but as soon I switch to a Nexus 4 or older, the switch goes below/disappears from the view.
Here is my layout code,
<android.support.constraint.ConstraintLayout
android:id="#+id/locationLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent">
<TextView
android:id="#+id/locationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="#string/location_title"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="16sp"/>
<TextView
android:id="#+id/locationDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/location_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationTitle"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="#id/locationTitle"
app:layout_constraintRight_toLeftOf="#id/guidelineLocationLayout"
android:textSize="12sp"
/>
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="parent"/>
<View
android:id="#+id/viewLocationLayout"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#d6d6d6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationDescription"/>
<android.support.constraint.Guideline
android:id="#+id/guidelineLocationLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="48dp" />
</android.support.constraint.ConstraintLayout>
And here are how the constraints look like for the Pixel 2XL,
Here is how they look on a smaller device,
I have used 0dp width for the long description and defined left and right constraints, anything else I could do?
You can use barriers instead of guidelines because a Barrier references multiple widgets as input, and creates a virtual guideline based on the most extreme widget on the specified side.
According to the Documentation
Similar to a guideline, a barrier is an invisible line that you can
constrain views to. Except a barrier does not define its own position;
instead, the barrier position moves based on the position of views
contained within it. This is useful when you want to constrain a view
to the a set of views rather than to one specific view.
Hope this helps you. I've used barrier instead of guideline.
<?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/locationLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent">
<TextView
android:id="#+id/locationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Save location to the song"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/locationDescription"
android:layout_width="261dp"
android:layout_height="32dp"
android:text="Your location is only requested when a new song is identified. Location details are never sent to the server"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationTitle" />
<android.support.constraint.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="locationDescription,locationTitle" />
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="41dp"
android:layout_height="26dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/barrier"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/viewLocationLayout"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#d6d6d6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationDescription" />
</android.support.constraint.ConstraintLayout>
You need to change the constraints of the switch like this
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
You are constraining the bottom of the switch to the top of the parent and top of the switch to the bottom of the parent. You have to change it to layout_constraintTop_toTopOf and layout_constraintBottom_toBottomOf

Categories

Resources