Is it possible to animate RecyclerView height, or otherwise change it programmatically? For example, if I have a large header view that is sometimes visible, and other times not - I would want to animate the RecyclerView height to fill the screen when the header is animated out.
Changing LayoutParams.height does not seem to work. LinearLayout animateLayoutChanges causes a crash.
<LinearLayout>
<RelativeLayout (header)>
<RecyclerView>
</LinearLayout>
I want to make the RelativeLayout animate out the top (translationY) and then at the same time make the recyclerview animate to be taller to fit.
There are possible options to tackle this:
Follow suggestion from #Ari to start animation and on every animation tick update layout params. This will make an effect of recyclerview changing its size. However, this is a horrible idea from performance stand point. Layout and Measure process is quite expensive, so generally you want to minimize calls which trigger layout. Call to setLayoutParams will trigger layout & measure process for RecyclerView + all its children which means that on every single frame you will do really expensive work which most likely will lead to framedrop and bad user experience
There is another way though. It might not work in all cases - it all depends on your final layout, but still that's what I would recommend doing. The idea - is to make your recyclerView taller before you start animation. It requires some advanced Android skills though. Basically you need to override onMeasure & layout methods in your RecyclerView (you actually need to extend RecyclerView class to do that).
You can introduce some flag to your recyclerView to measure itself a bit taller than normal (how much taller - the exact height of your header view)
when you need to animate header out - set your flag to true and request new layout. This will re-layout recyclerView with some invisible part at the bottom.
Now you can just animate y translations of both RecyclerView & Header so header moves out of the screen and recyclerview goes higher. This will make user feel like recyclerview "expands"
Once animation is done - set your custom flag to false and change visibility of your header to GONE since it is off screen now
Here is some information about implementing custom onMeasure logic:
https://medium.com/android-news/perfmatters-introduction-to-custom-viewgroups-to-improve-performance-part-2-f14fbcd47c
Related
I am experimenting with a RecyclerView and it currently displays four CardViews vertically on the screen. Using an adapter, I am able to resize each CardView's height equally in the space given.
What I'm trying to accomplish:
On click, I would like the selected RecyclerView child to expand to fullscreen. Currently, I can programmatically set the height and expand the selected CardView dimensions, but the other CardViews after it are pushed down off-screen. How can I have all the selected CardView positioning become absolute, and lock the other views positions and expand "over" them? Is this the proper approach, or should I be looking into shared-element transitions or something else?
Side-ask: Is there a way to control all top/left positioning of RecyclerView children in an adapter?
The comments above seem to be correct - after looking into shared transitions, I found numerous examples performing the exact behavior I described. Crediting #AmratSingh since he answered first.
If it helps anyone, here is the one I am following currently: Michael Scammell - Shared Element Transitions
This one in particular: Shared element transitions within a RecyclerView
This is a question regarding the use of Android Transition API.
I am trying to animate the height change of a list, just like a dropdown menu.
I tried 2 approaches
Use a RecyclerView and animates its height change
Use a ScrollView > LinearLayout hierarchy and animates ScrollView's height.
The 2nd approach works perfectly.
But the 1st approach has a serious glitch - when the collapse transition starts, items disappear immediately.
By looking at the below GIF you can observe clearly the difference:
To be exact, items' visibility changes at the moment I change RecyclerView's LayoutParams, without waiting for the transition to finish, whatever it is expanding or collapsing
Code
I have created a minimal project on Github.
If you just want to look at the code, here is the MainActivity.
Question
Is it possible to achieve ScrollView's effect with a RecyclerView?
If yes, how?
My Idea is to do the transition of all the recycler view rows individual rather than the whole RecyclerView:
So when collapsing iterate through each ROW of a RecyclerView and do a transition. Remember to check for null if some rows are recycled they may return null. So after that collapse the whole recyclerView.
And like wise for the expanding do the same for the views.
This issue is cause by RecyclerView has many views with it but Scroll View has only one View nested in it.
I would like to know if there is an easy way of having a grid of elements, where when one of the elements is pressed,
This state:
Changes, to reveal the touched element (center element here)
For a start, I thought manually re-adding the element as over all others, then programmatically setting the position to keep it appear to be centered.
Is there an easier way, or do I have to break a bit of sweat for it?
As far as I know, Android animations don't affect views boundaries. Therefore, you could simply use setScale method of view to scale them up and down. Also, you could considering animations for better UX.
In Android there are two general way for displaying a grid of views:
Grid View
Grid Layout
In both approaches, this trick can be used.
For each cell (individual views) add a touch listener in which whenever the touch is of type down, scale it up and otherwise scale it to normal.
In Grid Views, you should do this in its adapter while for a grid layout you could iterate over its children and apply this.
I want to implement a layout similar to this.
The catch is that the content needs to be a view pager (that contains scrollable content).
My current plan is to implement this with one of the following
Make the main view a linear layout with the top section holding the header taking up fixed space (the viewpager fills whatever is left). Listen for touch events on the linear layout to expand or shrink the header, once the header has reached the minimum size, propagate the scroll events through to the viewpager (how?).
Same as 1., but wrapped in a ScrollView
Same as 1., but listen for scrolling in the viewpager and propagate that back up the view hierarchy (onScroll Listeners of some kind).
Same as 3, but wrapped in a ScrollView
I have a better idea on how to implement 3/4, but it seems like it introduces a lot of coupling, and "feels gross". I have less of an idea on how to do 1/2, but it feels (slightly) less gross. In either case, using the LinearLayout, I would have to override onTouch, rather than onScroll. Not sure which of those is preferable.
Ideally I would like to find a more elegant solution (possibly from Android L), but I welcome insights/pros/cons to my proposed solutions as well.
I have a UI layout that's comprised of a single outer layout that contains three internal layouts. The internal layouts are essentially a header, body and footer.
I would like to cause the top, header view to become completely hidden if it's forced to shrink past a certain threshold. It contains a logo image, and if it shrinks past a certain point, I'd rather just hide it completely.
What's the best way to do this? Is there a way to accomplish this statically in a layout xml? If not, do I need to subclass the View and listen for resizes? Is there another way?
Subclass your View an override the onLayout or onMeasure methods. That is when the View itself decides its width and height. After onMeasure is completed, you can call this.getMeasuredHeight() and check if its below your threshold. If it is, just hide it.
I don't think you can do it in the XML, but whenever anything happens that could shrink it (you might need to use an onTouchListener() if it's shrunk by the user's finger), you can call getHeight(), and if it's less than a certain value call setVisibility(View.GONE) on it.