iOS Scrolling one UIScrollView based off contentOffset of another goes out of sync
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:
Scroll collectionview to cell 1:
Scroll collectionview to cell 2:
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:
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
add a comment |
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:
Scroll collectionview to cell 1:
Scroll collectionview to cell 2:
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:
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
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
add a comment |
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:
Scroll collectionview to cell 1:
Scroll collectionview to cell 2:
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:
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
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:
Scroll collectionview to cell 1:
Scroll collectionview to cell 2:
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:
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
ios iphone uiscrollview uicollectionview
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
add a comment |
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
add a comment |
2 Answers
2
active
oldest
votes
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.
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
DeletescrollViewWillBeginDragging
method and initpreviousOffset_Header
&previousOffset_Scrollview
with 0 invideoDidLoad
. It seems that system callsscrollViewWillBeginDragging
is delayed.
– Dan Lee
Nov 26 '18 at 6:28
add a comment |
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];
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
DeletescrollViewWillBeginDragging
method and initpreviousOffset_Header
&previousOffset_Scrollview
with 0 invideoDidLoad
. It seems that system callsscrollViewWillBeginDragging
is delayed.
– Dan Lee
Nov 26 '18 at 6:28
add a comment |
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.
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
DeletescrollViewWillBeginDragging
method and initpreviousOffset_Header
&previousOffset_Scrollview
with 0 invideoDidLoad
. It seems that system callsscrollViewWillBeginDragging
is delayed.
– Dan Lee
Nov 26 '18 at 6:28
add a comment |
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.
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.
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
DeletescrollViewWillBeginDragging
method and initpreviousOffset_Header
&previousOffset_Scrollview
with 0 invideoDidLoad
. It seems that system callsscrollViewWillBeginDragging
is delayed.
– Dan Lee
Nov 26 '18 at 6:28
add a comment |
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
DeletescrollViewWillBeginDragging
method and initpreviousOffset_Header
&previousOffset_Scrollview
with 0 invideoDidLoad
. It seems that system callsscrollViewWillBeginDragging
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
add a comment |
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];
}
add a comment |
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];
}
add a comment |
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];
}
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];
}
answered Nov 26 '18 at 6:53
OrgmirOrgmir
31538
31538
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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