UIScrollView внутри UITableViewCell Touch Detect - PullRequest
22 голосов
/ 09 июля 2011

У меня есть таблица с 8 пользовательскими ячейками. в восьмой ячейке я добавил scrollView с включенной подкачкой, чтобы я мог показывать страницы 1 и 2 (или 3, 4 ... 10) без очень высокой ячейки.

Проблема с scrollView. Я не могу использовать didSelectRowAtIndexPath, потому что ячейка находится за scrollView, поэтому я пытаюсь обнаружить касание scrollView (не смахивание).

Я играл с прикосновениями Bean и touchesEnded, но они никогда не называются (я знаю, прикосновения работают только с UIView, но может быть .....)

Любая помощь очень ценится.

Спасибо, Max

Ответы [ 5 ]

77 голосов
/ 18 июня 2014

В этом случае Apple рекомендует использовать один трюк: Сессия WWDC 2014"Расширенные просмотры прокрутки" (см. Демонстрацию, начиная с 8:10):

[cell.contentView addSubview:_scrollView];
[_scrollView setUserInteractionEnabled:NO];
[cell.contentView addGestureRecognizer:_scrollView.panGestureRecognizer];

Этовсе, что нужно сделать, не нужно переопределять touchesBegan:, touchesMoved: и др.


Я использовал решение, основанное на переопределении touchesBegan:, touchesMoved:, touchesEnded: и touchesCancelled: ранее, но иногда это вызывало странное поведение: при выборе определенной ячейки вызывался метод -tableView:didSelectRowAtIndexPath: для ячейки с другим indexPath.

Решение от Apple пока не имеет побочных эффектов и выглядит более элегантно.

14 голосов
/ 15 апреля 2014

Существует также элегантное разрешение:

Создать подкласс из UIScrollView и переопределить следующие методы

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesMoved:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesCancelled:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[self superview]touchesEnded:touches withEvent:event];
}

Передача каждого прикосновения к суперпредставлению вида прокрутки, а затем вызывается didSelectRowAtIndexPath.

5 голосов
/ 10 июля 2011

Решено создание подклассов как uitableviewcell, так и uiscrollview.

Это сработало для моих нужд.Надеюсь, что это поможет.

Макс


myScrollView.h


#import <UIKit/UIKit.h>
@interface myScrollView : UIScrollView {
}

@end

myScrollView.m


#import "myScrollView.h"
@implementation myScrollView


- (id)initWithFrame:(CGRect)frame {

    return [super initWithFrame:frame];
}

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event 
{   
    NSLog(@"touch scroll");
    // If not dragging, send event to next responder
    if (!self.dragging) 
        [self.nextResponder touchesEnded: touches withEvent:event]; 
    else
        [super touchesEnded: touches withEvent: event];
}

myCell.h


#import <UIKit/UIKit.h>


@interface myCell : UITableViewCell {

}

@end

myCell.m



#import "myCell.h"


@implementation myCell


- (id)initWithFrame:(CGRect)frame {

    return [super initWithFrame:frame];
}

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event 
{   
    NSLog(@"touch cell");
    // If not dragging, send event to next responder
    [super touchesEnded: touches withEvent: event];
}

RootViewController.h



#import <UIKit/UIKit.h>

@class myCell;
@class myScrollView;

@interface RootViewController : UITableViewController {

    myCell *cell;
    myScrollView *scrollView;
}

@end

RootViewController.m



#pragma mark -
#pragma mark Table view data source

// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 3;
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    // my custom cell
    cell = [[myCell alloc] init];
    if (cell == nil) {
        cell = [[[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }


    // the custom scroll view
    scrollView = [[myScrollView alloc] initWithFrame:cell.frame];
    scrollView.contentSize = CGSizeMake(640, 40);
    [cell.contentView addSubview:scrollView];

    //something to add in scrollView
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 20)];
    label.text = @"some text";
    [scrollView addSubview:label];

    // Configure the cell.

    return cell;
}
4 голосов
/ 05 марта 2014

Выбранный ответ правильный, но я обновил код, основываясь на полученной ошибке.

В виде прокрутки в подклассах добавьте следующий код.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.dragging) {
        [super touchesMoved:touches withEvent:event];
    } else {
        if ([self.delegate isKindOfClass:[UITableViewCell class]]) {
            [(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event];
        }

        [self.superview touchesMoved:touches withEvent:event];
    }
}

Если ваш self.delegate не является UITableViewCell, тогда замените это свойство свойством для вашей ячейки.

Ячейка должна получить событие отмены касания во время движения, чтобы предотвратить нежелательные результаты. Это может быть легко воспроизведено следующим образом.

  • Подсветка ячейки (при условии, что представление прокрутки расположено над всей ячейкой, если не выделено представление прокрутки)
  • Пока ячейка выделена, перетащите табличное представление
  • Выберите любую другую ячейку, и теперь ранее выделенная ячейка получит состояние didSelectCell

Еще один момент, о котором стоит упомянуть, это то, что порядок имеет значение! Если self.delegate не вызывается до self.superview, то выделенное состояние не произойдет.

0 голосов
/ 03 октября 2015

Я нашел самое простое решение для своих нужд:

подкласс UIScrollView метод touchesEnded и отправка уведомления.

В UITableview добавьте наблюдателя в viewdidAppear (удалите его в viewdiddisappear), чтобы вызватьфункция, которая вызывает tableview didSelectRowForIndexPath.

Как-то так (быстрая версия)

// myScrollView.swift

import UIKit

class myScrollView: UIScrollView {
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
            NSNotificationCenter.defaultCenter().postNotificationName("selectTVRow", object: nil)
    }
}

В вашем табличном представлении:

// ItemsList.swift

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "selectFourthRow", name: "selectTVRow", object: nil)
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: "selectfourthrow", object: nil)
    }

    func selectFourthRow() {
        let rowToSelect:NSIndexPath = NSIndexPath(forRow: 4, inSection: 0);
        self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect);
    }

    /*
    .... rest of your tableview Datasource and Delegate methods...
    numberOfSectionsInTableView, numberOfRowsInSection, cellForRowAtIndexPath
    */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...