РЕДАКТИРОВАТЬ: я прикрепил простую ссылку dropbox демонстрационного проекта внизу
У меня есть пользовательский интерфейс с UICollectionView вверху и прокрутки внизу.Я хочу, чтобы прокрутка в коллекционном просмотре прокручивала прокрутку тоже синхронно.Я отключил взаимодействие с пользователем в просмотре прокрутки, чтобы только прокрутка в нем могла влиять на прокрутку в нем.
Каждый элемент коллекционного просмотра имеет 150 пикселей для этой цели тестирования.
UIViews в просмотре прокрутки - это ширина экрана вразмер.Таким образом, для каждой прокрутки элемента коллекции необходимо прокрутить прокрутку по ширине экрана.Чтобы достичь этого, я вычисляю расстояние, на которое изменилось смещение коллекционного вида, а затем делю его на ширину ячейки (150) и умножаю на ширину scrollview.
Я пытаюсь получить следующий интерфейс:
Начало:
Прокрутить представление коллекции в ячейку 1:
Прокрутите представление коллекции в ячейку 2:
Все это отлично работает первые несколько раз, но когда я прокручиваю представление коллекции назад и вперед несколькоВ разы на большие расстояния (скажем, ячейка 10 -> 0 -> 10 -> 0 и т. д.), просмотр прокрутки не синхронизируется на «крошечные» расстояния.Чтобы проиллюстрировать это, обратите внимание, что есть «желтый» цвет из второго UIView на правом краю прокрутки:
Я вижу этопроблема с NSLogging contentOffset просмотра scrollview (обратите внимание, как он начинает выходить из синхронизации на 0,5 после нескольких раз):
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
Я не совсем уверен, что является причиной этой проблемы, и я пробовал довольно многоспособы это исправить но зря.Я могу как-то найти обходной путь (чтобы сбросить смещение и вернуть его в синхронизацию после завершения прокрутки), но я хотел бы знать, почему именно эта проблема вызвана несинхронизацией.
Обходное решение путем сброса contentOffset scrollView для закрытия, кратного ширине экрана:
-(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);
}
}
КОНЕЦ РАБОЧЕГО РЕШЕНИЯ
Я приложил простую демонстрациюПроект, чтобы проиллюстрировать эту проблему также (запустите приложение и несколько раз агрессивно прокручивайте взад-вперед на верхнем свитке): https://www.dropbox.com/s/e2bzgo6abq5wmgw/ScrollViewMatchTest.zip?dl=0
Вот код:
#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