在UITableViewCell中的UIScrollview并维护scrollview页面

时间:2013-08-14 04:58:47

标签: ios uitableview uiscrollview

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

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

3 个答案:

答案 0 :(得分:2)

您需要在属性中跟踪滚动视图的内容偏移量。在下面的示例中,我使用可变字典执行此操作。在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)];
}

paths是我在viewDidLoad中创建的属性(NSMutableDictionary)。

答案 1 :(得分:0)

使用我的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文件将记录或页面保留在单元格内。

<强> 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中设置页面并滚动,重新滚动后返回上一个位置将显示您在滚动前设置的页面。 它将保持您的页面原样移动。

Download And Run

答案 2 :(得分:0)

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);
}