iOS Scrolling one UIScrollView based off contentOffset of another goes out of sync












1















EDIT: I have attached a simple demo project dropbox link at bottom



I have a UI with a UICollectionView at top and a scrollview at the bottom. I want the scrolling in collectionview to scroll the scrollview too in sync. I have disabled user-interaction in scrollview so only the collectionview can effect the scrolling in it.



Each collectionview item is 150px for this testing purpose.



The UIViews in the scrollview are screen width in size. So for every scroll of a collectionview item, I need to scroll the scrollview by screen width. To achieve this, I am calculating the distance the collectionview offset has changed by and then dividing it by the cell width (150) and multiplying it by scrollview's width.



I am trying to achieve the following UI:



Start:



enter image description here



Scroll collectionview to cell 1:



enter image description here



Scroll collectionview to cell 2:



enter image description here



This all works fine the first few times but as I scroll the collectionview back and forth a few times to longer distances (let's say cell 10 -> 0 -> 10 -> 0 and so on), the scrollview goes out of sync by "tiny" distances. To illustrate this, notice how there is the "yellow" color from the second UIView on the right edge of the scrollview:



enter image description here



I can see this issue by NSLogging the contentOffset of the scrollview too (notice how it starts getting out of sync by 0.5 after few times):



2018-11-25 19:24:28.273278-0500 ScrollViewMatchTest[19412:1203912] Finished: 0
2018-11-25 19:24:31.606521-0500 ScrollViewMatchTest[19412:1203912] Finished: 0.5
2018-11-25 19:24:55.173709-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:03.007528-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:07.841096-0500 ScrollViewMatchTest[19412:1203912] Finished: 2.5
2018-11-25 19:26:57.634429-0500


I am not really sure what's causing this problem and I have tried quite a few ways to fix it but in vain. I can sort of figure out a workaround (to reset the offset and bring it back in sync when scrolling finishes) but I would like to know why exactly this out of sync issue is caused.





Workaround solution by resetting the contentOffset of scrollView to closes multiple of screen width:



-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if (scrollView==self.myCollectionView) {
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
NSLog(@"Closest: %g",RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width));
[self.myScrollView setContentOffset:CGPointMake(RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width), self.myScrollView.contentOffset.y) animated:YES];
}
}

float RoundTo(float number, float to)
{
if (number >= 0) {
return to * floorf(number / to + 0.5f);
}
else {
return to * ceilf(number / to - 0.5f);
}
}


END OF WORKAROUND SOLUTION



I have attached a simple demo project to illustrate this issue as well (run the app and scroll back and forth aggresively on the top scrollview a few times): https://www.dropbox.com/s/e2bzgo6abq5wmgw/ScrollViewMatchTest.zip?dl=0



Here's the code:



#import "ViewController.h"
#define countOfItems 50

@interface ViewController (){
CGFloat previousOffset_Header;
CGFloat previousOffset_Scrollview;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self.myCollectionView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellWithReuseIdentifier:@"cell"];
[self.myCollectionView reloadData];

for (NSInteger i=0; i<countOfItems; i++) {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(i*self.myScrollView.frame.size.width, 0, self.myScrollView.frame.size.width, self.myScrollView.frame.size.height)];
myView.backgroundColor=i%2==0?[UIColor blueColor]:[UIColor yellowColor];
[self.myScrollView addSubview:myView];

}
self.myScrollView.contentSize=CGSizeMake(countOfItems*self.myScrollView.frame.size.width, self.myScrollView.frame.size.height);


}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return countOfItems;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = indexPath.item%2==0?[UIColor blueColor]:[UIColor yellowColor];
cell.myLabel.text=[NSString stringWithFormat:@"%ld",indexPath.item];

return cell;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
if (scrollView==self.myCollectionView) {
previousOffset_Header = self.myCollectionView.contentOffset.x;
previousOffset_Scrollview = self.myScrollView.contentOffset.x;
}
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{

if (scrollView==self.myCollectionView) {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:scrollView afterDelay:0.1 inModes:@[NSRunLoopCommonModes]];
CGFloat offsetToMoveBy = (self.myCollectionView.contentOffset.x-previousOffset_Header)*(self.myScrollView.frame.size.width/150);
previousOffset_Scrollview = previousOffset_Scrollview +offsetToMoveBy;

[self.myScrollView setContentOffset:CGPointMake(previousOffset_Scrollview, self.myScrollView.contentOffset.y) animated:NO];
previousOffset_Header = self.myCollectionView.contentOffset.x;

}
}

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
}

@end









share|improve this question

























  • So is the problem solved? If so, please answer your own question and accept your own answer.

    – matt
    Nov 26 '18 at 1:13











  • @matt it's not solved as my workaround works but 1. I would still like to know what the actual issue is and 2. The workaround doesn't look nice as you see the scrollView stop and then scroll a bit again to fix itself. So looks kind of ugly.

    – Pranoy C
    Nov 26 '18 at 1:27
















1















EDIT: I have attached a simple demo project dropbox link at bottom



I have a UI with a UICollectionView at top and a scrollview at the bottom. I want the scrolling in collectionview to scroll the scrollview too in sync. I have disabled user-interaction in scrollview so only the collectionview can effect the scrolling in it.



Each collectionview item is 150px for this testing purpose.



The UIViews in the scrollview are screen width in size. So for every scroll of a collectionview item, I need to scroll the scrollview by screen width. To achieve this, I am calculating the distance the collectionview offset has changed by and then dividing it by the cell width (150) and multiplying it by scrollview's width.



I am trying to achieve the following UI:



Start:



enter image description here



Scroll collectionview to cell 1:



enter image description here



Scroll collectionview to cell 2:



enter image description here



This all works fine the first few times but as I scroll the collectionview back and forth a few times to longer distances (let's say cell 10 -> 0 -> 10 -> 0 and so on), the scrollview goes out of sync by "tiny" distances. To illustrate this, notice how there is the "yellow" color from the second UIView on the right edge of the scrollview:



enter image description here



I can see this issue by NSLogging the contentOffset of the scrollview too (notice how it starts getting out of sync by 0.5 after few times):



2018-11-25 19:24:28.273278-0500 ScrollViewMatchTest[19412:1203912] Finished: 0
2018-11-25 19:24:31.606521-0500 ScrollViewMatchTest[19412:1203912] Finished: 0.5
2018-11-25 19:24:55.173709-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:03.007528-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:07.841096-0500 ScrollViewMatchTest[19412:1203912] Finished: 2.5
2018-11-25 19:26:57.634429-0500


I am not really sure what's causing this problem and I have tried quite a few ways to fix it but in vain. I can sort of figure out a workaround (to reset the offset and bring it back in sync when scrolling finishes) but I would like to know why exactly this out of sync issue is caused.





Workaround solution by resetting the contentOffset of scrollView to closes multiple of screen width:



-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if (scrollView==self.myCollectionView) {
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
NSLog(@"Closest: %g",RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width));
[self.myScrollView setContentOffset:CGPointMake(RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width), self.myScrollView.contentOffset.y) animated:YES];
}
}

float RoundTo(float number, float to)
{
if (number >= 0) {
return to * floorf(number / to + 0.5f);
}
else {
return to * ceilf(number / to - 0.5f);
}
}


END OF WORKAROUND SOLUTION



I have attached a simple demo project to illustrate this issue as well (run the app and scroll back and forth aggresively on the top scrollview a few times): https://www.dropbox.com/s/e2bzgo6abq5wmgw/ScrollViewMatchTest.zip?dl=0



Here's the code:



#import "ViewController.h"
#define countOfItems 50

@interface ViewController (){
CGFloat previousOffset_Header;
CGFloat previousOffset_Scrollview;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self.myCollectionView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellWithReuseIdentifier:@"cell"];
[self.myCollectionView reloadData];

for (NSInteger i=0; i<countOfItems; i++) {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(i*self.myScrollView.frame.size.width, 0, self.myScrollView.frame.size.width, self.myScrollView.frame.size.height)];
myView.backgroundColor=i%2==0?[UIColor blueColor]:[UIColor yellowColor];
[self.myScrollView addSubview:myView];

}
self.myScrollView.contentSize=CGSizeMake(countOfItems*self.myScrollView.frame.size.width, self.myScrollView.frame.size.height);


}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return countOfItems;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = indexPath.item%2==0?[UIColor blueColor]:[UIColor yellowColor];
cell.myLabel.text=[NSString stringWithFormat:@"%ld",indexPath.item];

return cell;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
if (scrollView==self.myCollectionView) {
previousOffset_Header = self.myCollectionView.contentOffset.x;
previousOffset_Scrollview = self.myScrollView.contentOffset.x;
}
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{

if (scrollView==self.myCollectionView) {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:scrollView afterDelay:0.1 inModes:@[NSRunLoopCommonModes]];
CGFloat offsetToMoveBy = (self.myCollectionView.contentOffset.x-previousOffset_Header)*(self.myScrollView.frame.size.width/150);
previousOffset_Scrollview = previousOffset_Scrollview +offsetToMoveBy;

[self.myScrollView setContentOffset:CGPointMake(previousOffset_Scrollview, self.myScrollView.contentOffset.y) animated:NO];
previousOffset_Header = self.myCollectionView.contentOffset.x;

}
}

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
}

@end









share|improve this question

























  • So is the problem solved? If so, please answer your own question and accept your own answer.

    – matt
    Nov 26 '18 at 1:13











  • @matt it's not solved as my workaround works but 1. I would still like to know what the actual issue is and 2. The workaround doesn't look nice as you see the scrollView stop and then scroll a bit again to fix itself. So looks kind of ugly.

    – Pranoy C
    Nov 26 '18 at 1:27














1












1








1








EDIT: I have attached a simple demo project dropbox link at bottom



I have a UI with a UICollectionView at top and a scrollview at the bottom. I want the scrolling in collectionview to scroll the scrollview too in sync. I have disabled user-interaction in scrollview so only the collectionview can effect the scrolling in it.



Each collectionview item is 150px for this testing purpose.



The UIViews in the scrollview are screen width in size. So for every scroll of a collectionview item, I need to scroll the scrollview by screen width. To achieve this, I am calculating the distance the collectionview offset has changed by and then dividing it by the cell width (150) and multiplying it by scrollview's width.



I am trying to achieve the following UI:



Start:



enter image description here



Scroll collectionview to cell 1:



enter image description here



Scroll collectionview to cell 2:



enter image description here



This all works fine the first few times but as I scroll the collectionview back and forth a few times to longer distances (let's say cell 10 -> 0 -> 10 -> 0 and so on), the scrollview goes out of sync by "tiny" distances. To illustrate this, notice how there is the "yellow" color from the second UIView on the right edge of the scrollview:



enter image description here



I can see this issue by NSLogging the contentOffset of the scrollview too (notice how it starts getting out of sync by 0.5 after few times):



2018-11-25 19:24:28.273278-0500 ScrollViewMatchTest[19412:1203912] Finished: 0
2018-11-25 19:24:31.606521-0500 ScrollViewMatchTest[19412:1203912] Finished: 0.5
2018-11-25 19:24:55.173709-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:03.007528-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:07.841096-0500 ScrollViewMatchTest[19412:1203912] Finished: 2.5
2018-11-25 19:26:57.634429-0500


I am not really sure what's causing this problem and I have tried quite a few ways to fix it but in vain. I can sort of figure out a workaround (to reset the offset and bring it back in sync when scrolling finishes) but I would like to know why exactly this out of sync issue is caused.





Workaround solution by resetting the contentOffset of scrollView to closes multiple of screen width:



-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if (scrollView==self.myCollectionView) {
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
NSLog(@"Closest: %g",RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width));
[self.myScrollView setContentOffset:CGPointMake(RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width), self.myScrollView.contentOffset.y) animated:YES];
}
}

float RoundTo(float number, float to)
{
if (number >= 0) {
return to * floorf(number / to + 0.5f);
}
else {
return to * ceilf(number / to - 0.5f);
}
}


END OF WORKAROUND SOLUTION



I have attached a simple demo project to illustrate this issue as well (run the app and scroll back and forth aggresively on the top scrollview a few times): https://www.dropbox.com/s/e2bzgo6abq5wmgw/ScrollViewMatchTest.zip?dl=0



Here's the code:



#import "ViewController.h"
#define countOfItems 50

@interface ViewController (){
CGFloat previousOffset_Header;
CGFloat previousOffset_Scrollview;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self.myCollectionView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellWithReuseIdentifier:@"cell"];
[self.myCollectionView reloadData];

for (NSInteger i=0; i<countOfItems; i++) {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(i*self.myScrollView.frame.size.width, 0, self.myScrollView.frame.size.width, self.myScrollView.frame.size.height)];
myView.backgroundColor=i%2==0?[UIColor blueColor]:[UIColor yellowColor];
[self.myScrollView addSubview:myView];

}
self.myScrollView.contentSize=CGSizeMake(countOfItems*self.myScrollView.frame.size.width, self.myScrollView.frame.size.height);


}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return countOfItems;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = indexPath.item%2==0?[UIColor blueColor]:[UIColor yellowColor];
cell.myLabel.text=[NSString stringWithFormat:@"%ld",indexPath.item];

return cell;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
if (scrollView==self.myCollectionView) {
previousOffset_Header = self.myCollectionView.contentOffset.x;
previousOffset_Scrollview = self.myScrollView.contentOffset.x;
}
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{

if (scrollView==self.myCollectionView) {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:scrollView afterDelay:0.1 inModes:@[NSRunLoopCommonModes]];
CGFloat offsetToMoveBy = (self.myCollectionView.contentOffset.x-previousOffset_Header)*(self.myScrollView.frame.size.width/150);
previousOffset_Scrollview = previousOffset_Scrollview +offsetToMoveBy;

[self.myScrollView setContentOffset:CGPointMake(previousOffset_Scrollview, self.myScrollView.contentOffset.y) animated:NO];
previousOffset_Header = self.myCollectionView.contentOffset.x;

}
}

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
}

@end









share|improve this question
















EDIT: I have attached a simple demo project dropbox link at bottom



I have a UI with a UICollectionView at top and a scrollview at the bottom. I want the scrolling in collectionview to scroll the scrollview too in sync. I have disabled user-interaction in scrollview so only the collectionview can effect the scrolling in it.



Each collectionview item is 150px for this testing purpose.



The UIViews in the scrollview are screen width in size. So for every scroll of a collectionview item, I need to scroll the scrollview by screen width. To achieve this, I am calculating the distance the collectionview offset has changed by and then dividing it by the cell width (150) and multiplying it by scrollview's width.



I am trying to achieve the following UI:



Start:



enter image description here



Scroll collectionview to cell 1:



enter image description here



Scroll collectionview to cell 2:



enter image description here



This all works fine the first few times but as I scroll the collectionview back and forth a few times to longer distances (let's say cell 10 -> 0 -> 10 -> 0 and so on), the scrollview goes out of sync by "tiny" distances. To illustrate this, notice how there is the "yellow" color from the second UIView on the right edge of the scrollview:



enter image description here



I can see this issue by NSLogging the contentOffset of the scrollview too (notice how it starts getting out of sync by 0.5 after few times):



2018-11-25 19:24:28.273278-0500 ScrollViewMatchTest[19412:1203912] Finished: 0
2018-11-25 19:24:31.606521-0500 ScrollViewMatchTest[19412:1203912] Finished: 0.5
2018-11-25 19:24:55.173709-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:03.007528-0500 ScrollViewMatchTest[19412:1203912] Finished: 1.5
2018-11-25 19:25:07.841096-0500 ScrollViewMatchTest[19412:1203912] Finished: 2.5
2018-11-25 19:26:57.634429-0500


I am not really sure what's causing this problem and I have tried quite a few ways to fix it but in vain. I can sort of figure out a workaround (to reset the offset and bring it back in sync when scrolling finishes) but I would like to know why exactly this out of sync issue is caused.





Workaround solution by resetting the contentOffset of scrollView to closes multiple of screen width:



-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if (scrollView==self.myCollectionView) {
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
NSLog(@"Closest: %g",RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width));
[self.myScrollView setContentOffset:CGPointMake(RoundTo(self.myScrollView.contentOffset.x, self.myScrollView.frame.size.width), self.myScrollView.contentOffset.y) animated:YES];
}
}

float RoundTo(float number, float to)
{
if (number >= 0) {
return to * floorf(number / to + 0.5f);
}
else {
return to * ceilf(number / to - 0.5f);
}
}


END OF WORKAROUND SOLUTION



I have attached a simple demo project to illustrate this issue as well (run the app and scroll back and forth aggresively on the top scrollview a few times): https://www.dropbox.com/s/e2bzgo6abq5wmgw/ScrollViewMatchTest.zip?dl=0



Here's the code:



#import "ViewController.h"
#define countOfItems 50

@interface ViewController (){
CGFloat previousOffset_Header;
CGFloat previousOffset_Scrollview;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self.myCollectionView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellWithReuseIdentifier:@"cell"];
[self.myCollectionView reloadData];

for (NSInteger i=0; i<countOfItems; i++) {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(i*self.myScrollView.frame.size.width, 0, self.myScrollView.frame.size.width, self.myScrollView.frame.size.height)];
myView.backgroundColor=i%2==0?[UIColor blueColor]:[UIColor yellowColor];
[self.myScrollView addSubview:myView];

}
self.myScrollView.contentSize=CGSizeMake(countOfItems*self.myScrollView.frame.size.width, self.myScrollView.frame.size.height);


}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return countOfItems;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = indexPath.item%2==0?[UIColor blueColor]:[UIColor yellowColor];
cell.myLabel.text=[NSString stringWithFormat:@"%ld",indexPath.item];

return cell;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
if (scrollView==self.myCollectionView) {
previousOffset_Header = self.myCollectionView.contentOffset.x;
previousOffset_Scrollview = self.myScrollView.contentOffset.x;
}
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{

if (scrollView==self.myCollectionView) {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:scrollView afterDelay:0.1 inModes:@[NSRunLoopCommonModes]];
CGFloat offsetToMoveBy = (self.myCollectionView.contentOffset.x-previousOffset_Header)*(self.myScrollView.frame.size.width/150);
previousOffset_Scrollview = previousOffset_Scrollview +offsetToMoveBy;

[self.myScrollView setContentOffset:CGPointMake(previousOffset_Scrollview, self.myScrollView.contentOffset.y) animated:NO];
previousOffset_Header = self.myCollectionView.contentOffset.x;

}
}

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"Finished: %g",self.myScrollView.contentOffset.x);
}

@end






ios iphone uiscrollview uicollectionview






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 26 '18 at 1:03







Pranoy C

















asked Nov 26 '18 at 0:47









Pranoy CPranoy C

4,18983561




4,18983561













  • So is the problem solved? If so, please answer your own question and accept your own answer.

    – matt
    Nov 26 '18 at 1:13











  • @matt it's not solved as my workaround works but 1. I would still like to know what the actual issue is and 2. The workaround doesn't look nice as you see the scrollView stop and then scroll a bit again to fix itself. So looks kind of ugly.

    – Pranoy C
    Nov 26 '18 at 1:27



















  • So is the problem solved? If so, please answer your own question and accept your own answer.

    – matt
    Nov 26 '18 at 1:13











  • @matt it's not solved as my workaround works but 1. I would still like to know what the actual issue is and 2. The workaround doesn't look nice as you see the scrollView stop and then scroll a bit again to fix itself. So looks kind of ugly.

    – Pranoy C
    Nov 26 '18 at 1:27

















So is the problem solved? If so, please answer your own question and accept your own answer.

– matt
Nov 26 '18 at 1:13





So is the problem solved? If so, please answer your own question and accept your own answer.

– matt
Nov 26 '18 at 1:13













@matt it's not solved as my workaround works but 1. I would still like to know what the actual issue is and 2. The workaround doesn't look nice as you see the scrollView stop and then scroll a bit again to fix itself. So looks kind of ugly.

– Pranoy C
Nov 26 '18 at 1:27





@matt it's not solved as my workaround works but 1. I would still like to know what the actual issue is and 2. The workaround doesn't look nice as you see the scrollView stop and then scroll a bit again to fix itself. So looks kind of ugly.

– Pranoy C
Nov 26 '18 at 1:27












2 Answers
2






active

oldest

votes


















0














Be aware in viewDidLoad method myScrollView frame is not really setted to the real device.



So in init of the view, the views's width and height might be wrong in your code.






share|improve this answer
























  • You are correct about the width's not correct in viewDidLoad and I fixed that to use viewDidLayoutSubviews. However this doesn't fix the actual issue of the offset's going out of sync, that still exists.

    – Pranoy C
    Nov 26 '18 at 4:10











  • Delete scrollViewWillBeginDragging method and init previousOffset_Header & previousOffset_Scrollview with 0 in videoDidLoad. It seems that system calls scrollViewWillBeginDragging is delayed.

    – Dan Lee
    Nov 26 '18 at 6:28



















0














There are a couple of things you should be doing differently, the way you calculate the offset and not using the UIScrollViewDelegate callbacks scrollViewDidEndDragging:willDecelerate: and scrollViewDidEndDecelerating:. I've rewritten the relevant code:



- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (scrollView==self.myCollectionView) {
[self calculateScrollviewOffset:self.myCollectionView];
}
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (scrollView == self.myCollectionView && !decelerate) {
[self calculateEndPosition: self.myCollectionView];
}
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView == self.myCollectionView) {
[self calculateEndPosition: self.myCollectionView];
}
}

- (void) calculateScrollviewOffset:(UICollectionView *) collectionView {
CGFloat cellWidth = 150.0;
CGFloat percentageMoved = collectionView.contentOffset.x / cellWidth;
[self setScrollViewOffset:percentageMoved animated:false];
}

- (void) calculateEndPosition:(UICollectionView*) collectionView {
CGFloat cellWidth = 150.0;
// NOTE: Add 0.5 to play around with the end animation positioning
CGFloat percentageMoved = floor(collectionView.contentOffset.x / cellWidth);
CGFloat collectionViewFixedOffset = (percentageMoved * cellWidth);
[collectionView setContentOffset:CGPointMake(collectionViewFixedOffset, collectionView.contentOffset.y) animated:true];
[self setScrollViewOffset:percentageMoved animated:true];
}

- (void) setScrollViewOffset:(CGFloat) percentageMoved animated:(BOOL) animated {
CGFloat newOffsetX = percentageMoved * self.myScrollView.frame.size.width;
[self.myScrollView setContentOffset:CGPointMake(newOffsetX, self.myScrollView.contentOffset.y) animated: animated];
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53473495%2fios-scrolling-one-uiscrollview-based-off-contentoffset-of-another-goes-out-of-sy%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    Be aware in viewDidLoad method myScrollView frame is not really setted to the real device.



    So in init of the view, the views's width and height might be wrong in your code.






    share|improve this answer
























    • You are correct about the width's not correct in viewDidLoad and I fixed that to use viewDidLayoutSubviews. However this doesn't fix the actual issue of the offset's going out of sync, that still exists.

      – Pranoy C
      Nov 26 '18 at 4:10











    • Delete scrollViewWillBeginDragging method and init previousOffset_Header & previousOffset_Scrollview with 0 in videoDidLoad. It seems that system calls scrollViewWillBeginDragging is delayed.

      – Dan Lee
      Nov 26 '18 at 6:28
















    0














    Be aware in viewDidLoad method myScrollView frame is not really setted to the real device.



    So in init of the view, the views's width and height might be wrong in your code.






    share|improve this answer
























    • You are correct about the width's not correct in viewDidLoad and I fixed that to use viewDidLayoutSubviews. However this doesn't fix the actual issue of the offset's going out of sync, that still exists.

      – Pranoy C
      Nov 26 '18 at 4:10











    • Delete scrollViewWillBeginDragging method and init previousOffset_Header & previousOffset_Scrollview with 0 in videoDidLoad. It seems that system calls scrollViewWillBeginDragging is delayed.

      – Dan Lee
      Nov 26 '18 at 6:28














    0












    0








    0







    Be aware in viewDidLoad method myScrollView frame is not really setted to the real device.



    So in init of the view, the views's width and height might be wrong in your code.






    share|improve this answer













    Be aware in viewDidLoad method myScrollView frame is not really setted to the real device.



    So in init of the view, the views's width and height might be wrong in your code.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 26 '18 at 4:02









    Dan LeeDan Lee

    215




    215













    • You are correct about the width's not correct in viewDidLoad and I fixed that to use viewDidLayoutSubviews. However this doesn't fix the actual issue of the offset's going out of sync, that still exists.

      – Pranoy C
      Nov 26 '18 at 4:10











    • Delete scrollViewWillBeginDragging method and init previousOffset_Header & previousOffset_Scrollview with 0 in videoDidLoad. It seems that system calls scrollViewWillBeginDragging is delayed.

      – Dan Lee
      Nov 26 '18 at 6:28



















    • You are correct about the width's not correct in viewDidLoad and I fixed that to use viewDidLayoutSubviews. However this doesn't fix the actual issue of the offset's going out of sync, that still exists.

      – Pranoy C
      Nov 26 '18 at 4:10











    • Delete scrollViewWillBeginDragging method and init previousOffset_Header & previousOffset_Scrollview with 0 in videoDidLoad. It seems that system calls scrollViewWillBeginDragging is delayed.

      – Dan Lee
      Nov 26 '18 at 6:28

















    You are correct about the width's not correct in viewDidLoad and I fixed that to use viewDidLayoutSubviews. However this doesn't fix the actual issue of the offset's going out of sync, that still exists.

    – Pranoy C
    Nov 26 '18 at 4:10





    You are correct about the width's not correct in viewDidLoad and I fixed that to use viewDidLayoutSubviews. However this doesn't fix the actual issue of the offset's going out of sync, that still exists.

    – Pranoy C
    Nov 26 '18 at 4:10













    Delete scrollViewWillBeginDragging method and init previousOffset_Header & previousOffset_Scrollview with 0 in videoDidLoad. It seems that system calls scrollViewWillBeginDragging is delayed.

    – Dan Lee
    Nov 26 '18 at 6:28





    Delete scrollViewWillBeginDragging method and init previousOffset_Header & previousOffset_Scrollview with 0 in videoDidLoad. It seems that system calls scrollViewWillBeginDragging is delayed.

    – Dan Lee
    Nov 26 '18 at 6:28













    0














    There are a couple of things you should be doing differently, the way you calculate the offset and not using the UIScrollViewDelegate callbacks scrollViewDidEndDragging:willDecelerate: and scrollViewDidEndDecelerating:. I've rewritten the relevant code:



    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if (scrollView==self.myCollectionView) {
    [self calculateScrollviewOffset:self.myCollectionView];
    }
    }

    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (scrollView == self.myCollectionView && !decelerate) {
    [self calculateEndPosition: self.myCollectionView];
    }
    }

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (scrollView == self.myCollectionView) {
    [self calculateEndPosition: self.myCollectionView];
    }
    }

    - (void) calculateScrollviewOffset:(UICollectionView *) collectionView {
    CGFloat cellWidth = 150.0;
    CGFloat percentageMoved = collectionView.contentOffset.x / cellWidth;
    [self setScrollViewOffset:percentageMoved animated:false];
    }

    - (void) calculateEndPosition:(UICollectionView*) collectionView {
    CGFloat cellWidth = 150.0;
    // NOTE: Add 0.5 to play around with the end animation positioning
    CGFloat percentageMoved = floor(collectionView.contentOffset.x / cellWidth);
    CGFloat collectionViewFixedOffset = (percentageMoved * cellWidth);
    [collectionView setContentOffset:CGPointMake(collectionViewFixedOffset, collectionView.contentOffset.y) animated:true];
    [self setScrollViewOffset:percentageMoved animated:true];
    }

    - (void) setScrollViewOffset:(CGFloat) percentageMoved animated:(BOOL) animated {
    CGFloat newOffsetX = percentageMoved * self.myScrollView.frame.size.width;
    [self.myScrollView setContentOffset:CGPointMake(newOffsetX, self.myScrollView.contentOffset.y) animated: animated];
    }





    share|improve this answer




























      0














      There are a couple of things you should be doing differently, the way you calculate the offset and not using the UIScrollViewDelegate callbacks scrollViewDidEndDragging:willDecelerate: and scrollViewDidEndDecelerating:. I've rewritten the relevant code:



      - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
      if (scrollView==self.myCollectionView) {
      [self calculateScrollviewOffset:self.myCollectionView];
      }
      }

      - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
      if (scrollView == self.myCollectionView && !decelerate) {
      [self calculateEndPosition: self.myCollectionView];
      }
      }

      - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
      if (scrollView == self.myCollectionView) {
      [self calculateEndPosition: self.myCollectionView];
      }
      }

      - (void) calculateScrollviewOffset:(UICollectionView *) collectionView {
      CGFloat cellWidth = 150.0;
      CGFloat percentageMoved = collectionView.contentOffset.x / cellWidth;
      [self setScrollViewOffset:percentageMoved animated:false];
      }

      - (void) calculateEndPosition:(UICollectionView*) collectionView {
      CGFloat cellWidth = 150.0;
      // NOTE: Add 0.5 to play around with the end animation positioning
      CGFloat percentageMoved = floor(collectionView.contentOffset.x / cellWidth);
      CGFloat collectionViewFixedOffset = (percentageMoved * cellWidth);
      [collectionView setContentOffset:CGPointMake(collectionViewFixedOffset, collectionView.contentOffset.y) animated:true];
      [self setScrollViewOffset:percentageMoved animated:true];
      }

      - (void) setScrollViewOffset:(CGFloat) percentageMoved animated:(BOOL) animated {
      CGFloat newOffsetX = percentageMoved * self.myScrollView.frame.size.width;
      [self.myScrollView setContentOffset:CGPointMake(newOffsetX, self.myScrollView.contentOffset.y) animated: animated];
      }





      share|improve this answer


























        0












        0








        0







        There are a couple of things you should be doing differently, the way you calculate the offset and not using the UIScrollViewDelegate callbacks scrollViewDidEndDragging:willDecelerate: and scrollViewDidEndDecelerating:. I've rewritten the relevant code:



        - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
        if (scrollView==self.myCollectionView) {
        [self calculateScrollviewOffset:self.myCollectionView];
        }
        }

        - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
        if (scrollView == self.myCollectionView && !decelerate) {
        [self calculateEndPosition: self.myCollectionView];
        }
        }

        - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        if (scrollView == self.myCollectionView) {
        [self calculateEndPosition: self.myCollectionView];
        }
        }

        - (void) calculateScrollviewOffset:(UICollectionView *) collectionView {
        CGFloat cellWidth = 150.0;
        CGFloat percentageMoved = collectionView.contentOffset.x / cellWidth;
        [self setScrollViewOffset:percentageMoved animated:false];
        }

        - (void) calculateEndPosition:(UICollectionView*) collectionView {
        CGFloat cellWidth = 150.0;
        // NOTE: Add 0.5 to play around with the end animation positioning
        CGFloat percentageMoved = floor(collectionView.contentOffset.x / cellWidth);
        CGFloat collectionViewFixedOffset = (percentageMoved * cellWidth);
        [collectionView setContentOffset:CGPointMake(collectionViewFixedOffset, collectionView.contentOffset.y) animated:true];
        [self setScrollViewOffset:percentageMoved animated:true];
        }

        - (void) setScrollViewOffset:(CGFloat) percentageMoved animated:(BOOL) animated {
        CGFloat newOffsetX = percentageMoved * self.myScrollView.frame.size.width;
        [self.myScrollView setContentOffset:CGPointMake(newOffsetX, self.myScrollView.contentOffset.y) animated: animated];
        }





        share|improve this answer













        There are a couple of things you should be doing differently, the way you calculate the offset and not using the UIScrollViewDelegate callbacks scrollViewDidEndDragging:willDecelerate: and scrollViewDidEndDecelerating:. I've rewritten the relevant code:



        - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
        if (scrollView==self.myCollectionView) {
        [self calculateScrollviewOffset:self.myCollectionView];
        }
        }

        - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
        if (scrollView == self.myCollectionView && !decelerate) {
        [self calculateEndPosition: self.myCollectionView];
        }
        }

        - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        if (scrollView == self.myCollectionView) {
        [self calculateEndPosition: self.myCollectionView];
        }
        }

        - (void) calculateScrollviewOffset:(UICollectionView *) collectionView {
        CGFloat cellWidth = 150.0;
        CGFloat percentageMoved = collectionView.contentOffset.x / cellWidth;
        [self setScrollViewOffset:percentageMoved animated:false];
        }

        - (void) calculateEndPosition:(UICollectionView*) collectionView {
        CGFloat cellWidth = 150.0;
        // NOTE: Add 0.5 to play around with the end animation positioning
        CGFloat percentageMoved = floor(collectionView.contentOffset.x / cellWidth);
        CGFloat collectionViewFixedOffset = (percentageMoved * cellWidth);
        [collectionView setContentOffset:CGPointMake(collectionViewFixedOffset, collectionView.contentOffset.y) animated:true];
        [self setScrollViewOffset:percentageMoved animated:true];
        }

        - (void) setScrollViewOffset:(CGFloat) percentageMoved animated:(BOOL) animated {
        CGFloat newOffsetX = percentageMoved * self.myScrollView.frame.size.width;
        [self.myScrollView setContentOffset:CGPointMake(newOffsetX, self.myScrollView.contentOffset.y) animated: animated];
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 26 '18 at 6:53









        OrgmirOrgmir

        31538




        31538






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53473495%2fios-scrolling-one-uiscrollview-based-off-contentoffset-of-another-goes-out-of-sy%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            404 Error Contact Form 7 ajax form submitting

            How to know if a Active Directory user can login interactively

            TypeError: fit_transform() missing 1 required positional argument: 'X'