I have a ScrollView which has a ConstraintLayout.
Inside the ConstraintLayout I want to position a View to the bottom of a Barrier.
The Barrier itself has constraints: a Guideline(it can be also a view with height half of parent) which is half of the ConstraintLayout and a TextView.
The issue here is that the ConstraintLayout will expand even more (adds more scrollable area) because of the half of screen percentage calculation.
<?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">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="100dp"
android:layout_height="200dp"
android:background="#39537A4B"
android:fillViewport="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="#+id/topHalf"
android:layout_width="10dp"
android:layout_height="0dp"
android:background="#99B146B8"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<View
android:id="#+id/bottomHalf"
android:layout_width="10dp"
android:layout_height="0dp"
android:background="#99B89F46"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Do smth \n\n\n\n\n\n\nasdasda"
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="horizontal"
app:layout_constraintGuide_percent="0.5" />
<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="guideline, text" />
<View
android:id="#+id/view"
android:layout_width="60dp"
android:layout_height="40dp"
android:background="#651F7878"
app:layout_constraintStart_toStartOf="#id/barrier"
app:layout_constraintTop_toBottomOf="#id/barrier" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Try changing the Barrier constraints to:
app:constraint_referenced_ids="text"
And you understand that Barrier brakes the calculations.
I know how to solve this layout issue from java, I want a solution from xml. It can be this is a bug on ConstraintLayout
This behavior is odd and is definitely related to the barrier and a wrap_content ConstraintLayout Here is a simplified layout that showcases the behavior.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<View
android:id="#+id/redBox"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#android:color/holo_red_light"
android:textAppearance="#style/TextAppearance.AppCompat.Body2"
app:layout_constraintEnd_toEndOf="parent"
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="horizontal"
app:layout_constraintGuide_percent=".5" />
<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="redBox,guideline"/>
</androidx.constraintlayout.widget.ConstraintLayout>
With the above layout, the following is what is displayed. Although the ConstraintLayout is wrap_content, it expands to twice the height of the red box.
If we remove the red box or the guideline from the barrier, the layout behaves:
The height of the ConstraintLayout can be varied by changing the location of the guideline. Here it is with the guideline set at 30%:
The expected behavior, IMO, is that the ConstraintLayout would size itself based upon the heights of its child views, here just the red box, and the guideline would be set accordingly. That is clearly not what is happening.
Maybe someone can figure out an XML work-around using the simplified layout. I didn't see a similar issue reported from a cursory search, so it may be worth reporting.
(Using ConstraintLayout version 2.1.0)
Related
I am using a ConstraintLayout and I want to make the following constraint:
I have made it using a lot of margin and also using a guideline. I would like to know which situation is more efficient:
Situation 1 using layout_marginEnd(230dp):
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintTop_toTopOf="#id/view1"
app:layout_constraintBottom_toBottomOf="#id/view1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/view1"
android:layout_marginEnd="230dp"/>
<View
android:id="#+id/view1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#color/blue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.05"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Situation 2 using GuideLine:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintTop_toTopOf="#id/view1"
app:layout_constraintBottom_toBottomOf="#id/view1"
app:layout_constraintEnd_toStartOf="#id/guideline"
app:layout_constraintStart_toEndOf="#id/view1"
/>
<View
android:id="#+id/view1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#color/blue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.05"/>
<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.44" />
</androidx.constraintlayout.widget.ConstraintLayout>
Which situation is better for performance and it will be better to use, situation one with almost 250dp of layout_marginEnd or situation 2 with a vertical guideline?
Thanks for the help.
I suggest that Margin and guideline are just for critical conditions
If you want exact position like in pic then just remove end end constraint from textview and make your textview wrap content thats all
Hey I am working in constraint layout with recylerview. My bottom item is cut in the screen. I read this stack overflow post. I don't want to use relative layout or linear layout. Can someone guide me how to fix this in constraint layout.
abc.xml
<?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">
<androidx.appcompat.widget.SearchView
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
app:closeIcon="#drawable/ic_cancel"
app:layout_constraintBottom_toTopOf="#+id/exploreScroll"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintVertical_bias="0.0" />
<HorizontalScrollView
android:id="#+id/exploreScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:scrollbars="none"
app:layout_constraintBottom_toTopOf="#+id/exploreList"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/searchView">
<com.google.android.material.chip.ChipGroup
android:id="#+id/exploreChips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:chipSpacingHorizontal="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:singleLine="true"
app:singleSelection="true" />
</HorizontalScrollView>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/exploreList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:paddingTop="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/exploreScroll" />
</androidx.constraintlayout.widget.ConstraintLayout>
My view cut from
UPDATE
#Zain after your suggestion i tried in my xml any my HorizontalScrollView is going behind my RV. I am adding my blueprint and you can see clearly that, HorizontalScrollView is going behind. After removing app:layout_constraintBottom_toTopOf="#+id/exploreList" from the HorizontalScrollView.
2nd suggestion try
Disclaimer Using a wrap_content height with vertical RecyclerView
can have impact on performance in terms of recycling views; specially
if the height is going to change frequently. Check this article
for more illustration.
So, the first step is to designate the RecyclerView height or to constraint it; from the constraints you want it to expand to the bottom; so use 0dp for that. But in order to make the minimum height to wrap content of the RecyclerView (in case that the items don't exceed the screen height); you can set the default height constraint to wrap with app:layout_constraintHeight_default="wrap" constraint.
Then remove app:layout_constraintBottom_toTopOf="#+id/exploreList" from the HorizontalScrollView, this actually made the bottom item of the RV hide (your main issue); because it is an over-constraint; the HorizontalScrollView tends to push the RV to the bottom while the RV tends to push the HorizontalScrollView to the top.
This will solve the main issue; but when the items are fully accommodated by the screen (no scrolling in the RV), then it will be biased in the middle; to fix this use the bias with app:layout_constraintVertical_bias="0.0" to be biased to the top.
Adding this in place into the 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">
<androidx.appcompat.widget.SearchView
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
app:closeIcon="#drawable/ic_cancel"
app:layout_constraintBottom_toTopOf="#+id/exploreScroll"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed" />
<HorizontalScrollView
android:id="#+id/exploreScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/searchView">
<com.google.android.material.chip.ChipGroup
android:id="#+id/exploreChips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:chipSpacingHorizontal="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:singleLine="true"
app:singleSelection="true" />
</HorizontalScrollView>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/exploreList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="20dp"
android:paddingTop="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_default="wrap"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/exploreScroll" />
</androidx.constraintlayout.widget.ConstraintLayout>
I have an imageview that I will place different images.
This images can have many sizes like 200x200 200x400 400x200...
Above imageview I have an adview and below this imageview I need 4 buttons.
The problem is, I'd like the image be below adview, but stop jumping position when ad loads. It goes down when an ad loads, I'd to stop this move, make the image fix, but above the adview.
My xml:
<?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">
<LinearLayout
android:id="#+id/ad_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="49dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="#+id/imageView1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.gms.ads.AdView xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
ads:adSize="SMART_BANNER"
ads:adUnitId="ca-app-pub-xxx/xxx">
</com.google.android.gms.ads.AdView>
</LinearLayout>
<ImageView
android:id="#+id/imageView1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:layout_marginTop="89dp"
android:contentDescription="img"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/ad_view" />
<TextView
android:id="#+id/a1"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.207"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.447" />
<TextView
android:id="#+id/a2"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.806"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.447" />
<TextView
android:id="#+id/a3"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.207"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.582" />
<TextView
android:id="#+id/a4"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.806"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.582" />
</androidx.constraintlayout.widget.ConstraintLayout>
TL;DR
The fastest solution would be to change your ad view android:layout_height="wrap_content" into android:layout_height="fixed size" so your ad view will have a single height and won't change because of its wrap_content attribute (If your ad view is not loaded you can think of wrap_content as height of 0 and only after its loaded it will have height, thus the layout jump).
Why is it bad?
your layout won't be responsive.
How to fix?
Read the answer below.
Long but better answer:
You can use guidelines with app:layout_constraintGuide_percent=".2" to tell your guideline to be at the top of your screen (80%) and constraint your ad view to your guideline - this way your layout will won't jump (it will have its space to load into).
Another thing, different phones got different screen size, in your layout you are using fixed size on your view (fixed size is 50dp for example) and the result is that what may look good on one screen (your android studio preview screen) will not look good on another screen (your actual phone).
Here is an example to achieve your wanted look using ConstaintLayout:
<?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">
<Button
android:id="#+id/adView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintHeight_percent="0.08"
android:text="add view"
app:layout_constraintBottom_toTopOf="#+id/guideline"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#drawable/ic_launcher_background"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/guideline"
app:layout_constraintWidth_percent="0.6" />
<TextView
android:id="#+id/a1"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a1"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintWidth_percent="0.25"
app:layout_constraintBottom_toTopOf="#+id/a3"
app:layout_constraintEnd_toStartOf="#+id/a2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="#+id/imageView1"
app:layout_constraintTop_toBottomOf="#+id/imageView1" />
<TextView
android:id="#+id/a2"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a2"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintWidth_percent="0.25"
app:layout_constraintBottom_toBottomOf="#+id/a1"
app:layout_constraintEnd_toEndOf="#+id/imageView1"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/a1"
app:layout_constraintTop_toTopOf="#+id/a1"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/a3"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a3"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/a1"
app:layout_constraintStart_toStartOf="#+id/a1"
app:layout_constraintTop_toBottomOf="#+id/a1" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".2" />
<TextView
android:id="#+id/a4"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a4"
app:layout_constraintBottom_toBottomOf="#+id/a3"
app:layout_constraintEnd_toEndOf="#+id/a2"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintStart_toStartOf="#+id/a2"
app:layout_constraintTop_toTopOf="#+id/a3" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here is how it will look (I am adding a screenshot from the layout editor for better understanding ConstaintLayout)
Some extra information:
ConstraintLayout is not meant to have nested view groups (in your case you have LinearLayout inside constraintlayout).
ConstraintLayout allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It's similar to RelativeLayout in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use with Android Studio's Layout Editor.
You can Use ConstraintLayout with guidelines and Chains to support different screen sizes, you won't have to use fixed sizes on your views and you will be able to use a single layout to support different screen size.
Give the adview or it's surrounding layout a minimum height equal to the smart banner content in your case likely 90px.
It's jumping because with no content loaded your wrap_content height = 0, then it gets a new height of x, so your imageview shifts down x.
I've been experimenting with ConstraintLayout, is there a way to set the max width of a view to a percentage of the parent (and a height of match constraint and dimension ratio of 1:1)?
Here is the code without using max width:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:id="#+id/frameLayout3"
android:layout_width="0dp"
android:layout_height="259dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:background="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#android:drawable/ic_menu_add"
app:layout_constraintBottom_toBottomOf="#+id/frameLayout3"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3"/>
</android.support.constraint.ConstraintLayout>
This is the result:
Tablet:
Phone:
I achieved the max width percentage using two attributes:
app:layout_constraintWidth_max="wrap"
app:layout_constraintWidth_percent="0.4"
Example:
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Helo world"
android:textAlignment="viewStart"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="wrap"
app:layout_constraintWidth_percent="0.4" />
The text width will increase to 40% of parent and then wrap if the content exceeds that.
If I'm understanding your problem right then You're almost there. I think you're giving frameLayout static height that's why it is not giving the appropriate result on tablet.. because you set the height according to phone preview. What you need to do is make the height of frameLayout relative to imageView.. so when imageView grows in size the frameLayout also grows with it.
I think you should do something like this
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#android:drawable/ic_menu_add"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3" />
<FrameLayout
android:id="#+id/frameLayoutTwo"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/black"
app:layout_constraintBottom_toBottomOf="#+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
I checked and this gives the same result in phone and tablet. Correct me if I misunderstood your problem.
No, there is not. I think we should file a feature request. I am pretty sure that PercentRelativeLayout also does not have this feature. (This answer is accurate for ConstraintLayout 1.1)
You can set a LinearLayout or other ViewGroup as exact percent width and place your wrap_content view inside this layout.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_place_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- This LinearLayout will have exact 80% of parent width-->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.8">
<!-- This MaterialCardView will get a wrap_content width,
with a max width of his parent LinearLayout, which is 80% -->
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/half_activity_horizontal_margin"
android:layout_marginTop="#dimen/half_activity_vertical_margin"
android:layout_marginEnd="#dimen/half_activity_horizontal_margin"
android:layout_marginBottom="#dimen/half_activity_vertical_margin"
android:backgroundTint="?attr/colorPrimary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:paddingStart="#dimen/half_activity_horizontal_margin"
android:paddingEnd="#dimen/half_activity_horizontal_margin"
android:text="Lorem ipsum"
android:textAppearance="?attr/textAppearanceCaption" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I used constraintLayout and layout_constraintDimensionRatio="1:1"
(width is wrap_content, height is 0dp (match_constraint))
As a result, I expected width and height to be 1:1, but it's not working.
What is wrong?
I attached code and screenshot.
<?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/t1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:background="#android:color/holo_blue_bright"
android:gravity="center"
android:text="Hello World!11"
app:layout_constraintDimensionRatio="1:1" />
</android.support.constraint.ConstraintLayout>
screenshot
I quote android developer site about Constraintlayout.
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html#DimensionConstraints
Ratio :: You can also define one dimension of a widget as a ratio of
the other one. In order to do that, you need to have at least one
constrained dimension be set to 0dp (i.e., MATCH_CONSTRAINT), and set
the attribute layout_constraintDimentionRatio to a given ratio. For
example:
<Button android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1" />
will set the height of the button to be the same as its width.
but it was not working.
You forget to add your constraints
<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/t1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="#android:color/holo_blue_bright"
android:gravity="center"
android:text="Hello World!11"
app:layout_constraintDimensionRatio="1" />
</android.support.constraint.ConstraintLayout>
0dp is only applied to the child views of ConstraintLayout.
Any view should apply the attribute rules of its parent.
As off version 1.1.0 this has changed.
You can now define:
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintDimensionRatio="W,1:1"
app:layout_constraintDimensionRatio="H,1:1"
Check the link below to find all the documentation regarding DimensionConstraints:
Link to the docs
In my case I have a problem like i have to fill my layout inside container with A4 size paper ratio.
Problem
I am getting A4 size resume pages as images from backend so i have to append those images in Viewpager in which i am using ImageView to display those images.
Solution
I went through Constraint layout document in which Ratio section is there. So i can use layout_constraintDimensionRatio for solving my problem.
So my xml that is used to Display the whole Layout is following, in my case i have used app:layout_constraintDimensionRatio="1:1.27" as with:height ratio but the actual ratio is app:layout_constraintDimensionRatio="1:1.41"
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/orange">
<!-- divider line which i used as restricting my A4 size container height-->
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/headline_title_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias=".85"/>
<!-- A4 size Image View-->
<ImageView
android:id="#+id/resumeContainer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="16dp"
android:layout_marginRight="12dp"
android:layout_marginBottom="16dp"
android:background="#color/green"
android:text="#string/change"
android:src="#drawable/banner"
app:layout_constraintBottom_toTopOf="#id/divider"
app:layout_constraintDimensionRatio="1:1.27"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<!-- for Bottom two buttons -->
<com.bold.job.utils.CustomButton
android:id="#+id/preview"
style="#style/tertiaryButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:onClick="preview"
android:text="#string/preview_resume"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/divider"
/>
<android.support.constraint.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<com.bold.job.utils.CustomButton
android:id="#+id/preview2"
style="#style/tertiaryButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:onClick="preview"
app:layout_constraintLeft_toRightOf="#id/guideline"
app:layout_constraintRight_toRightOf="parent"
android:text="#string/preview_resume"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/divider"
/>
</android.support.constraint.ConstraintLayout>
Please notice the last line, adding constraints around the edges makes the constraint work.
You can also use the design view in Studio, and drag and drop the constraints between objects.
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Available chats" />
<ListView
android:id="#+id/listChats"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/textView"/>