web-dev-qa-db-ja.com

UITableViewCell内の水平方向のUIScrollView

AppStoreアプリでスクリーンショットを表示するのとまったく同じ効果を作成しようとしています。UITableView内に、UITableViewCellのカスタムサブクラスがあります。それらの1つは、たとえば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)と私について話しますこれを行うには、より「最近の」アプローチがあると確信しています。

いくつかの精度:

  • 2本の指でUIScrollViewをスクロールできます。それは私が望んでいることではなく、1本の指だけでスクロールできるようにしたいのです。
  • 2本の指でスクロールしても、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;
}

助けてくれてありがとう!

36
Cyrille

回避策を見つけました。

非常に単純なUITableView(8行)を最初から再作成し、2行目にのみUIScrollViewを挿入すると、完全に機能します。ネストされたスクロールビュー(TableViewとScrollView)は、期待どおりに独立してスクロールします。これはすべて、AppDelegateの単一ファイルのテストプロジェクトで行われました。

だから...最初に「これは委任の問題かもしれない」と思ったので、スクロールビューに、デリゲートはカスタムのViewViewCellサブクラスではなくTableViewであると伝えました。無駄に。

次に、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を作成すると、Niceが再生されないのはなぜですか。しかし、「クラシック」TVCellを作成した直後にTableViewからscrollViewを作成すると、機能しますか?

私は解決策を見つけたかもしれませんが、その理由にはまだ戸惑っています。

21
Cyrille