我在 UITableViewCell 中有一个 UIScrollView ,用于滚动单元格内的图像。然而,当一个单元格被重用时,滚动位置/内容被重新加载,因此当它再次进入视图时,单元格不记得它所在的滚动位置(页面)。
在 UITableView 单元格中拥有滚动视图并让它在返回视图时保持位置的最佳方式是什么。例如,AirBnB 应用程序 ( https://itunes.apple.com/us/app/airbnb/id401626263?mt=8 ) 似乎已经实现了这一点。
我在 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)];
}
路径是我在 viewDidLoad 中创建的一个属性 (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
并使用单例文件在单元格内保存记录或页面。
我的经理.h
#import <Foundation/Foundation.h>
@interface MyManager : NSObject
+ (id)sharedManager;
-(void)setpage:(int)page ForKey:(NSString*)key;
-(int)getpageForKey:(NSString*)key;
@end
我的经理.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 的答案缺少一些东西。scrollViewDidEndDecelerating
只有当用户滚动触发减速行为时才会调用。
仅拖动滚动不会调用此方法,因此对于无法区分两种滚动类型的用户,您将获得不一致的行为。你需要抓住它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);
}