Горизонтальный UIScrollView внутри UITableViewCell - PullRequest
36 голосов
/ 01 декабря 2010

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

21 голосов
/ 01 декабря 2010

Я нашел обходной путь.

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

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

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

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

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

...