I have collectionView nested inside a scrollView. Both of which scroll Vertically.
In my main scroll View I want to stop it's scrolling when reaching scrollView.contentOffset.y > someValue, and enable scrolling in collectionView
But I want this to happen in one continuous motion without needing to lift finger in between.
Full view
If you want continues scrolling, you should not stop the scrolling of your main scroll view. And you should set the main scrollView.contentOffset.y as constant value once it's reached your max offset(scrollView.contentOffset.y > someValue). And you can increase/decrease the contentOffset.y of your collectionView as per you main scrollview motion.
Example:
if (scrollView.contentOffset.y > 50) {
scrollView.contentOffset.y = 50.0;
collectionView.contentOffset.y += 1; //you can do your scroll up/down calculation over here
}
Related
In scrollview delegate method table content offset while scrolling always return 0 for it's y position.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(items:String(format:"Offset %d",scrollView.contentOffset.y))
}
I have also printed the myTableView.contentOffset.y
But it also prints the same result.
ContentOffset doesn't change when you scrolling. It's origin of your content in scrollView. It defines the point in the content view that is visible at the top left of the scroll view bounds. We can use this property to scroll programmatically .
There is more about it
https://developer.apple.com/documentation/uikit/uiscrollview/1619404-contentoffset
https://www.objc.io/issues/3-views/scroll-view/
Try to track contenView.bounds.origin.y for tracking y-position
I have a smaller child scrollview inside a parent scrollview. I want the child to have scrolling disabled, so that when the user drags on the screen only the parent scrollview scrolls, then once the parent reaches a certain content offset to enable scrolling on the child scrollview, with the same drag.
Currently, the child scroll is disabled, then the parent scrollview reaches the desired offset and enables scrolling on the child, but you need to take your finger off the screen and initiate a new drag to be able to scroll the now-enabled child scrollview.
Why is this? Is there any way to enable the scrollview and start scrolling it with the same drag?
Edit:
Here is the code I am currently using:
func scrollViewDidScroll (scrollView: UIScrollView) {
if scrollView == outerScroll {
if scrollView.contentOffset.y == 10 {
outerscroll.scrollEnabled = false
innerScroll.scrollEnabled = true
}
}
}
I’m have a view that contains a regular UIView and a UIScrollView. The UIView sits above the UIScrollView offscreen. The UIScrollView typically occupies the entire screen. (It should be noted that I’m not using Autolayout). When the user scrolls to the top of the scrollview content I would like the UIView to start appearing on the screen. And when it reaches a certain threshold have the UIView snap into place and occupy the screen.
My initial thought was to use the UIScrollView delegate method, and adjust the superview.frame.orgin.y value when the scrollview contentOffset.y value is negative.
func scrollViewDidScroll(scrollView: UIScrollView) {
pullDownInProgress = scrollView.contentOffset.y <= 0.0
if pullDownInProgress {
self.view. = (-self.view.height / 2) - scrollView.contentOffset.y
}
}
However, this creates a stretching between the UIView and the UIScrollView due the scrollview bounce setting. If I turn off the bounce setting then the scrollview.contentOffset is never less then zero, therefore my superview frame is never adjusted.
Any suggestions on how to accomplish this?
You don't need to change the superview.frame, instead move the offscreen view down by its height so that it can appears and any bouncing effect for the scroll view might be hidden by that view.Or you can even move both the scroll view and the offscreen view with the height of the offscreen view. It really depends whether your offscreen view is transparent or not
I have a ScrollView that is supposed to be scrolled only downwards. The content View's size matches scrollview identically. I use this code to prevent from scrolling up:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
#define CONTENT_OFFSET 0
NSLog(#"%f", scrollView.contentOffset.y);
//prevent from scrolling up
if (scrollView.contentOffset.y > CONTENT_OFFSET) {
scrollView.contentOffset = CGPointMake(0, CONTENT_OFFSET);
}
}
It used to work perfectly. But now for some reason scroll view starts at -44 points and is of course scrollable up to 0. In between -44 and 0 it doesn't bounce if drag ended. I'm pretty sure I have not changed anything in layout but I might have unintentionally. I think scroll view now has bigger content view for some reason. Where do I look for the origin of this problem?
So I realize that having nested scroll views at all it sort of a red flag, but the current setup of everything actually works quite well besides one small problem. One scroll view manages scrolling through a collection, while another handles zooming and panning on the entire collection view. This all works, but the small problem comes from when zooming in and panning downward, the scrollview pans while the collectionview scrolls, causing the view to scroll twice as fast, and not feel connected to your finger.
What I ideally want to happen is vertical scrolling is managed by the outer scroll view when panning is possible, and then handled by the inner scroll view when the outer one can no longer pan. I got very close by writing something like this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == _outerScrollView) {
CGPoint offset = _outerScrollView.contentOffset;
CGFloat height = _outerScrollView.frame.size.height;
CGFloat contentHeight = _outerScrollView.contentSize.height;
ScrollDirection scrollDirection;
if (offset > _lastContentOffset){
scrollDirection = ScrollDirectionUp;
} else {
scrollDirection = ScrollDirectionDown;
}
BOOL scrollIsAtTop = offset.y <= 0;
BOOL scrollIsAtBottom = offset.y + height >= contentHeight;
//If there is a pan upward and we aren't at the top of the outer
//scrollview cancel the gesture on the inner view
//downward vice versa
if (!((scrollIsAtTop && scrollDirection == ScrollDirectionUp)
|| (scrollIsAtBottom && scrollDirection == ScrollDirectionDown))) {
_innerCollectionView.panGestureRecognizer.enabled = NO;
_innerCollectionView.panGestureRecognizer.enabled = YES;
}
}
_lastContentOffset = offset.y;
}
This ALMOST works, with one side effect of a big pan downward stops when it hits the bottom and requires the user to start a new gesture to continue scrolling with the inner collection. Ideally this transition would be smooth, but I'm having a hard time figuring out a way to do this. Again I realize scroll view inside scroll view is not ideal, but if I can fix this small problem everything will be good, rather than attempt to redesign the whole thing.
Any ideas on how I can handle the double scroll in a way that lets the pan gesture win, but cleanly transitions to the inner collection when the outer scroll view can no longer pan vertically?
So, since I never got any answers, this is the solution I've been going with. Essentially if the inner collection view isn't at the top or bottom, I reset the y offset change the outer scroll view has in scrollViewDidScroll. Code looks like this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == _outerScrollView) {
if (![self innerScrollIsAtTop] && ![self innerScrollIsAtBottom] && !self.allowOuterScroll) {
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, self.lastContentOffset)];
}
self.lastContentOffset = scrollView.contentOffset.y;
}
}
using these 2 conveniences:
- (BOOL)innerScrollIsAtTop {
return _innerCollectionView.contentOffset.y <= 0;
}
- (BOOL)innerScrollIsAtBottom {
CGFloat zoom = self.zoomScale;
CGFloat height = _innerCollectionView.frame.size.height;
CGFloat contentHeight = _innerCollectionView.contentSize.height;
CGPoint offset = _innerCollectionView.contentOffset;
return offset.y + height / zoom >= contentHeight;
}
And you'll need 2 class variables, a float to hold the previous y content offset of the outer scroll, and a BOOL to hold whether you want to allow the outer scroll view to scroll, which you can set to YES while zooming or programatically scrolling. This solution fixes the double scroll, but does have a cumbersome hack within scrollviewDidScroll that may bite you later and you constantly need to work around, but for now this is the solution I've been using.