Scrolling one UIScrollView Proportionately to Another - ios

I have two UIScrollViews with vertical scroll: foreground and background. The user can only interact with the former; the latter is moved programmatically. How can I make it so that when the user scrolls the foreground, the background scrolls at a proportional rate of ΒΌ? For example, for every 4px that foreground scrolls, background will scroll 1px in the same direction.
How can I achieve this relationship in Swift2?

set your self as the scrollView delegate -
self.foregroundScrollView.delegate = self
and use the UIScrollViewDelegate methods:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
self.lastY = scrollView.contentOffset.y;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// Calculate how much distance the scrollView has travelled since last scroll
CGFloat currentY = scrollView.contentOffset.y;
CGFloat difference = currentY - self.lastY;
// Set new contentOffset for your background scrollView
CGPoint currentBackgroundOffset = self.backgroundScrollView.contentOffset;
currentBackgroundOffset.y += difference/4;
self.backgroundScrollView.contentOffset = currentBackgroundOffset;
// Don't forget to update the lastY
self.lastY = currentY;
}
Swift:
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
lastY = scrollView.contentOffset.y
}
func scrollViewDidScroll(scrollView: UIScrollView) {
// Calculate how much distance the scrollView has travelled since last scroll
let currentY = scrollView.contentOffset.y
let difference = currentY - lastY
// Set new contentOffset for your background scrollView
var currentBackgroundOffset = backgroundScrollView.contentOffset
currentBackgroundOffset.y += difference/4
backgroundScrollView.contentOffset = currentBackgroundOffset
// Don't forget to update the lastY
lastY = currentY
}

Related

Disable scrollViewDidScroll: when scrolling UICollectionView - iOS

I have implemented scrollViewDidScroll: inside my viewcontroller to cause some animations when I scroll the view up and down.
However, when I scroll my collectionview inside the viewcontroller (horizontally) it messes up with my animation inside scrollViewDidScroll:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
newAlpha = 1 - scrollView.contentOffset.y / 200;
self.introImageView.alpha = newAlpha;
//... -> prevent scrolling when collectionview is scrolled
}
How do I prevent calling scrollViewDidScroll: when scrolling my collectionview horizontally?
The best way is not to disable the delegate method, but make sure to only call that code when it's called by your scrollview. Here's an example
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == self.myScrollView) {
newAlpha = 1 - scrollView.contentOffset.y / 200;
self.introImageView.alpha = newAlpha;
} else {
//collectionView would fall here
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if ([scrollView isKindOfClass:[UICollectionView class]] == NO) {
newAlpha = 1 - scrollView.contentOffset.y / 200;
self.introImageView.alpha = newAlpha;
//... -> prevent scrolling when collectionview is scrolled
}
}

Scroll view when collection view scrolls

I want to scroll the UIView when collection view scrolls as shown in below video
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(scrollView.contentOffset.x)
let contentSize = self.propertyImageCollectionView.contentSize
let xOffSet = (((scrollView.contentOffset.x * self.propertyImageCollectionView.frame.width) / (contentSize.width - self.progressViewWidthConstratint.constant)))
let xValue = xOffSet + ((self.progressViewWidthConstratint.constant * self.progressViewLeadingConstraint.constant) / self.propertyImageCollectionView.frame.width)
print( self.progressViewWidthConstratint.constant)
print( xOffSet)
print(xValue)
if xValue > 0 && xValue < self.propertyImageCollectionView.frame.width - self.progressViewWidthConstratint.constant{
self.progressViewLeadingConstraint.constant = xValue
}
}
The view is not scrolling upto end of screen. It stops scrolling before some points. Where am I lacking in my code. I also tried to use KVO but not succeed. Do you have any alternative approach?

Swift: How to anchor view to the top when scrolling

I have an UIView in ScrollView superview. I want this UIView to stick to the top and stays there when users scrolls down.
Note that it should start in the middle of a screen and go up respectively when scrolling down.
I've seen many questions and answers but none of them solved my problem
iOS: Add subview with a fix position on screen
Simple way to change the position of UIView?
My code in scrollViewDidScroll method
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y > anchor.frame.origin.y {
var fixedFrame:CGRect = self.anchor.frame
fixedFrame.origin.y = (self.navigationController?.navigationBar.frame.height)!
self.anchor.frame = fixedFrame
}
}
you can do this by saving a initial offset value of Y for your anchor view, then compare it in the scrollview delegate event.
self.initialOffSet = self.anchor.frame.origin.y
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var newFrame = self.anchor.frame
newFrame.origin.y = max(self.initialOffSet!, scrollView.contentOffset.y)
self.anchor.frame = newFrame
}
Why dont you put that view out of your scrollview?It will stay at the top only even when you will be scrolling your scrollview?

iOS how to check if go to the bottom of webView

Is there any event I can notify the supper view?
I try the scrollViewDidScroll. But it don't be called.
-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
NSLog(#"At the bottom...");
}
You must set the delegate of scrollview which in the webview to self first. So that, scrollViewDidScroll: could be call when you scroll the webview. So, try this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.webview.scrollview.delegate = self;
}
- (void)scrollViewDidScroll:(UIScrollView*)scrollview
{
CGPoint offset = scrollView.contentOffset;
CGRect bounds = scrollView.bounds;
UIEdgeInsets inset = scrollView.contentInset;
CGFloat currentOffset = offset.y + bounds.size.height - inset.bottom;
if (currentOffset - scrollView.contentSize.height <= 0)
{
NSLog(#"At the bottom...");
}
}
If you have an instance of webView, you can get the reference of its scrollView by doing,
webView.scrollView. Set its delegate to self like so:
webView.scrollView.delegate = self;
Now, make sure you have implemented UIScrollViewDelegate in your class where you have an instance of the webView. Implement the below the code that tells you whether you have reached the bottom.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
float bottomEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
if (bottomEdge >= scrollView.contentSize.height) {
//This means that you have reached the end.
}
}
To get the call in scrollView delegate methods you need to assign the delegate for webview scroll view like this:
webview.scrollView.delegate = self;
Also Conform the UIScrollViewDelegate in .h file like this:
#interface MyController : UIViewController <UIScrollViewDelegate>
#end
If anyone is interested on how this is done in Swift 4, here it is:
Set the webviews' scrollView delegate to self in viewDidLoad() self.webView.scrollView.delegate = self
Extend your class from UIScrollViewDelegate
Implement the method scrollViewDidScroll() which will handle the scroll events
(this particular implementation is used to check if the user has scrolled to the bottom of the webview's content)
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let bottom = scrollView.contentOffset.y + scrollView.frame.size.height
if (bottom >= scrollView.contentSize.height) {
// Do something here
}
}

Detect UITextView scroll location

I am trying to implement a form of a Terms & Conditions page where the "Proceed" button is only enabled once the user has scrolled to the bottom of a UITextView. So far I have set my class as a UIScrollView delegate & have implemented the method below:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(#"Checking if at bottom of UITextView");
CGPoint bottomOffset = CGPointMake(0,self.warningTextView.frame.size.height);
//if ([[self.warningTextView contentOffset] isEqualTO:bottomOffset])
{
}
}
I have commented the if statement because I am not sure how to check if the UITextView is at the bottom.
UITextView is a UIScrollView subclass. Therefore the UIScrollView delegate method you are using is also available when using UITextView.
Instead of using scrollViewDidEndDecelerating, you should use scrollViewDidScroll, as the scrollview may stop scrolling without deceleration.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height)
{
NSLog(#"at bottom");
}
}
A Swift version for this question:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height {
print( "View scrolled to the bottom" )
}
}
This should solve it. It works. I am using it.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float bottomEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
if (bottomEdge >= scrollView.contentSize.height)
{
// we are at the end
}
}

Resources