Как украсть штрихи из UIScrollView? - PullRequest
38 голосов
/ 07 января 2011

Сегодня в свое творческое время я провел довольно всеобъемлющее исследование о том, как украсть касания из UIScrollView и мгновенно отправить их в конкретное подпредставление, сохраняя при этом поведение по умолчанию для остальной части представления прокрутки. Рассмотрите возможность использования UIPickerView внутри UITableView. Поведение по умолчанию состоит в том, что, если вы проведете пальцем по виду средства выбора, представление прокрутки будет прокручиваться, и представление средства выбора останется неизменным.

Первым делом я попытался переопределить

- (BOOL)touchesShouldCancelInContentView:(UIView *)view

и просто не разрешать UIScrollView отменять касания в представлении выбора. Это работает, но имеет неприятный побочный эффект. Вы хотите, чтобы окно выбора отвечало незамедлительно, и поэтому вам придется установить delaysContentTouches на NO. Проблема в том, что вы не хотите, чтобы остальная часть табличного представления реагировала немедленно, потому что если это произойдет, ячейка табличного представления будет всегда подсвечиваться в течение нескольких миллисекунд до начала прокрутки.

Второе, что я попробовал, это переопределить

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

потому что я прочитал, что представление прокрутки всегда возвращает себя, так что оно «украдет» прикосновения из своих подпредставлений и позже отправит их в подпредставление, если они не были интересны представлению прокрутки. Однако это уже не так. Реализация по умолчанию hitTest: withEvent: UIScrollView по умолчанию возвращает подпредставление, которое должно получить прикосновение. Вместо этого он использует распознаватели жестов для перехвата касаний.

Итак, третье, что я пытался сделать, - это внедрить свой собственный распознаватель жестов и вызвать его сбой, если касание находилось за пределами окна выбора и, в противном случае, было успешным. Затем я установил все распознаватели жестов представления прокрутки на сбой, если мой распознаватель жестов не смог использовать следующий код:

for (UIGestureRecognizer * gestureRecognizer in self.tableView.gestureRecognizers)
{
    [gestureRecognizer requireGestureRecognizerToFail:myRecognizer];
}

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

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches)
        [touch.view touchesBegan:touches withEvent:event];
}

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

Я также попробовал еще одну вещь, прежде чем вернуться к своей обычной работе. Во время моего обширного поиска в Google я прочитал, что вложенные UIScrollViews волшебным образом работают с 3.x, поэтому я попытался поместить свое представление выбора во вложенный UIScrollView и установить для него следующие свойства:

scrollView.delaysContentTouches = NO;
scrollView.canCancelContentTouches = NO;

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

Что я знаю, так это то, что в UIScrollView есть распознаватель жестов с именем UIScrollViewDelayedTouchesBeganGestureRecognizer, который перехватывает прикосновения и отправляет их в соответствующее подпредставление через 150 (?) Мс. Я думаю, что я должен быть в состоянии написать аналогичный распознаватель, который вызывает сбой распознавателей по умолчанию представления прокрутки и вместо того, чтобы откладывать касания немедленно отправляет их в представление выбора. Поэтому, если кто-то знает, как написать такой распознаватель, пожалуйста, дайте мне знать, и если у вас есть какое-либо иное решение проблемы, вы также можете поделиться этим.

Спасибо за то, что прочитали весь вопрос, и даже если вы не знаете ответа, вы все равно можете поддержать вопрос так, чтобы он получил больше внимания (надеюсь, от кого-то, кто может ответить на него). Спасибо! :)

Ответы [ 3 ]

35 голосов
/ 07 января 2011

Иногда вам нужно задать вопрос, прежде чем вы сможете найти ответ. У Дана Рэя была похожая проблема, и она была решена совсем другим решением.

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView* result = [super hitTest:point withEvent:event];

    if ([result.superview isKindOfClass:[UIPickerView class]])
    {
        self.scrollEnabled = NO;
    }
    else 
    {
        self.scrollEnabled = YES;    
    }
    return result;
}

Я проверил код, и он прекрасно работает и для меня. Тем не менее, это не совсем кража касаний в представлении прокрутки, так что если кто-то знает, как на самом деле украсть касания, это было бы здорово.

Источник: UIPickerView внутри UITableView.tableFooterView не получает перетаскивания

4 голосов
/ 15 октября 2012

Немного поздно, но я нашел это решение: http://www.cocoanetics.com/2010/06/hacking-uiscrollview-gesture-recognizers/ У меня работает

0 голосов
/ 16 июля 2018

Я также опаздываю на вечеринку, но для новичков, если вы просто хотите проигнорировать пролистывание в представлении прокрутки, мне помогло добавить средство распознавания жестов панорамирования в представление, которое я хочу игнорировать проведите, как это:

let panGesture = UIPanGestureRecognizer()
panGesture.cancelsTouchesInView = false
myView?.addGestureRecognizer(panGesture)
...