I have a very simple RecyclerView that loads data from a Firestore database. There are no issues with the code to get the data but the RecyclerView does not show anything when I set the view holder to wrap_content. However it does load the data when I set it to match_parent. I have tried using
firestoreRecycler.setHasFixedSize(true)
but it doesnt do anything, the data is just not shown at all when I use wrap_content and using match_parent makes it so that i have to scroll a lot to see a single item.
Here is the code for the RecyclerView row layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp">
<TextView
android:id="#+id/listOfficeName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/listOfficeAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/listOfficeName" />
</androidx.constraintlayout.widget.ConstraintLayout>
There is nothing relevant about the rest, there is functionality only for the RecyclerView that I got from a tutorial in which wrap_content actually worked.
Thanks in advance!
The distance of the recyclerview used in ConstraintLayout as a view is disabled because it does not fit the logic of ConstraintLayout. So edit the height value of recyclerview as follows:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp" />
height = 0dp
Related
This should be similar to an iOS tableview footer, also seen in various websites (sticky-footer).
I want to achieve the following:
A is a RecyclerView with variable number of rows.
When A is smaller than screen (or parent) size, B (footer) should be placed bellow the last row.
When A + B are bigger than screen size, then B becomes fixed at the bottom and A content is scrollable.
We are currently performing this with onMeasure functions that calculate all components heights in order to resize A accordingly.
I was wondering if there is an easier way to do it, maybe with ConstraintLayout.
Put A and B in a vertical packed chain with a bias of 0 to align it to the top. You also need to set app:layout_constrainedHeight="true" for the RecyclerView so that its constraints are taken into account when it gets too big to fit them (parent's height remains match_parent in this case):
<?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.recyclerview.widget.RecyclerView
android:id="#+id/A"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/B" />
<TextView
android:id="#+id/B"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Footer"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/A"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
The above solution does not seem to work on Constraintlayout:2.0.0-beta2, looks like a bug introduced in that version. Works on 2.0.0-beta1 and 1.1.3.
Another way would be to set parent's height to wrap_content and then you can use the default chainstyle and remove the bias:
<?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="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/A"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/B" />
<TextView
android:id="#+id/B"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Footer"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/A"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This solution works on all versions.
Just try ConstraintLayout, this should very well be possible, just fix Bs height and constrain it to the bottom and A and turn the bias up to top.
I have a screen that contains 2 views, a map(top) and a recycler(bottom)
The rules are simple .
the recycler view is allowed to extend up to the middle of the screen, if more space is needed then it should scroll instead, the map will occupy the rest of the space, Of course if the recycler has less elements then it should shrink leaving more space for the map ..
I am trying to achieve this using constraint layout, also I am trying to avoid solutions that involved calculations .
Check image below for more information on what I am trying to achieve :
Here is my code
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
tools:context="com.qmic.itraffic.ui.activities.crowdsourcing.CrowdSourceReportingDetailsActivity">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/halfScreenGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/categories"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="#color/manatee"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/categories"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/halfScreenGuideline" />
</androidx.constraintlayout.widget.ConstraintLayout>
My Question is can I achieve this behaviour using xml only (constraint layout )?or I would need to do calculation ?
Could you please try the following code in your recyclerview xml
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
Change the height to wrap content and add the second the line. This way the recyclerview should have the height same as its content but never exceeds the guideline/contraint.
The answer by Akhil Soman is correct but missing one thing
app:layout_constraintVertical_bias="1.0"
Without it the RecyclerView was floating above the bottom of the screen leaving an empty space .
for reference here is the complete answer
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/categories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
android:clipToPadding="false"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/halfScreenGuideline"
app:layout_constraintVertical_bias="1.0" />
Also the suggestion by the Jaymin seems interesting and can fix this problem, but I haven't applied it because I already used Akil solution .
I have a layout with two views that should behave like this:
On top is an EditText that should grow (and shrink) dynamically.
Right underneath is another view. The EditText grows until the other
View reaches the bottom of the parent layout, then it stops growing
and becomes scrollable instead.
An image that illustrates the desired behaviour can be found here (cannot upload it) :
The problem, it seems, is to limit the EditText to a certain height so it won't push the other View off the bottom of the screen. Or to give the other View an attribute that it always stays on screen, I don't know.
I tried several different approaches to solve it via xml. The one I attach simply works by limiting the number of lines in the EditText - which I would later have to change programmatically depending on device's resolution. So that's not really desirable.
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/tripNotes_toolbar_layout"
layout="#layout/toolbar_details" />
<android.support.constraint.ConstraintLayout
android:id="#+id/tripNotes_constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="#style/CardStyle"
android:layout_gravity="top"
android:layout_marginLeft="#dimen/card_outer_margin_left"
android:layout_marginRight="#dimen/card_outer_margin_left">
<EditText
android:id="#+id/tripNotes_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="#null"
android:hint="Put your notes here"
android:inputType="textMultiLine|textCapWords"
android:lines="12"
android:maxLength="1000"
android:maxLines="12"
android:minLines="1"
android:textColor="#color/grey_12"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/tripNotes_pictureGrid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tripNotes_editText"
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_weight="1"/>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
The actual result is that other View is pushed off screen if number of lines in EditText is not limited, but I would prefer a solution with alyout attributes.
You can wrap the edit text into a scroll view
Your layout would look like this :
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/tripNotes_toolbar_layout"
layout="#layout/toolbar_details" />
<android.support.constraint.ConstraintLayout
android:id="#+id/tripNotes_constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/CardStyle"
android:layout_gravity="top"
android:layout_marginLeft="#dimen/card_outer_margin_left"
android:layout_marginRight="#dimen/card_outer_margin_left">
<ScrollView
android:id="#+id/tripNotes_editTextContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/tripNotes_pictureGrid">
<EditText
android:id="#+id/tripNotes_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="#null"
android:hint="Put your notes here"
android:inputType="textMultiLine|textCapWords"
android:textColor="#color/grey_12" />
</ScrollView>
<View
android:id="#+id/tripNotes_pictureGrid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/tripNotes_editTextContainer"
app:layout_constraintTop_toBottomOf="#id/tripNotes_editTextContainer"
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_weight="1"/>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
Changes made :
Constraint layout height changed from match_parent to wrap_content
Edit text
removed app:layout_constraintTop_toTopOf="parent" (no longer needed since it is wrapped in scrollview)
removed maxLines, lines, minLines and maxLength attributes
Added ScrollView
Bottom View :
changed
app:layout_constraintStart_toStartOf="parent" to app:layout_constraintStart_toEndOf="#id/tripNotes_editTextContainer"
changed
app:layout_constraintTop_toBottomOf="#id/tripNotes_editText" to app:layout_constraintTop_toBottomOf="#id/tripNotes_editTextContainer"
The bottom view will be just under the Edittext and will go down until the bottom of the screen and the EditText will become scrollable
I'm trying to have a RecylerView with a varying item count wrap its height to its items, but to never have it exceed its constraints. I believe I've set this up properly. Here's a simple XML for such a layout:
<!-- container.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="600dp"
android:background="#colors/blue">
<View
android:id="#+id/bottomGreenView"
android:layout_width="0dp"
android:layout_height="100dp"
android:background="#colors/green"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#colors/red"
app:layout_constrainedHeight="true"
app:layout_constraintHeight_max="0dp"
app:layout_constraintVertical_bias="0"
app:layout_constraintBottom_toTopOf="#id/bottomGreenView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:itemCount="1"
tools:listitem="#layout/test_list_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- test_list_item.xml -->
<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="wrap_content"
android:background="#colors/white">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="List item here"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Note that the container is blue, the RecyclerView is red and the bottom view that should not be exceeded is green. And since the list items are white, there is no spacing between the items and the RecyclerView should wrap around the list items, the red background of the RecyclerView should never be seen. However, you can clearly see here that the RecyclerView is in fact seen and is much taller than it should be:
What I'm trying to achieve is this, where the RecyclerView properly wraps its content:
Interestingly, this does actually work as expected if I have the TextView's width wrap_content and remove its end-to-end constraint (the latter only so that it's not being centered horizontally). However, in my actual app I need these constraints as I also have content on the right side that I don't want to potentially overlap with long texts.
To me, this feels like an issue in either ConstraintLayout or RecyclerView (or both in tandem), so I've also filed an issue in the bug tracker. But if it is not, then I'd be happy to hear what you all have to say
I'm making memory game in Android.
I decided to use GridView with adapter, which inflates image inside every of cell.
Problem is that images in first row get cut of while 3D rotating around y axis,
like this:
This does not happen with images in last row.
Only way I managed to avoid this behaviour was to increase padding for each image, but that changes by layout too much. I also tried adding top padding and/or margin to GridView, but that did not help.
Is there any way to make images in first rotate without this issue?
Here is my layout code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
tools:context="com.example.alen.matchinggameaddiko.activities.GameActivity">
<ImageView
android:id="#+id/imageView"
android:layout_width="150dp"
android:layout_height="0px"
android:layout_marginLeft="26dp"
android:layout_marginTop="0dp"
android:src="#drawable/addiko_logo_white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<GridView
android:id="#+id/grid_game"
android:layout_width="0px"
android:layout_height="0px"
android:layout_marginBottom="10dp"
android:layout_marginEnd="#dimen/gridImagesMarginLeft"
android:layout_marginStart="#dimen/gridImagesMarginRight"
android:numColumns="4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView" />
</android.support.constraint.ConstraintLayout>
Thanks!
Have you tried ViewGroup.setClipChildren(false)? The rotation looks like it's leaving the ViewGroup's bounds.
In a RecyclerView that I had the same issue, what worked was adding android:clipChildren="false" in the RecyclerView and android:clipToPadding="false" in the root layout of the adapter of the RecyclerView.