I need to emulate the behavior of Instagram's Reels which scrolls to the next or previous page when the current page is scrolled more than 50% upwards or downwards respectively and the finger goes up. ViewPager2's default behavior isn't satisfactory for this and I don't think I can change it without changing the PagerSnapHelper inside ViewPager2.
Is there any other way I can implement a custom Snap behavior for ViewPager2 then?
Related
I want to create my own version of ViewPager2 so that I can control the animation design and orientation capabilities. Basically, I'm trying to have a scrolling up and down load new users while left and right would be more information about that user.
I tried using custom animations with swipe gestures, which works exactly as I wanted, except I don't get the control of dynamically animating the swiping direction. Essentially, it still works like a button animation - you might swipe in the direction you want but the animation speed/feel/etc is always the same animation vs. ViewPager2's ability to move with the gesture.
I experimented with OnDragListeners which do give me the "Tinder card movement" animation effect but I don't want to allow for animations in all directions. I was able to use a ViewPager2 for the horizontal direction while using the OnDragListener to override the swiping (using OnLongClick). When you drag up or down it has the same issue of the transition animation being the same speed/feel/etc everytime instead of the nice ViewPager2 slide on touch effect.
I only need 4 fragments for each user so my next idea was to try a horizontalscrollview in a recyclerview but that's working either.
Any suggestions for an approach I might not have considered?
It's 2022, and I'm having the same issue with ViewPager2 that folks had with ViewPager (see NestedScrolling inside a Viewpager inside a BottomSheetDialog ) - 5 years ago.
Although I'm not using a BottomSheetDialogFragment, just a regular old bottom sheet (with a FragmentContainer).
ViewPager2 is a bit different in that it itself uses a horizontal RecyclerView. BottomSheetView.findScollingChild() sees this as the scrolling child!
So, the approach I took to solving this is:
added a page change listener to my ViewPager2 that gets the hosting
CoordinatorLayout, and calls requestLayout() on it after the page change.
copied the BottomSheetBehavior class that matches my current material components version (1.5) into my project, renamed it, and made findScrollingChild public.
subclassed that copy, and set the sub-class as the behavior on my sheet.
Why sub-class and not just change the findScrollingChild method directly? Well, this way it's relatively easy to update the copy of BottomSheetBehavior when we update our material components.
My implementation of findScrollingChild() in the sub-class checks specifically for a ViewPager2.
If it is, it gets child 0 of the ViewPager2 (the horizontal RecyclerView), and then uses recycler?.layoutManager?.findViewByPosition(pager.currentItem) as the view to then search for the scrolling child.
If the view is not a ViewPager2, it uses the same algorithm from the original findScrollingChild()
This basically works. I have a pager with 2 tabs, one containing a ScollView that has nested scrolling enabled, and one containing a RecyclerView. The bottom sheet expands as its scrolled, and then the contents of the nested child scroll down properly once the sheet is open.
The problem is if after the sheet has expanded if the finger gets lifted, then any attempt to scroll up causes the bottom sheet to close rather then scrolling up -- no matter how far it's been scrolled down. At least this is the case for the RecyclerView in the second tab, I don't have enough content in the first tab at the moment that it actually needs to scroll.
The sheet gets closed with the list still scrolled down several pages (or wherever you stopped scrolling). If however you scroll down -- even just a little bit -- scrolling up works again! And you can swipe a couple times and it will work - until it doesn't, and the sheet moves to the half expanded state.
I'm not sure where this behavior is coming from or how to resolve it. It doesn't happen when the bottom sheet has a direct RecyclerView (no ViewPager2 I'm the way).
I tried disabling swiping in the ViewPager2 thinking it might be interfering with touch events, but to no avail.
I have a fragment with a scrollview that holds a long layout essentially representing 2 different sections that are related, what I want is to control the scrollview so when the user wants to scroll down it always goes all the way down and can never be in the middle so it will never reveal partially the top or bottom parts, same effect backwards when you want to scroll up it just takes over and goes all the way up to reveal the top section of the layout fully.
It is basically how a vertical viewpager will behave but contained within a single long view.
I know how to programatically scroll up or down but I don't know how to avoid the user scrolling to just the middle, I'd like to hook up to some scroll event, detect the direction and go fully in either direction.
I want to be able to scroll a RecyclerView behind a keyboard. The issue is that if I have say more than 5 items in the RecyclerView.Adapter, and assume that each item might have a height of say 100dp. I want to be able to scroll the RecyclerView down with the keyboard still up and be able to scroll down to be able to see the first item in the RecyclerView.
In iOS you can set something called a contentInset on a NSTableView and that gives you extra scrolling space below the list. I am looking for something similar for the RecyclerView so far, there isn't much to go on.
INITIAL STARTING POINT
WHAT HAPPENS (Can't scroll down anymore)
WHAT I WANT (be able to scroll down)
I have a ScrollView which has two hidden images, one at the top and one at the bottom. In between there is a bunch of visible content.
What I need to do is make these images hidden by default but when you scroll all the way up or all the way down you could see them as you're scrolling. But then as soon as you stop scrolling it should bounce back to the visible area so that the hidden images aren't showing.
Basically I'm trying to imitate the bounce scrolling feature of the iphone UIScrollView.
I have my ScrollView all setup and I do a scroll at the beginning so as to hide the top hidden image. Now all I need to do is detect when a scrolling has ended, figure out the Y position, and check whether a hidden image is shown. If it is, I would just programmatically scroll the view back so that the hidden image is hidden.
I hope all that made sense.
So anyways, I know how to programmatically scroll a ScrollView. Now what I need is some sort of callback to tell me when a ScrollView ended scrolling and also a way to get the ScrollView's current 'Y' position. Are there any such methods I could use?
I looked through the ScrollView docs but nothing jumped out at me. I'm still not very familiar with the Android naming schemes so maybe I missed something obvious somewhere.
Anyways, any help would be appreciated here. Cheers.
You can use an OnTouchListener to detect when the user presses/releases the list.
You can also use the onScrollStateChanged method of the OnScrollListener class (most likely in conjunction with a touch listener) to detect changes in the SCROLL_STATE - when the list has stopped scrolling the state will change from a state that is not SCROLL_STATE_IDLE to SCROLL_STATE_IDLE.
Alternatively if you are using 2.3 or above you can use an OverScroller to get the desired effect (see Modifying Android OverScroll for how to change the over scroll effect to an iPhone like one).