Подтвердить что ты не робот

UIScrollView внутри сенсорного обнаружения UITableViewCell

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

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

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

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

Спасибо, Макс

4b9b3361

Ответ 1

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

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

В 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)
    }
}

В таблице tableView:

// 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
    */

Ответ 2

Существует трюк, который 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 пока не имеет побочных эффектов и выглядит более элегантно.

Ответ 3

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

Создайте SubClass из 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.

Ответ 4

Решено подклассификация как uitableviewcell, так и uiscrollview.

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

Max


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;
}

Ответ 5

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

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

- (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, тогда выделенное состояние не будет.