UITableViewCell中的UIScrollview和维护滚动页面

我有UITableViewCell中的UIScrollView能够滚动单元格内的图像。 但是,当单元格被重用时,滚动位置/内容被重新加载,因此单元格不再记住当它再次进入视图时滚动的位置(页面)。

在UITableView单元格中拥有滚动视图的最佳方式是什么?当它重新回到视图中时,保持它的位置。 AirBnB应用程序( https://itunes.apple.com/us/app/airbnb/id401626263?mt=8 )似乎已经完成了这个例子。

你需要跟踪你的滚动视图的内容偏移在一个属性。 在下面的例子中,我用一个可变的字典来做这个。 在cellForRowAtIndexPath:中,我给滚动视图一个标记,并将控制器设置为委托。 在滚动视图委托方法scrollViewDidEndDecelerating中,滚动视图的内容偏移量被设置为对应于滚动视图标签的键的对象。 在cellForRowAtIndexPath:中,我检查indexPath.row(转换为NSNumber)是否是字典键之一,如果是,则恢复该滚动视图的正确偏移量。 我给标记添加1的原因是因为表视图有自己的滚动视图,其标签为0,所以我不想使用0作为单元格的一个滚动视图的标记。

所以在cellForRowAtIndexPath,你需要这样的东西:

cell.scrollView.tag = indexPath.row + 1; cell.scrollView.delegate = self; if ([self.paths.allKeys containsObject:@(indexPath.row + 1)]) { cell.scrollView.contentOffset = CGPointMake([self.paths[@(indexPath.row + 1)] floatValue],0); }else{ cell.scrollView.contentOffset = CGPointZero; } return cell; 

而在委托方法中:

 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView.tag != 0) [self.paths setObject:@(scrollView.contentOffset.x) forKey:@(scrollView.tag)]; } 

path是我在viewDidLoad中创build的属性(NSMutableDictionary)。

使用我的tableView海关单元格

homeScrollCell.h

 #import <UIKit/UIKit.h> #import "MyManager.h" @interface homeScrollCell : UITableViewCell<UIScrollViewDelegate> { MyManager *manager; UIScrollView *__scrollView; } -(void)setPage:(int)page; @property int currentPage; @end 

homeScrollCell.m

 #import "homeScrollCell.h" @implementation homeScrollCell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { manager=[MyManager sharedManager]; __scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width,self.bounds.size.height)]; [__scrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight]; NSInteger viewcount= 3; for(int i = 0; i< viewcount; i++) { CGFloat x = i * self.bounds.size.width; UIView *view = [[UIView alloc] initWithFrame:CGRectMake(x, 0,self.bounds.size.width,self.bounds.size.height)]; [view setAutoresizingMask:UIViewAutoresizingFlexibleHeight]; UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(50, 20, 200, 50)]; [label setBackgroundColor:[UIColor redColor]]; label.text=[NSString stringWithFormat:@"Hi, I am label %i",i]; [view addSubview:label]; view.backgroundColor = [UIColor greenColor]; [__scrollView addSubview:view]; } [__scrollView setBackgroundColor:[UIColor redColor]]; __scrollView.contentSize = CGSizeMake(self.bounds.size.width *viewcount, 100); __scrollView.pagingEnabled = YES; __scrollView.bounces = NO; __scrollView.delegate=self; [self addSubview:__scrollView]; // Initialization code } return self; } -(void)setPage:(int)page { CGFloat pageWidth = __scrollView.frame.size.width; float offset_X=pageWidth*page; [__scrollView setContentOffset:CGPointMake(offset_X, __scrollView.contentOffset.y)]; _currentPage=page; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { static NSInteger previousPage = 0; CGFloat pageWidth = scrollView.frame.size.width; float fractionalPage = scrollView.contentOffset.x / pageWidth; NSInteger page = lround(fractionalPage); if (previousPage != page) { _currentPage=page; [manager setpage:_currentPage ForKey:[NSString stringWithFormat:@"%i",self.tag]]; previousPage = page; } } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } @end 

并使用Singleton文件保存单元格内的logging或页面。

MyManager.h

 #import <Foundation/Foundation.h> @interface MyManager : NSObject + (id)sharedManager; -(void)setpage:(int)page ForKey:(NSString*)key; -(int)getpageForKey:(NSString*)key; @end 

MyManager.m

 #import "MyManager.h" static NSMutableDictionary *dictionary; @implementation MyManager #pragma mark Singleton Methods + (id)sharedManager { static MyManager *sharedMyManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedMyManager = [[self alloc] init]; }); return sharedMyManager; } -(void)setpage:(int)page ForKey:(NSString*)key { [dictionary setValue:[NSString stringWithFormat:@"%i",page] forKey:key]; } -(int)getpageForKey:(NSString*)key { return [[dictionary valueForKey:key] intValue]; } - (id)init { if (self = [super init]) { dictionary=[[NSMutableDictionary alloc] init]; } return self; } - (void)dealloc { // Should never be called, but just here for clarity really. } @end 

在cellForRow中使用这个自定义单元格

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Home Scroll Cell"; homeScrollCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell==nil) { cell = [[homeScrollCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } cell.tag=indexPath.row; [cell setPage:[manager getpageForKey:[NSString stringWithFormat:@"%i",indexPath.row]]]; return cell; } 

在CustomCell中设置你的页面,滚动和滚动之后返回到上一个位置将显示你在滚动之前设置的页面。 它会坚持你的页面移动。

下载并运行

rdelmar的答案是缺less的东西。 只有当用户滚动触发减速行为时,才会调用scrollViewDidEndDecelerating

只拖动滚动将不会调用此方法,因此您将得到不区分这两种滚动types的用户不一致的行为。 你需要用scrollViewDidEndDragging:willDecelerate来捕捉它

 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { self.tableCellContentOffsets[@(scrollView.tag)] = @(scrollView.contentOffset.x); } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { self.tableCellContentOffsets[@(scrollView.tag)] = @(scrollView.contentOffset.x); }