Реагирование на касания началось в UIPickerView вместо UIView

StackOverflow https://stackoverflow.com/questions/567805

Вопрос

У меня есть UIPickerView, который затухает до 20% альфа-сигнала, когда не используется.Я хочу, чтобы пользователь мог прикоснуться к средству выбора и заставить его снова исчезнуть.

Я могу заставить это работать, если добавлю метод touchesBegan в основной вид, но это работает только тогда, когда пользователь прикасается к виду.Я попробовал подклассировать UIPickerView и включить там touchesBegan, но это не сработало.

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

Это было полезно?

Решение

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

Извините, если мой язык не очень техничен, но я довольно новичок в Objective-C и разработке iPhone.

Подкласс UIPickerView - правильный способ сделать это.Но вы должны переопределить - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event способ.Этот метод вызывается всякий раз, когда вы прикасаетесь к экрану, и он возвращает вид, который будет реагировать на прикосновение.Другими словами, представление, чей touchesBegan:withEvent: будет вызван метод.

UIPickerView имеет 9 подвидов!В реализации класса UIPickerView - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event не вернется self (это означает, что touchesBegan:withEvent: вы пишете, что подкласс не будет вызван), но вернет вложенный вид, точно такой же, как вид с индексом 4 (недокументированный подкласс, называемый UIPickerTable).

Хитрость заключается в том, чтобы сделать - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event способ возврата self таким образом, у вас есть контроль над touchesBegan:withEvent:, touchesMoved:withEvent: и touchesEnded:withEvent: методы.

В этих методах, чтобы сохранить стандартные функциональные возможности UIPickerView, вы ДОЛЖНЫ не забыть вызвать их снова, но в подвиде UIPickerTable.

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

Другие советы

Вот некоторый код, который делает то, что вы хотите:

@interface TouchDetectionView : UIPickerView {

}
- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@implementation TouchDetectionView

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
    [hitTestView touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
    [hitTestView touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
    [hitTestView touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
    [hitTestView touchesCancelled:touches withEvent:event];
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    return self;
}

- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch * touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    UIView * hitTestView = [super hitTest:point withEvent:event];

    return ( hitTestView == self ) ? nil : hitTestView;
}

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

Причина проблемы:мой постоянный рендеринг препятствовал тому, чтобы анимация UIPickerView получала циклы процессора, необходимые для завершения, следовательно, для отображения правильного текущего выбора.Мое решение - которое работает - заключалось в следующем:в UIPickerView в touchesEnded:withEvent:, выполните что-нибудь, чтобы ненадолго приостановить мой рендеринг.Вот код:

#import "SubUIPickerView.h"

@implementation SubUIPickerView

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

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

- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [singleton set_secondsPauseRendering:0.5f];  // <-- my code to pause rendering

    [pickerTable touchesEnded:touches withEvent:event];
}

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

- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
    if (CGRectContainsPoint(self.bounds, point))
    {
        if (pickerTable == nil)
        {
            int nSubviews = self.subviews.count;
            for (int i = 0; i < nSubviews; ++i)
            {
                UIView* view = (UIView*) [self.subviews objectAtIndex:i];
                if ([view isKindOfClass:NSClassFromString(@"UIPickerTable")])
                {
                    pickerTable = (UIPickerTable*) view;
                    break;
                }
            }
        }
        return self;    // i.e., *WE* will respond to the hit and pass it to UIPickerTable, above.
    }
    return [super hitTest:point withEvent:event];
}

@end

и затем заголовок, SubUIPickerView.h:

@class UIPickerTable;

@interface SubUIPickerView : UIPickerView
{
    UIPickerTable*  pickerTable;
}

@end

Как я уже сказал, это работает.Рендеринг приостанавливается еще на 1/2 секунды (он уже приостанавливается при перемещении UIScrollView), позволяя завершить анимацию UIPickerView.Использование NSClassFromString() означает, что вы не используете никаких недокументированных API.Возиться с цепочкой Ответчиков не было необходимости.Спасибо checcco и Tylerc230 за помощь в разработке моего собственного решения!

Установите для canCancelContentTouches и delaysContentTouches родительского представления значение NO, у меня это сработало

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top