【问题标题】:Horizontal UIScrollView inside a UITableViewCellUITableViewCell 内的水平 UIScrollView
【发布时间】:2011-05-18 11:50:29
【问题描述】:

我正在尝试创建与在 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;
}

感谢您的帮助!

【问题讨论】:

    标签: iphone uitableview uiscrollview scroll


    【解决方案1】:

    我找到了解决方法。

    从头开始重新创建一个非常简单的 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 子类创建我的滚动视图时,它怎么会玩得不好;但是当我在创建“经典”TVCell 后立即从 TableView 创建滚动视图时,它可以工作吗?

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

    【讨论】:

    • 谢谢西里尔!!这里同样的问题。您的解决方案在绝望中为我节省了很多时间! :-)
    • 嗨 Cyrille - 我知道这是一个古老的 SO 问题,但我想知道您是否有此解决方案的示例应用程序?谢谢..
    • @Craig:没有示例应用,抱歉。从那时起,这段代码就发生了变化,我不再使用它了。但实际上,重现这种情况所需的所有代码都在我的帖子中。
    • 不用担心 - 我得到一个卡住的子类 UITableViewCell 就是这样!欣赏,否则它已经在那里了。谢谢!
    • 谢谢,我遇到了同样的问题,用这个技巧很好地解决了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 2013-10-11
    • 2016-09-07
    • 2013-03-29
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多