I'm animating my recycler view so that it slides side-to-side, exposing a checkbox on the left. The initial animation is great, but when the list is longer than the device height, we get issues with where the two elements (the date and the horizontal rule) are placed. I've recorded two videos to demonstrate the bug in more detail.
Goal: How do I prevent the dates from zig-zagging like that?
http://dai.ly/x6j70qz
http://dai.ly/x6j70yr
Here's the parent recycler view:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_vins"
android:layout_width="0dp"
android:layout_height="0dp"
android:paddingStart="-46dp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
And here's the view holder for each list item:
<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/front_layout_read_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/is_selected_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:button="#drawable/checkbox_selector"
android:checked="false"
android:scaleX="0.5"
android:scaleY="0.5"
app:layout_constraintEnd_toStartOf="#+id/year_make_model_text_view"
app:layout_constraintTop_toTopOf="#+id/year_make_model_text_view" />
<TextView
android:id="#+id/year_make_model_text_view"
style="#style/VinListYearMakeModel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="64dp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toStartOf="#+id/date_text_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1998 Honda Fit blahblahblahblahblahblahblahblahblahblahblah" />
<TextView
android:id="#+id/vin_text_view"
style="#style/VinListVin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
app:layout_constraintStart_toStartOf="#+id/year_make_model_text_view"
app:layout_constraintTop_toBottomOf="#+id/year_make_model_text_view"
tools:text="4JHG2J43HJHG34" />
<TextView
android:id="#+id/date_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/year_make_model_text_view"
tools:text="03/14/18" />
<TextView
android:id="#+id/horizontal_rule"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="24dp"
android:background="#E1E1E1"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/vin_text_view" />
</android.support.constraint.ConstraintLayout>
And here's the gist of the animation that slides the recycler view side-to-side:
val aul = AnimatorUpdateListener {
Log.i("Animated Value", it.animatedValue.toString())
recyclerview_vins.setPadding(it.animatedValue as Int, 0 ,0 ,0)
}
val varl = ValueAnimator.ofInt(0, -137) // These values reversed for opposite animation
varl.duration = 400
varl.addUpdateListener(aul)
varl.start()
I think it may be related to other bugs having to do with the last item in a recycler view list behaving weirdly:
Weird Animation Comes For RecyclerView Last Item
When you using recyclerviews you have to keep in mind that the VIEWS are recycled. this means as you scroll the same view is brought onto screen that previously left the screen.
So if you just scroll without ever sliding anything, it will probably be fine, but the second you animate a view into a different position, that view will stay there for the next active data item that will populate it with it's content.
You need to make sure that as onBindView happens that you are clearing the animations and cleaning up your previous movement of the view. Otherwise, it will stay selected, slide, or whatever else you did to the view.
If you are using animations, you can simply use UIElementThatYouUsed.clearAnimations() or something like that, and it should remove whatever you animated over.
I've had very similar issues in the past when animating recycler view rows, they do remain where you move them unless you clear it.
Related
I have a widget that, no matter what constraints I place upon it and other widgets, including the addition of barriers, always positions itself at the top of the layout.
This is a fairly simple arrangement of two rows of two elements each, not aligned column wise. The first element in each row is a TextView label, the second an input (Spinner).
There is also a lone TextView title above the first row stretching all the way across. By my understanding and previous experience with constraint layout, this shouldn't require a barrier between the rows, and that was my initial version.
This is the design view, where the selected element ("Credentials") is supposed to be in the second row but instead appears above the first row, over top of the title TextView ("PKIX"):
Actual result in the emulator looks much the same. The selected "Credentials" element is the fourth of five elements in the XML layout below. All of the other elements are in the right place.
<?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">
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/bottomborder"
android:text="PKIX"
android:textAlignment="center"
android:layout_marginHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/addsrv_trust_lbl"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:text="Trust"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_trust_spin"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_lbl"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_spin"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:paddingHorizontal="10sp"
android:text="Credentials"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_cred_spin"
app:layout_constraintTop_toBottomOf="#+id/addsrv_trust_lbl"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_cred_spin"
/>
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_cred_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_trust_spin"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
I'm perplexed. The addsrv_cred_lbl TextView ("Credentials") is:
Start aligned with parent.
End aligned with the addsrv_cred_spin spinner, which appears correctly positioned;
this alignment is reciprocated to create a horizontal chain. They are also baseline
aligned.
Top aligned with the bottom of the TextView above it, addsrv_trust_lbl.
This alignment is also reciprocated.
There's no bottom alignment yet (there's another row to go); bottom aligning it with the parent makes no difference unless I bottom align the spinner from the same row, in which case the result goes from bad to worse.
Since this did not work, I tried to use a barrier between the rows. If I use it as a "top", with the second row widgets as the constraint referents, the barrier appears at the top, above the title, regardless of what constraints are used to position it below the first row. Used as a "bottom", with the first row widgets referenced and the second row chained below it (which is more logical), things are a little bit better in that the barrier appears in the right place -- but the "Credentials" widget is still up top.
The design view of this looks exactly the same as the previous one except the barrier is visible below the first row. In the XML, I aslo added optimizationLevel="none" after having read this can help with misbehaving barriers (but it made no difference). There's also a few stylistic elements added back here (such as font size) I removed for brevity before.
<?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"
app:layout_optimizationLevel="none"
>
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/bottomborder"
android:backgroundTint="#color/tbar"
android:text="PKIX"
android:textAlignment="center"
android:textSize="#dimen/addsrv_bigfont"
android:textColor="#color/titleText"
android:layout_marginHorizontal="10sp"
app:layout_constraintBottom_toTopOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:text="Trust"
android:textSize="#dimen/addsrv_fontsz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_trust_spin"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toTopOf="#+id/addsrv_bar1"
app:layout_constraintHorizontal_chainStyle="packed"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBottom_toTopOf="#+id/addsrv_bar1"
/>
<androidx.constraintlayout.widget.Barrier
android:id="#+id/addsrv_bar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="addsrv_trust_lbl,addsrv_trust_spin"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_lbl"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Credentials"
android:textSize="#dimen/addsrv_fontsz"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_cred_spin"
app:layout_constraintEnd_toStartOf="#+id/addsrv_cred_spin"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_bar1" />
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_cred_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_bar1"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Am I correct in observing that some of the constraints on addsrv_cred_lbl are being completely ignored? Doesn't topToBottom mean that the top of the widget is aligned with the bottom of the other? Instead, it seems simply to mean that they will be connected with a squiggly, potentially curved and convoluted line in the design view, and the spacial relation of the two widgets is arbitrary, such that the semantic logic might as well be inverted, "top = bottom, bottom = top", etc.
Please note that I do not want to use absolute values to position anything. If the only way to get this to work is to do that, constraint layout seems a complete waste of time even in this simple case, and I'd rather just stack some liner layouts.
The problem is that Spinner doesn't have a baseline. You were trying to tie it to the baseline of the item inside the Spinner is my guess - ConstraintLayout can't reach children of its children.
You can check it via the design tab with a right click. TextViews will show an option "Show baseline" but the Spinner doesn't.
Also snippet from the doc
Align the text baseline of a view to the text baseline of another
view.
That's what baselines are for, if you want two TextViews connect together so they don't have the height where the text starts messed up.
I think there is a tiny flaw in your approach to the chain. You were setting the top constraint of both elements in each row to the bottom of the previous row(or title in the first row). Even if the Spinner would have a baseline, this would make the label off-centered in relation to the Spinner(slightly higher because the baseline of a text is higher than the actual bottom of the view).
I think the best approach in these types of layouts is to have one guiding element(which is also the element of the chain) that represents the row and let other elements be positioned in relation to it.
<?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">
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="PKIX"
android:textAlignment="center"
android:layout_marginHorizontal="10sp"
app:layout_constraintVertical_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/addsrv_trust_spin"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:text="Trust"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_trust_spin"
app:layout_constraintTop_toTopOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toBottomOf="#+id/addsrv_trust_spin"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_spin"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Credentials"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_cred_spin"
app:layout_constraintTop_toTopOf="#+id/addsrv_cred_spin"
app:layout_constraintBottom_toBottomOf="#+id/addsrv_cred_spin"
/>
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_cred_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
NOTE: I added the last bottom constraint to the parent and "spread" to the chain for demonstration but also know that if you don't have the bottom of the last view constrained to something - it's not a chain.
Working with ConstraintLayout is easy if you obey few simple rules:
Create one chain. That means Views hooking to each other reciprocally, all the way.
Now that you have a working chain, you can manipulate it with layout_constraintVertical_bias and layout_constraintVertical_chainStyle. If changing those does nothing, it means your chain is broken.
hook remaining Views to ones laid out by the chain
every control must have 4 constraints: top, bottom, start and end
do not create competing chains and try to force them into working together.
Spinner cannot have baseline, only TextView and its descendants have it. Spinner is AdapterView, so it can contain whatever you can imagine.
BTW: don't use #+id to refer to existing ids. Plus means creating new id, so if you make a typo it will create new id that refers to nothing instead of error "there's no such id".
Here's an example: top label and Spinners form the main chain and side labels are positioned each to their Spinner:
<?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"
>
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10sp"
android:background=""
android:text="PKIX"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="#id/addsrv_trust_spin"
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"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Trust"
app:layout_constraintBottom_toBottomOf="#id/addsrv_trust_spin"
app:layout_constraintEnd_toStartOf="#id/addsrv_trust_spin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/addsrv_trust_spin"
app:layout_constraintVertical_bias="1.0"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="#id/addsrv_cred_spin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/addsrv_trust_lbl"
app:layout_constraintTop_toBottomOf="#id/addsrv_pkix_title"
app:layout_constraintVertical_bias="0.0"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Credentials"
app:layout_constraintBottom_toBottomOf="#id/addsrv_cred_spin"
app:layout_constraintEnd_toStartOf="#id/addsrv_cred_spin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/addsrv_cred_spin"
app:layout_constraintVertical_bias="1.0"
/>
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/addsrv_cred_lbl"
app:layout_constraintTop_toBottomOf="#id/addsrv_trust_spin"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
I have a recyclerview which contains many items.
But the first item is like an intro screen, it has a button on which user can tap to view more, or user can scroll to view more data.
Something like following.
I want this button to be at the bottom of screen, in small devices it is not visible unless user scrolls the view. So basically layout is taking more height, so user has to scroll to view the complete layout.
I am using constraint layout, and connect it to the bottom of the view.
There are only 2 items in the view, 1 is imageView, which does not have any image, I have only added background color to it, and other is a TextView.
<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">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/Black_Color"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:gravity="center"
android:layout_marginBottom="50dp"
android:textSize="17dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</
in small devices it is not visible unless user scrolls the view - sounds like your image is taking a lot of screen height in small devices so the user must scroll trow the screen
If you want to "disable" the scrolling behavior of your item and put everything inside a screen (without views gong out of the screen and thus making the user scroll) you can change your layout so your item will only occupy the given screen height and not more, and by doing so you will not have this problem on small devices.
something like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.9"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="#tools:sample/backgrounds/scenic" />
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="TextView"
android:textSize="17sp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
The trick was to simply give the image height in percentage like this
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.9"
And now your image will take 90% height on every screen size.
I'm facing an issue when I'm trying to position an edit text under a recycler view, the position of the edit text is at the bottom of the screen, and above the edit text the recycler view is placed, please refer the image
The preview in the android studio shows my desired view, with a scrollable recycler view above the edit text.
My problem is the recycler view should be constrained above the edit text, so the edit text should be always visible on the screen, and it should not be moved down when the number of items in the recycler view increases, ex the no of items in the recycler view is 10 and the no of items visible on the preview is 9 and to see the 10th item I have to scroll, but still the edit text outside the recycler view will be visible on the screen. as a fixed position which is at the bottom of the screen
this is the code
`
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="Select"
android:textSize="17sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
app:layout_constraintBottom_toTopOf="#id/horizontal_barrier"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tv_header"
tools:itemCount="10"
tools:listitem="#layout/item_list" />
<android.support.constraint.Barrier
android:id="#+id/horizontal_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="et" />
<EditText
android:id="#+id/et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="15dp"
android:imeOptions="actionDone"
android:inputType="number"
android:textColor="#color/black_primary_text_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/horizontal_barrier" />
</android.support.constraint.ConstraintLayout>
`
I have been searching for a valid reason for this behavior, but I'm not able to find any solid answer, I have checked multiple solutions like using height as 0dp for recycler view, using layout_constraintHeight_default as a wrap for recycler view, using barriers, Guidelines but nothing worked for me, and I know that this issue can be solved in linear, relative layouts. while I have been observing this behavior in constraint layout, Can someone please Guide or point out to me what am I doing wrong here?
If your edittext is fixed at bottom then you don't need to use barrier.
just give edittext start, end and bottom constraint. So, it will fixed at bottom. Now give recylerview bottom constraint at top of edittext.
<?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">
<TextView
android:id="#+id/tv_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="Select"
android:textSize="17sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
app:layout_constraintBottom_toTopOf="#id/et"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tv_header"
tools:itemCount="10"
tools:listitem="#layout/layout_item_notifications" />
<androidx.appcompat.widget.AppCompatEditText
android:id="#+id/et"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="7dp"
android:layout_marginEnd="15dp"
android:imeOptions="actionDone"
android:inputType="number"
android:text="Hello"
android:background="#color/bg_card"
android:textColor="#color/color_black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I'm a little confused on what your problem is.
The preview in android studio shows my desired view, with scrollable
recycler view above the edit text, but when I run this on a real
device, the edit text is placed below the recycler view
Isn't that what you wanted, the EditText placed below the RecyclerView?
I ran your layout xml (with androidx dependencies instead of android support libraries) and there's nothing wrong with it, It's always sticking EDIT TEXT to the bottom of the screen and doesn't scrolls with Recycler view.
If that's not the behavior you want and want to scroll EDIT TEXT with Recycler view while keeping it at the bottom, then you should wrap EDIT TEXT & RECYCLER VIEW inside NestedScrollView and set recycler view nested scrolling to false.
recyclerView.setNestedScrollingEnabled(false);
The issue was with a parent activity that has a container that was inside a nested scroll view, so when this activity was inflated inside the container the above-mentioned issue was happening. Thanks all for helping out, much appreciated.
I'm trying to center the items of my listview which are a custom view to the center of a constraint layout but they only show at the left side.
I tried setting the horizontal bias of both the constraint and the list view to 50 and to 100 but the listView still doesn't show the Items in the center or anywhere else other than at the start. I tried using layout_centerhorizontal="true" but that does not work either. Bare in mind that the listview is being inflated inside a fragment which is inside a ViewPager.
UPDATE:
I fixed it by wrapping the custom_item xml inside a linear layout which filled the entire screen horizontally and added horizontal center gravity to the item.
Here is my xml:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/parentConstraint_tutor_fragment_loged"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="8dp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<ListView
android:id="#+id/tutorListView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#null"
android:dividerHeight="0dp"
android:listSelector="#android:color/transparent"
android:overScrollMode="never"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And here is the custom_Item:
<?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="323dp"
android:layout_height="68dp"
android:layout_gravity="center_horizontal"
android:background="#drawable/tutor_entry_panel_phones_selector">
<ImageView
android:id="#+id/tutorIcon_cell"
android:layout_width="35dp"
android:layout_height="33dp"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:scaleType="fitCenter"
android:tint="#color/BlueColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/login_tutor_icon" />
<TextView
android:id="#+id/userLogin_nameTextV"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp"
android:layout_marginEnd="22dp"
android:layout_marginRight="22dp"
android:gravity="center"
android:textColor="#color/BlueColor"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/deleteIconPhones"
app:layout_constraintStart_toEndOf="#+id/tutorIcon_cell"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/deleteIconPhones"
android:layout_width="32dp"
android:layout_height="36dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I just need the custom view inside the listview to be in the center of the constraint layout. here is a Screenshot of the current state:
https://ibb.co/88KVQvq
desired state will be with the custom_item in the middle and not in the beginning of the constraintLayout:
https://ibb.co/XbtWJkw
custom_item snapshot:
https://ibb.co/rkDXmGs
Blueprint view of the viewpager in which this fragment is contained (Im trying to get the custom_item centered inside the viewpager's fragment):
https://ibb.co/XVR02Kq
If it is a custom_listView then Do change in the custom_layout.xml - (Whatever you gave the name of the layout) and check it again.
First of all, all these parameters in <ConstraintLayout ...> element are unnecessary:
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
They don't have any meaning. Those parameters are used on elements inside ConstraintLayout, not on Layout itself. Layout fills all available space (in case of activity, it is whole screen), whatever layout are you using. Generally, just use match_parent/wrap_content in width/height, and that's it.
Secondly, based on your screen I cannot say where the ViewPager is located. It looks like ViewPager itself is left aligned in whole activity, but I am not sure. If it is, than it is the reason why everything squashed to left side. You can activate Developer Options on your device, then find and activate option Show Layout Bounds, than you will see on your screen borders of all rendered elements and see if this is the case.
Additionally, your item does not have very proper layout. If you want to chain these three elements, all of them should have all four layout_constraintXxx_toYyyOf elements. You can find it described here. I am not sure that this is the cause of your problem, but certainly is something that might cause the issue. Also, unless you really need to use ConstraintLayout, I would advise to use here LinearLayout, or even just plain text/button with drawableStart and drawableEnd set. It is documented on TextView class (Button is just a subclass of a TextView.)
I have a ViewHolder with the header on top and that header becomes visible in a specific case. In most other cases, the header is set as GONE. The problem is that when a header is set as GONE, its height is still calculated and other views are spread differently (with more space between).
Here is a layout blueprint:
Blueprint explanation:
The header is constrained to top, left and right.
Two views below are in packed chain, constrained to a header on top, ImageView to the right and parent to the left and bottom.
And here is a screenshot from the layout inspector with highlighted header view which is set as GONE:
According to documentation, the header view, when set to GONE should be shrunk to point with constraints from other views still applied to it, but the header should not occupy layout space and affect the height of the ConstraintLayout as it is set as wrap_content.
In this inspector screenshot, it's not clear what happened actually. The header is not visible, a bottom view is obviously constrained to parent top, but the header is still shown in the inspector as full width with specified height.
I'm not sure if this is a bug or I should force ConstraintLayout to re-measure itself.
XML UPDATE:
<?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="wrap_content">
<TextView
android:id="#+id/list_item_step_conversion_tv_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#color/gray_very_light"
android:padding="#dimen/activity_vertical_margin"
android:text="#string/favorites"
android:textColor="#android:color/black"
android:textSize="#dimen/default_text_size"
android:textStyle="bold"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="#+id/list_item_step_conversion_tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#color/gray_dark"
android:textSize="#dimen/medium_text_size"
app:layout_constraintBottom_toTopOf="#+id/list_item_step_conversion_tv_description"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/list_item_step_conversion_iv_favorite"
app:layout_constraintTop_toBottomOf="#+id/list_item_step_conversion_tv_header"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Bicycling - light (10-11.9 mph)"/>
<TextView
android:id="#+id/list_item_step_conversion_tv_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="16dp"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#android:color/black"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="#+id/list_item_step_conversion_tv_title"
app:layout_constraintRight_toLeftOf="#+id/list_item_step_conversion_iv_favorite"
app:layout_constraintTop_toBottomOf="#+id/list_item_step_conversion_tv_title"
tools:text="182 steps/minute"/>
<ImageView
android:id="#+id/list_item_step_conversion_iv_favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_marginRight="24dp"
android:layout_marginTop="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/list_item_step_conversion_tv_header"
app:srcCompat="#drawable/ic_not_liked"/>
</android.support.constraint.ConstraintLayout>
UPDATE 2
After additional observations, this problem occurs only after a call to notifyDataSetChanged in RecyclerView.Adapter. Here is a screenshot of layout state before and after the click to the favorite icon to one of the items.
Screenshots explanation:
On the left side, ViewHolder with visible header view is on position: 2. Items above are displayed correctly.
After click on favorite icon (item with value 242), ViewHolder on position: 1 is the one with visible header view, while the ViewHolder on position: 2 have header view set as GONE. I was expecting for ViewHolder height to decrease and have the same height as ViewHolder on position: 0.
Having in mind that this ViewHolder had header set to VISIBLE in previous state, it might have something with recycling, not sure.
I've solved this issue by calling view.requestLayout()* in the end of my adapter's #getView, after the usual call to binding.executePendingBindings().
*I'm using an old-school Adapter right now, so you should search for the RecyclerView.Adapter's equivalent, probably #onBindViewHolder()
It seems like the layout is actually correct -- disregard the frame of the gone object in the inspector, when a widget is marked as gone we don't lay it out again, as it will simply be skipped (in Studio we do, to provide an easier way to see what's going on, but there's no point doing that on the real device).
Which version of ConstraintLayout are you using? I seem to get the correct behavior here:
After marking the first element to gone:
What worked for me was set the inital visibilty of an object to "gone" and change its visibity via code.
Some like this:
My xml:
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tvMyobject"
style="#style/myStyle"
tools:text="#string/dummy_text"
android:textAlignment="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/anyotherobject"
android:visibility="gone"
/>
My activity:
if (isSomethingToShow) {
tvMyobject.setVisibility(View.VISIBLE);
tvMyobject.setText(R.string.my_string_to_show);
}