UITableViewCell内的水平UIScrollView

36

我正在尝试创建与AppStore应用程序中查看屏幕截图相同的效果:在UITableView内,我有自定义的UITableViewCell子类。其中之一旨在显示某个产品的预览,例如4张图片。我希望它们以与AppStore呈现应用程序屏幕截图相同的方式显示:在具有附加UIPageControl的水平UIScrollView内。

因此,我将我的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个回答

20

我找到了一个解决方法。

重新创建一个非常简单的UITableView(8个行),并在第二行中插入一个UIScrollView,可以完美地工作。嵌套的滚动视图(TableView和ScrollView)按预期独立滚动。所有这些都在一个单文件测试项目中完成,位于AppDelegate中。

所以...一开始我认为“这可能是委托问题”,所以我告诉scrollView它的委托是TableView,而不是我的自定义TableViewCell子类。但没有用。

然后,我没有使用只添加ScrollView和PageControl的自定义干净的TableViewCell子类,而是在TableView的cellForRowAtIndexPath:方法中创建一个普通的TableViewCell。然后,在初始化TableViewCell之后,我创建一个UIScrollView,将其添加到TableViewCell中,然后就可以正常工作了!

之前的代码:

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时,它就可以工作呢?

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


谢谢Cyrille!!我也遇到了同样的问题。你的解决方案让我在绝望中节省了很多时间!! :-) - Di Wu
嗨,Cyrille - 我知道这是一个旧的SO问题,但我想知道你是否有这个解决方案的示例应用程序?谢谢。 - Craig
@Craig:抱歉,没有示例应用程序。自那时以来,这段代码已经发展了,我不再使用它了。但是,你需要重现这种情况的所有代码都在我的帖子中。 - Cyrille
不用担心 - 我卡在继承UITableViewCell这一步了!感谢你,其他部分都已经完成了。谢谢! - Craig
谢谢,我也遇到了同样的问题,并且用这个技巧成功地解决了。 - John
谢谢。由于某种未知原因,我无法在Storyboard中的单元格内添加ScrollView。我通过编程方式实现了它,一切都正常工作。 - Beto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接