I'm trying to use a vertical scrollview in conjunction with a vertical viewpager (see https://github.com/kaelaela/VerticalViewPager), and I'm not sure how to tackle it.
Essentially, I have two fragments, one lower fragment (the one that is defaulted to when the activity starts) which contains a full-screen scrollview, and one upper fragment which I want to reach when the user is at the top of the lower fragment's scrollview and continues to pull down. If anyone has used Facebook messenger, it's similar to their functionality where if you continue to scroll down on their chats page, the camera is started.
Right now, the scrollview blocks the action of opening the second fragment unless i pull down from a very specific angle.
I've considered implementing something using the OnOverScroll method of the scrollview (if Y scroll position is 0), but I feel that would lead to a bad UX because even the slightest overscroll would pull down a whole new fragment.
If anyone has any ideas, I'd be really grateful.
Thanks a lot.
I solved my issue by wrapping my scrollview in a SwipeRefreshLayout. Here are the steps, to help anyone that runs into this issue in the future:
After wrapping your scrollview in the SwipeRefreshLayout, set the layout to transparent in code using mySwipeRefreshLayout.setColorSchemeColors.
Then use
mySwipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// do your pull-down task here
}
});
to listen for when the user pulls down their scrollview from the top.
Slightly hacky solution but avoids writing custom class extensions that could introduce bugs and uses an existing feature to pretty nicely achieve the desired outcome.
Related
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'm struggling for the past 2 days to find/implement an working solution for my UI requirements for an on boarding flow. This is how the UI should look like:
These pages should be scrollable vertically only.
As you can see, the pages should be stacked on top of each other. The current page (the top one) should also resize if not the first one so that the user can see the top edges of the already swiped up pages.
Beside the arrangement of the pages, when the user swipes an page up or down, there should also be an page transition, something similar to DepthPageTransformer, or at least to easily support changes for these transitions.
Until now I've tried:
Custom vertical ViewPager
Custom ScrollView with custom listener and one-by-one item scroll
Flippable StackView (and multiple other implementations of StackView)
But I've failed to achieve the desired result using any of these approaches.
The flow is similar to the linkedin flippable stackview, with the difference that my requirements are for an vertical widget and with some small minor adjustments which can be adjusted afterwards.
Can someone please help me with this or at least guide me into the correct direction?
Thank you.
I need to implement a UI like this:
In the above screen row needs to be scrolled horizontally and columns need to be scrolled vertically.
I have not used Gallery as It is being deprecated. Here are some scenarios which I have tried:
1. Combination of GridView and ListView.
2. Combination of ListView and Horizontal ListView(Custom Component).
Option 1 did not work for me but I could make it with option 2.
With option 2 perfomance is not good.
Solution: I am thinking of implementing 4-5 horizontal listviews inside scrollview with Gestures so that I can handle the vertical swipe thru code or by subclassing the ScrollView and overriding the onScrollChanged method.
But I am looking for some more optimized solution.
Any help is appreciated.
Thanks
Use webview and push the content into it through JS hooks.
I have gone with my solution if anyone can suggest a better solution then obviously I will go with it:
Solution:
Implemented 4-5 horizontal listviews inside scrollview with Gestures
and handled the vertical swipe thru code or by subclassing the
ScrollView and overriding the onScrollChanged method.
I want to give my app a nice touch by allowing users to slide the page left or right instead of just using next/previous buttons (similar to the home screen).
What is the best way to do that? I assume I would have to override one of the Activity.on... methods and that I would also have to put my page's main View in a ViewGroup that allows me to shift pages left and right.
ViewFlipper is your friend!
Here you can see a nice video of the ViewFlipper in action and also a very good tutorial:
http://www.inter-fuser.com/2009/07/android-transistions-slide-in-and-slide.html
The solution is even easier these days with the release of Compatibility Package r3. You can download here: http://developer.android.com/sdk/compatibility-library.html
It includes
ViewPager: A ViewGroup that manages the layout for the child views, which the user can swipe between.
PagerAdapter: An adapter that populates the ViewPager with the views that represent each page.
and Fragment versions of those, if you are that way inclined.
The pager code is compatible back to API version 4 (1.6), and I just implemented a dynamically generated viewPager coming off a dynamically generated ListView in about 2 hours. I'm a novice, so this is definitely the preferred path.
There is an example app here: http://geekyouup.blogspot.com/2011/07/viewpager-example-from-paug.html
If one wants to flip between two activities perhaps one can apply this animated transition:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
finish();
//transition using XML view animations
overridePendingTransition(R.anim.slideinfromright, R.anim.slideouttoleft);
Use GestureDetector to detect if the touch event is a scroll.
If the first event to the first call to onScroll is ACTION_DOWN then you should see if it was a dominantly horizontal scroll. If so then your scroll is started and you should shift the absolute position of the view that fills the page.
For non deprecated absolute positioning, see my answer here Android: Alternative to AbsoluteLayout (I really do need absolute positioning)
You will want to be cautions of whether you return true to consume the touch events or not.
GestureDetector does not have a callback for scrolling having stopped. You will have to check if there was an ACTION_UP before you call GestureDetector.onTouchEvent and if there was an action up and you did have an unfinished scroll then you should set the absolute position to the destination location and use a TranslateAnimation to make it look nice moving from current to destination.
Edit:
GestureDetector did not work well at all if the child views also wanted to respond to touch events. I ended up creating a subclass of FrameLayout (one of the most basic layouts and the closest thing to a non intrusive parent view) and overriding dispatchTouchEvent. I just took all the events and did the detection myself.
cant we use Gallery view here?? with the adapter the whole page can be inflated inside gallery view adapter getView() and it will manage the left right scrolling perfectly.
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).