Горизонтальный UIScrollView внутри UITableViewCell

Я пытаюсь создать тот же эффект, что и в приложении 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 только для тестовых целей, я их скрою позже далее).

Моя проблема в том, что я могу прокрутить весь UITableView, содержащий этот phVolumePreviewCell (подкласс UITableViewCell), но я не могу прокрутить UIScrollView. Как я могу достичь этого?

Единственная найденная мной информация: http://theexciter.com/articles/touches-and-uiscrollview-inside-a-uitableview.html Но он говорит о старых SDK (а именно, 2.2), и я уверен, что для этого существует более "недавний" подход.

Некоторые замечания:

  • Я могу прокрутить UIScrollView двумя пальцами. Это не то, что я хочу, я хочу, чтобы он мог прокручивать только одним пальцем.
  • Когда я прокручиваю двумя пальцами, TableView по-прежнему перехватывает касания и немного прокручивается вверх или вниз. Я бы хотел, чтобы TableView придерживался своего положения, когда я касаюсь ScrollView.

Я считаю, что мне нужно разобраться, как перехватывать штрихи на моем 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

Я нашел обходное решение.

Восстанавливая с нуля очень простой UITableView (8 строк) и вставляя UIScrollView только во вторую строку, отлично работает. Вложенные представления прокрутки (TableView и ScrollView) прокручиваются независимо, как и ожидалось. Все, что было сделано в однофайловом тестовом проекте, в AppDelegate.

Итак... сначала я подумал: "Это может быть проблема с делегацией", поэтому я сказал scrollView, что его делегатом был TableView, а не мой собственный подкласс TableViewCell. Безрезультатно.

Затем вместо использования специального, чистого подкласса TableViewCell, который просто добавляет ScrollView и PageControl, я прибегал к созданию простого TableViewCell в методе cellViewRightAtIndexPath: TableView. Затем я создаю UIScrollView сразу после инициализации TableViewCell, а затем добавляю его в 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 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;

Как получается, когда я создаю свой scrollView из подкласса TVCell, он не играет хорошо; но когда я создаю scrollView из TableView сразу после создания "классического" TVCell, он работает?

Я мог бы найти решение, но я все еще озадачен причиной.