UITableViewCell内的水平UIScrollView

时间:2010-12-01 12:49:01

标签: iphone uitableview uiscrollview scroll

我正在尝试创建与用于查看屏幕截图的AppStore应用程序完全相同的效果:在UITableView中,我有UITableViewCell的自定义子类。其中一个旨在显示某些产品的预览,比如4个图像。我希望它们的显示方式与AppStore显示应用程序的屏幕截图相同:在水平UIScrollView中,附带UIPageControl。

所以我将我的UIScrollView和我的UIPageControl添加到我的UITableViewCell,就像那样:

@implementation phVolumePreviewCell
- (id)init {
    if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kVolumePreviewCellIdentifier]) {
        [self setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
        [self setSelectionStyle:UITableViewCellSeparatorStyleNone];

        previews = [[NSMutableArray alloc] initWithCapacity:4];
        for (int i = 0; i < 4; i++) {
            [previews addObject:@"dummy"];
        }

        scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
        [scrollView setPagingEnabled:YES];
        [scrollView setBackgroundColor:[UIColor grayColor]];
        [scrollView setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
        [scrollView setShowsHorizontalScrollIndicator:YES];
        [scrollView setBounces:YES];
        [scrollView setScrollEnabled:YES];
        [scrollView setDelegate:self];
        [self.contentView addSubview:scrollView];
        [scrollView release];

        pageControl = [[UIPageControl alloc] initWithFrame:CGRectZero];
        [pageControl setNumberOfPages:[previews count]];
        [pageControl setBackgroundColor:[UIColor grayColor]];
        [self.contentView addSubview:pageControl];
        [pageControl release];
    }
    return self;
}

(注意:我在这里用虚拟数据填充“预览”,只是为了让[预览计数]有效;我想查看scrollView的滚动指示器仅用于测试目的,我稍后会隐藏它们上)。

我的问题是我可以滚动包含这个phVolumePreviewCell(UITableViewCell的子类)的整个UITableView,但我无法滚动UIScrollView。我怎样才能做到这一点?

我找到的唯一信息是:http://theexciter.com/articles/touches-and-uiscrollview-inside-a-uitableview.html 但是它讨论了旧的SDK(即2.2),我确信有一种更“近期”的做法。

一些准确性:

  • 我可以用两根手指滚动UIScrollView。这不是我想要的,我希望它只能用一根手指滚动。
  • 当我用两根手指滚动时,TableView仍会截取触摸并向顶部或底部滚动一点。当我触摸ScrollView时,我希望TableView坚持它的位置。

我相信我必须弄清楚如何拦截我的TableView上的触摸,如果触摸是在phVolumePreviewCell(自定义UITableViewCell子类)上,则将其传递给单元格而不是在TableView上处理它。

为了记录,我的TableView是在UITableViewController子类中以编程方式创建的:

@interface phVolumeController : UITableViewController <UITableViewDelegate> {
    LocalLibrary *lib;
        NSString *volumeID;
        LLVolume *volume;
}

- (id)initWithLibrary:(LocalLibrary *)newLib andVolumeID:(NSString *)newVolumeID;
@end

@implementation phVolumeController

#pragma mark -
#pragma mark Initialization

- (id)initWithLibrary:(LocalLibrary *)newLib andVolumeID:(NSString *)newVolumeID {
    if (self = [super initWithStyle:UITableViewStylePlain]) {
        lib          = [newLib retain];
        volumeID     = newVolumeID;
        volume       = [(LLVolume *)[LLVolume alloc] initFromLibrary:lib forID:volumeID];
        [[self navigationItem] setTitle:[volume title]];
    }
    return self;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kVolumePreviewCellIdentifier];
    if (cell == nil) {
        cell = [[[phVolumePreviewCell alloc] init] autorelease];
    }

    [(phVolumePreviewCell *)cell setVolume:volume];
    return (UITableViewCell *)cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return kVolumePreviewCellHeight;
}

感谢您的帮助!

1 个答案:

答案 0 :(得分:21)

我找到了解决方法。

从头开始重新创建一个非常简单的UITableView(8行),并在第二行插入UIScrollView,效果非常好。嵌套滚动视图(TableView和ScrollView)按预期独立滚动。所有这些都是在AppDelegate的单文件测试项目中完成的。

所以...首先我认为“这可能是一个委托问题”,所以我告诉scrollView它的委托是TableView,而不是我的自定义TableViewCell子类。无济于事。

然后,我不再采用只添加ScrollView和PageControl的自定义干净的TableViewCell子类,而是使用TableView的cellForRowAtIndexPath:方法创建一个普通的TableViewCell。然后,我在初始化TableViewCell之后立即创建一个UIScrollView,然后将它添加到TableViewCell,然后shazam ......它可以工作!

在:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kVolumePreviewCellIdentifier];
if (cell == nil) {
    cell = [[[phVolumePreviewCell alloc] init] autorelease];
}

[(phVolumePreviewCell *)cell setVolume:volume];
// That does the job of creating the cell's scrollView and pageControl

return (UITableViewCell *)cell

后:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kvcPreviewRowIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kvcPreviewRowIdentifier] autorelease];

    previewScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, kvcPreviewScrollViewHeight)];
    [previewScrollView setContentSize:CGSizeMake(1000, kvcPreviewScrollViewHeight)];
    [[cell contentView] addSubview:previewScrollView];

    previewPageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, kvcPreviewScrollViewHeight, tableView.frame.size.width, kvcPreviewPageControlHeight)];
    [previewPageControl setNumberOfPages:4];
    [[cell contentView] addSubview:previewPageControl];
}

return (UITableViewCell *)cell;

当我从TVCell子类创建scrollView时,它是如何产生的,它不会很好;但是当我在创建“经典”TVCell之后立即从TableView创建scrollView时,它有效吗?

我可能已经找到了解决方案,但我仍然对原因感到困惑。