I have a horizontal UIScrollView. I want to implement a custom animation instead of the default bounce, where I pull all the way past the right edge of the scroll view's content size, the scroll view fly back to (0, 0) content offset after releasing finger.
Is there a way to cancel the bounce animation, keep the content offset from resetting, and then perform my animation?
I found a solution to this problem. Just use the UIScrollView delegate method:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
Thinking extemporaneously, without testing in code, grab the contentOffset, then set it back with setContentOffset:... animated:NO. That should cancel the ongoing animation and transition instantly to the position given. Since the position given is the current position, it should just cancel the animation.
Related
I have a vertical scroll view that needs to be scrollable but I want to use the left and right swipe gestures for something else. I have the behavior for each swipe direction working, but I want to restrict the angle of a swipe that scrolls the UIScrollView, so that it has to be really, really vertical, and most left or right leaning swipes activate the other behavior and do not change the scroll position.
I know that I can get the swipe angle by overriding scrollViewDidScroll and comparing the previous and current contentOffset, but I cannot stop the scrollview from scrolling there.
How can I limit the angle of a swipe that scrolls a UIScrollView ?
I think scrollViewDidScroll is too late for what you want to achieve.
Maybe try setting the directionalLockEnabled property of the UIScrollView to YES.(not sure if this helps... but play with it)
And/Or implement the UIScrollViewDelegate method - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView and within this methods implementation grab a pointer to the panGestureRecognizer (readonly) property of the UIScrollView passed in.
From there call translationInView: on the UIPanGestureRecognizer, passing in the view in whose coordinate system the translation of the pan gesture should be computed, and with the CGPoint returned use trigonometry to calculate the angle and if it's not within predetermined limits call setTranslationInView: on the UIPanGestureRecognizer to restore.
I have a UIScrollView in the centre of the whole view which is separated in to three parts and scroll horizontally.
Users can scroll the view freely and when the finger is up, i want to set one of the three parts to show based on the contentoffset of the UIScrollView.
how could i detect the touchupinside event in the UIScrollView? I tried add UITapGestureRecognizer and override touchesEnded but it does not work.
How about instead using the - scrollViewDidEndDecelerating:?
Keep in mind that just because the user has picked up their finger doesn't mean that the scrollview has stopped changing its content offset. By utilizing the - scrollViewDidEndDecelerating: delegate method, yo will be notified when the scroll view has come to a stop and at that point you can check the contentOffset and do what you need.
- scrollViewDidScroll: isn't a good match for what you want as it gets called even while the user's finger is still down. If that is important to you, then use - scrollViewDidEndDecelerating: as I mentioned above. If you'd rather know when the finger is lifted, and don't care that the scrollview is still in transit, then you can use - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate.
I would like to disable the effect of the UIScrollView, that it cancels the current setContentOffset animation when tapped. However, panning should still be recognized at any time.
The reason is that I have implemented custom page-sizes (By using the UIScollView delegate's method - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset, where I set targetContentOffset, such that it is a valid page bound).
If a user now taps while an animation is going on, the UIScrollView cancels the animation, which I want to avoid, because it leaves the UIScrollView with an invalid contentOffset.
There's a UIScrollViewDelegate method, scrollViewDidEndScrollingAnimation:, which tells you when a scroll view animation caused by calling setContentOffset:animated: completes. I ended up setting scrollEnabled to NO on the scroll view before I call setContentOffset:animated, then setting it back to YES in scrollViewDidEndScrollingAnimation:. Effectively the user can't tap to cancel the scroll animation.
I have a UIScrollView which has two pages and only scroll horizontally.
The scrolling and paging is controlled using a UIPageControl. I have placed a UIImageView on the scrollView which contains an image of an iPhone (shown in red in the image below) that says Hello inside page 1.
I wanted to animate the UIImageView to rotate and change its position as shown in the image when the user scrolls from page-1 to page-2. Also the animation should ideally rotate back when the user is scrolling back from page-2 to page-1.
The animation or movement of the UIImageView is based on how much the user is scrolling horizontally and not based on time.
How can I rotate the UIImageView back and forth based on the scroll position of the UIScrollView?
Set a delegate for your scroll view. Probably you want your view controller to be the delegate. You need to add UIScrollViewDelegate to its list of protocols.
Then, in the delegate, implement scrollViewDidScroll:. In scrollViewDidScroll:, look at the scroll view's contentOffset. Based on the contentOffset, set the image view's transform and center to rotate and move it where you want.
To find by how much the scroll view has scrolled, you can check UIScrollView's contentOffset property:
contentOffset - The point at which the origin of the content view is
offset from the origin of the scroll view.
Then to rotate that image view, you could do this:
self.imageview.transform = CGAffineTransformMakeRotation(M_PI/2);
As far as the animation goes, I personally don't have much experience with it. But you could have a look at Simple Animation Using UIImageView.
So the contentSize of my scrollView is initially equal to the frame of my image, but it seems that the more I zoom, the larger the contentSize gets. Thus, when the scrollView is zoomed in, , there is a huge gap around it. Dynamically updating the contentSize in - (void)scrollViewDidZoom:(UIScrollView *)aScrollView doesn't seem to work. Am I missing something?
Note: the gap is only visible vertically (i.e: above and below the imageView)
I don't believe it is possible to update contentSize on the fly while zooming. This is because:
A scroll view also handles zooming and panning of content. As the user
makes a pinch-in or pinch-out gesture, the scroll view adjusts the
offset and the scale of the content. When the gesture ends, the object
managing the content view should should update subviews of the content
as necessary. (Note that the gesture can end and a finger could still
be down.) While the gesture is in progress, the scroll view does not
send any tracking calls to the subview.
(Apple docs)
You should update your contentSize based on zoomScale after the user has finished zooming using:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView
withView:(UIView *)view
atScale:(float)scale