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.
Related
It has been quite some time since I used XML layout for Android. I am struggling with what seems to be very simple thing, yet I cannot find a quick solution.
I have a constraintLayout with an image, title, description and a button:
<?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=".FirstFragment">
<ImageView
android:id="#+id/image_cover"
android:layout_width="200dp"
android:layout_height="300dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:background="#android:color/holo_red_dark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:textColor="#color/black"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/image_cover"
app:layout_constraintTop_toTopOf="#id/image_cover"
tools:text="Title" />
<TextView
android:id="#+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/title"
app:layout_constraintStart_toStartOf="#id/title"
app:layout_constraintBottom_toTopOf="#id/button"
app:layout_constraintEnd_toEndOf="#id/title"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="spread_inside"
android:text="#string/some_very_long_text"/>
<Button
android:id="#+id/button"
app:layout_constraintTop_toBottomOf="#id/description"
app:layout_constraintBottom_toBottomOf="#id/image_cover"
app:layout_constraintStart_toStartOf="#id/title"
android:layout_width="wrap_content"
android:padding="0dp"
android:layout_margin="0dp"
android:background="#color/black"
android:text="Button"
android:layout_height="36dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I want to achieve the following result when the description is short:
Description is aligned to bottom of the title and button aligned to bottom of the image
The following result when description is long:
the button is pushed down/aligned to bottom of the description
I tried to create a chain with either packed (and vertical bias) or spread-inside, however I am only able to achieve either result 1 or 2 and not both.
The idea to do it in XML only, not in Java/Kotlin code.
Since you specify that the button is 39dp in height, you can set a Space widget 39dp from the bottom of the description using a bottom margin. Now set a barrier with a direction = bottom to the Space widget and the description. Now the barrier will float between the bottom of the Space widget and the bottom of the description and will alight on whichever is lower.
Now you can set the top of the button to the bottom of the Barrier and the button will float. The XML is below.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<ImageView
android:id="#+id/image_cover"
android:layout_width="200dp"
android:layout_height="300dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:background="#android:color/holo_red_dark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:textColor="#color/black"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/image_cover"
app:layout_constraintTop_toTopOf="#id/image_cover"
tools:text="Title" />
<TextView
android:id="#+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/some_very_long_text"
app:layout_constraintBottom_toTopOf="#id/button"
app:layout_constraintEnd_toEndOf="#id/title"
app:layout_constraintStart_toStartOf="#id/title"
app:layout_constraintTop_toBottomOf="#id/title"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="spread_inside" />
<Space
android:id="#+id/space"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="36dp"
android:padding="0dp"
app:layout_constraintBottom_toBottomOf="#id/image_cover"
app:layout_constraintStart_toStartOf="#id/title" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_margin="0dp"
android:background="#color/black"
android:padding="0dp"
android:text="Button"
app:layout_constraintStart_toStartOf="#id/title"
app:layout_constraintTop_toBottomOf="#id/barrier" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="description,space" />
</androidx.constraintlayout.widget.ConstraintLayout>
If you don't explicitly know the height of the button, you can create an invisible clone of the button with the same constraints and use the invisible button for the barrier.
Here is another version that also works, but I am not sure why. It doesn't use a Space.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<ImageView
android:id="#+id/image_cover"
android:layout_width="200dp"
android:layout_height="300dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:background="#android:color/holo_red_dark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="Title"
android:textColor="#color/black"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/image_cover"
app:layout_constraintTop_toTopOf="#id/image_cover" />
<TextView
android:id="#+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/some_very_long_text1"
app:layout_constraintBottom_toTopOf="#id/button"
app:layout_constraintEnd_toEndOf="#id/title"
app:layout_constraintStart_toStartOf="#id/title"
app:layout_constraintTop_toBottomOf="#id/title"
app:layout_constraintVertical_bias="0.0"/>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_margin="0dp"
android:background="#color/black"
android:padding="0dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="#id/barrier"
app:layout_constraintStart_toStartOf="#id/title" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="image_cover,description" />
</androidx.constraintlayout.widget.ConstraintLayout>
Update: I was curious about the last layout above. Although it works, I wouldn't use it and I have come to the conclusion that it is a bug since the barrier is located below the button but should be immediately below either the description or the image cover. I am using "androidx.constraintlayout:constraintlayout:2.1.4".
More: I no longer think that this is a bug but a reasonable resolution to a, seemingly, impossible condition: The barrier is positioned to the bottom of the TextView and ImageView. The button's bottom is constrained to the barrier while the TextView's bottom is constrained to top of the button. If the barrier is positioned immediately below its referenced views then the wrap_content height of the TextView cannot be honored since the button will intrude into the TextView height (For the long text.)
What is pictured above could be a compromise. The barrier is still below its referenced views, although much farther below, and all constraints and layout sizes can be honored.
It's hard to tell if this is intentional or not or if it will continue to be the case going forward. I believe that the Space solution is the better solution.
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"
I am using constraint layout as parent, and added multiple child using constraint. There are three views horizontally and I have to apply rounded corner background for two view only, which was achieved by linear layout previously. But with the help of constraint layout, I am not able to achieve this.
How can I achieve this?
ConstraintLayout recently introduced the concept of constrainthelper which can be used to perform an action on a group of views. 'Group', which is used to toggle visibility of multiple view is subclass of this.
A constrainthelper which changes background of multiple views together is not yet a part of the stable release, but soon will be.
Until then, you can achieve a backround as in the example below, where 3 textview share a common background, using an View class:
<?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="#AAA">
<View
android:id="#+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#FFF"
app:layout_constraintBottom_toBottomOf="#+id/textView3"
app:layout_constraintEnd_toEndOf="#+id/textView1"
app:layout_constraintStart_toStartOf="#+id/textView1"
app:layout_constraintTop_toTopOf="#+id/textView1" />
<TextView
android:id="#+id/textView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:padding="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="TextView" />
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintEnd_toEndOf="#+id/textView1"
app:layout_constraintStart_toStartOf="#+id/textView1"
app:layout_constraintTop_toBottomOf="#+id/textView1"
tools:text="TextView" />
<TextView
android:id="#+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintEnd_toEndOf="#+id/textView1"
app:layout_constraintStart_toStartOf="#+id/textView1"
app:layout_constraintTop_toBottomOf="#+id/textView2"
tools:text="TextView" />
</android.support.constraint.ConstraintLayout>
EDIT: A nice blog on what to expect from ConstraintLayout 2.0
You can do it with simple Image View following this steps:
Put a Image view before text views
set Image view's start, top constraint to match first text view
Set Image view's end & bottom constraint to match last text views
This will gone stretch that imageview to a Rectangle defined by top-left of first view and bottom-right of last view.
Note that ImageView must be before text views:
<!--Background Image View-->
<ImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:background="#drawable/lake"
app:layout_goneMarginRight="#dimen/activity_vertical_margin"
<!--Top_LEFT by first view-->
app:layout_constraintStart_toStartOf="heding"
app:layout_constraintTop_toTopOf="#+id/heding"
<!--BOTTOM RIGHT by last view-->
app:layout_constraintEnd_toEndOf="#+id/info"
app:layout_constraintBottom_toBottomOf="#+id/info"
/>
<!--first view-->
<TextView
android:id="#+id/heding"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="Lake Tahoe "
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.05"
app:layout_constraintStart_toEndOf="#+id/thumb"
app:layout_constraintTop_toTopOf="#+id/thumb"
tools:layout_constraintBottom_creator="1"
android:textColor="#FFF"
tools:layout_constraintTop_creator="1" />
<!--last view-->
<TextView
android:id="#+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="LakeTahoe is a large freshwater lake in Sierra Naveda"
android:textSize="15sp"
android:textColor="#FFF"
app:layout_constraintBottom_toBottomOf="#+id/thumb"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.05"
app:layout_constraintStart_toEndOf="#+id/thumb"
app:layout_constraintTop_toBottomOf="#+id/heding"
app:layout_constraintVertical_bias="1.0"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintRight_creator="1"
tools:layout_constraintTop_creator="1" />
Result:
I am trying to create a layout using constraint layout, with an ImageView on top, a button in the ImageView, a TextView below it and then another TextView below it. Following is the xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardElevation="4dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/news_image1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="16:9"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="0dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toTopOf="#+id/news_title1"/>
<ImageButton
android:id="#+id/news_share_button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#drawable/share_button_big"
app:layout_constraintBottom_toBottomOf="#+id/news_image1"
app:layout_constraintRight_toRightOf="#+id/news_image1"
android:layout_marginRight="15dp"
android:layout_marginEnd="15dp"/>
<TextView
android:id="#+id/news_title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_vertical|start"
android:layout_alignParentBottom="true"
android:lines="3"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="#+id/news_image1"
app:layout_constraintBottom_toTopOf="#+id/news_read_more1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textColor="#color/colorPrimaryText"
android:layout_margin="#dimen/news_cell0_textview_margin"
android:textSize="12sp"
android:typeface="monospace" />
<TextView
android:id="#+id/news_read_more1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_vertical|start"
android:layout_alignParentBottom="true"
android:lines="1"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="#+id/news_title1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:textColor="#color/read_more_text_color"
android:text="#string/news_read_more"
android:layout_margin="#dimen/news_cell0_textview_margin"
android:textSize="10sp" />
</android.support.constraint.ConstraintLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
Everything is correct except for a small margin on top of the first ImageView. Whatever I do I cannot get rid of that margin. See the image below.
Please note the margin between the top of the ImageView and the card, that is what is troubling me.
Your news_image, news_title1, and news_read_more1 views form a chain. Apparently, though I cannot find documentation on this, all views in a vertical chain will share vertical margins. In other words, applying a layout_marginTop or layout_marginBottom attribute to one of those three views will wind up applying it to all three of them.
You will have to re-allocate your margins, keeping this in mind.
Edit
Looks like the behavior is a little more sophisticated than I thought. First of all, it looks like it only applies to views with the spread "chain style" (which is the default). Second, it looks like top margin is applied to the view it is specified on as well as all views above that one in the chain, while bottom margin is applied to the view it is specified on as well as all views below that one in the chain. Finally, it appears that margins are cumulative (so if you had 10dp top margin on your bottom view and 20dp top margin on your middle view, the final result would be 30dp on your top view, 30dp on your middle view, and 10dp on your bottom view).
As for how to solve this problem in your specific case? You should be able to use left/right margins without issue. And then probably you should use bottom margin on your top view to space the three views out.
Edit #2
Muthukrishnan's answer made me realize that you could solve this problem by simply removing the chain from your views. If you delete the app:layout_constraintBottom_toTopOf="#+id/news_title1" constraint from your ImageView, that will break the chain and now the vertical margins aren't shared.
Thanks to the great starter by Ben P, I managed to figure out a solution. There are three(plus one weighed) chaining styles available in ConstraintLayout. According to this great tutorial the chaining styles are explained as:
Spread: The views are evenly distributed. E.g.
app:layout_constraintHorizontal_chainStyle=”spread”
app:layout_constraintVertical_chainStyle=”spread”
Spread inside: The first and last view are affixed to the constraints on each end of the chain and the rest are evenly distributed. E.g.
app:layout_constraintHorizontal_chainStyle=”spread_inside”
app:layout_constraintVertical_chainStyle=”spread_inside”
Packed: The views are packed together (after margins are accounted for). You can then adjust the whole chain’s bias (left/right or up/down) by changing the chain’s head view bias. E.g.
app:layout_constraintHorizontal_chainStyle=”packed”
app:layout_constraintVertical_chainStyle=”packed”
Weighted: When the chain is set to either spread or spread inside, you can fill the remaining space by setting one or more views to “match constraints” (0dp). By default, the space is evenly distributed between each view that's set to "match constraints," but you can assign a weight of importance to each view using thelayout_constraintHorizontal_weight and layout_constraintVertical_weight attributes. If you're familiar with layout_weight in a linear layout, this works the same way. So the view with the highest weight value gets the most amount of space; views that have the same weight get the same amount of space.
spread is the default chaining style. I changed it to spread_inside so that the first and last views are affixed to the constraints on each end of the chain(hence obeying the margins provided). The xml now looks like:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardElevation="4dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/news_image1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="16:9"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="0dp"
app:layout_constraintVertical_chainStyle="spread_inside"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toTopOf="#+id/news_title1"/>
<ImageButton
android:id="#+id/news_share_button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#drawable/share_button_big"
app:layout_constraintBottom_toBottomOf="#+id/news_image1"
app:layout_constraintRight_toRightOf="#+id/news_image1"
android:layout_marginRight="15dp"
android:layout_marginEnd="15dp"/>
<TextView
android:id="#+id/news_title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_vertical|start"
android:layout_alignParentBottom="true"
android:lines="3"
android:ellipsize="end"
app:layout_constraintVertical_chainStyle="spread_inside"
app:layout_constraintTop_toBottomOf="#+id/news_image1"
app:layout_constraintBottom_toTopOf="#+id/news_read_more1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textColor="#color/colorPrimaryText"
android:layout_margin="#dimen/news_cell0_textview_margin"
android:textSize="12sp"
android:typeface="monospace" />
<TextView
android:id="#+id/news_read_more1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_vertical|start"
android:layout_alignParentBottom="true"
android:lines="1"
android:ellipsize="end"
app:layout_constraintVertical_chainStyle="spread_inside"
app:layout_constraintTop_toBottomOf="#+id/news_title1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:textColor="#color/read_more_text_color"
android:text="#string/news_read_more"
android:layout_margin="#dimen/news_cell0_textview_margin"
android:textSize="10sp" />
</android.support.constraint.ConstraintLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
Try this, I remove app:layout_constraintTop_toTopOf="parent" in your layout it works
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardElevation="4dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/news_image1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="16:9"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<ImageButton
android:id="#+id/news_share_button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#drawable/ic_menu_share"
app:layout_constraintBottom_toBottomOf="#+id/news_image1"
app:layout_constraintRight_toRightOf="#+id/news_image1"
android:layout_marginRight="15dp"
android:layout_marginEnd="15dp"/>
<AliasTextView
android:id="#+id/news_title1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_vertical|start"
android:layout_alignParentBottom="true"
android:lines="3"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="#+id/news_image1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textColor="#color/colorPrimaryText"
android:layout_margin="#dimen/news_cell0_textview_margin"
android:textSize="12sp"
android:typeface="monospace" />
<TextView
android:id="#+id/news_read_more1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_vertical|start"
android:layout_alignParentBottom="true"
android:lines="1"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="#+id/news_title1"
app:layout_constraintLeft_toLeftOf="parent"
android:textColor="#color/read_more_text_color"
android:text="#string/news_read_more"
android:layout_margin="#dimen/news_cell0_textview_margin"
android:textSize="10sp" />
</android.support.constraint.ConstraintLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
Is there any reason why the following layout_marginBottom is not working?
However, if I use layout_marginTop on the second view it does work well
<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:background="#ade4ad">
<TextView
android:id="#+id/first"
android:layout_width="90dp"
android:layout_height="40dp"
app:layout_marginBottom="10dp"
android:background="#000"/>
<TextView
android:id="#+id/second"
android:layout_width="90dp"
android:layout_height="40dp"
android:background="#fff"
app:layout_constraintTop_toBottomOf="#+id/first"/>
</android.support.constraint.ConstraintLayout>
In order to
android:layout_marginBottom="20dp"
work well, you should use
app:layout_constraintBottom_toBottomOf="parent"
Layout top/bottom margin works only when:
constraints in the same direction need to connect with their next neighbor child, like a unidirectional linked list.
last constraint in the direction must be set.
In your case, you need to set "layout_constraintBottom_toXXXXX" for each view in the chain, and last view set bottom to parent.
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ade4ad">
<TextView
android:id="#+id/first"
android:layout_width="90dp"
android:layout_height="40dp"
app:layout_marginBottom="10dp"
app:layout_constraintBottom_toTopOf="#+id/second"
android:background="#000"/>
<TextView
android:id="#+id/second"
android:layout_width="90dp"
android:layout_height="40dp"
app:layout_marginBottom="10dp"
app:layout_constraintBottom_toTopOf="#+id/third"
android:background="#fff"/>
<TextView
android:id="#+id/third"
android:layout_width="90dp"
android:layout_height="40dp"
android:background="#fff"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
Moreover, reverse dependency is not required except you want "layout_marginTop" works.
you can use that trick, create a space bellow, align to parent bottom
<Space
android:id="#+id/space"
android:layout_width="wrap_content"
android:layout_height="80dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
and align your view on top of the space
app:layout_constraintBottom_toTopOf="#+id/space"
like so
<TextView
android:id="#+id/howNext"
style="#style/white_action_btn_no_border"
android:layout_width="344dp"
android:layout_height="60dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="#string/got_it_next"
app:layout_constraintBottom_toTopOf="#+id/space"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
This is not LinearLayout or RelativeLayout, its ConstraintLayout so you have to give Left, Right, Bottom, Top Constraint to Relevant Layout, in your case You have to give TextView first Bottom_Top Constraint to TextView second. so you can get Margin between Two TextView.
Your layout should be like below.
<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="#ade4ad">
<TextView
android:id="#+id/first"
android:layout_width="90dp"
android:layout_height="40dp"
android:background="#000"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="#+id/second"
android:layout_width="90dp"
android:layout_height="40dp"
android:background="#fff"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="#+id/first"
app:layout_constraintLeft_toLeftOf="#+id/first"
app:layout_constraintRight_toRightOf="#+id/first" />
</android.support.constraint.ConstraintLayout>