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

Как отключить сенсорный ввод ко всем представлениям, кроме самого верхнего вида?

У меня есть представление с несколькими subviews. Когда пользователь отбирает subview, subview расширяется по размеру, чтобы покрыть большую часть экрана, но некоторые другие подпункты все еще видны снизу.

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

4b9b3361

Ответ 1

Надеюсь, что эта помощь...

[[yourSuperView subviews]
   makeObjectsPerformSelector:@selector(setUserInteractionEnabled:)
   withObject:[NSNumber numberWithBool:FALSE]];

который отключит userInteraction представления немедленного просмотра. Затем дайте userInteraction единственное представление, которое вы хотели

yourTouchableView.setUserInteraction = TRUE;

EDIT:

Кажется, что при отключении iOS userInteraction на родительском представлении не отключается userInteraction на его дочерних элементах. Итак, код выше (я имею в виду один с makeObjectsPerformSelector:) будет работать только для отключения userInteraction родительского немедленного просмотра.

См. ответ пользователя madewulf, который рекурсивно получает все подзапросы и отключает взаимодействие пользователей со всеми из них. Или, если вам нужно отключить userInteraction этого представления во многих местах проекта, вы можете классифицировать UIView, чтобы добавить эту функцию. Что-то вроде этого будет делать.

@interface UIView (UserInteractionFeatures)
-(void)setRecursiveUserInteraction:(BOOL)value;
@end

@implementation UIView(UserInteractionFeatures)
-(void)setRecursiveUserInteraction:(BOOL)value{
    self.userInteractionEnabled =   value;
    for (UIView *view in [self subviews]) {
        [view setRecursiveUserInteraction:value];
    }
}
@end

Теперь вы можете позвонить

[yourSuperView setRecursiveUserInteraction:NO];

Также пользователь @lxt предлагает добавить невидимый вид поверх всего представления - это еще один способ сделать это.

Ответ 2

Есть несколько способов сделать это. Вы можете прокручивать все ваши другие подзаголовки и устанавливать userInteractionEnabled = NO, но это не так идеально, если у вас много других представлений (в конце концов, вам придется впоследствии их переименовать).

Как я делаю это, нужно создать невидимый UIView, чтобы размер всего экрана, который "блокирует" все касания от перехода к другим представлениям. Иногда это буквально невидимо, иногда я могу установить его на черный с альфа-значением 0,3 или около того.

Когда вы расширяете свой основной подзаголовок, чтобы заполнить экран, вы можете добавить этот "блокирующий" UIView за ним (используя insertSubview: belowSubview:). Когда вы сворачиваете расширенный subview, вы можете удалить невидимый UIView из своей иерархии.

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

Ответ 3

Остерегайтесь кода, данного здесь решением Кришнабхадры:

[[yourSuperView subviews]makeObjectsPerformSelector:@selector(setUserInteractionEnabled:) withObject:[NSNumber numberWithBool:FALSE]];

Это не будет работать во всех случаях, потому что [subSphereServiceView] дает только прямые подсмотры супервизора. Чтобы заставить его работать, вам придется рекурсивно перебирать все подзоны:

-(void) disableRecursivelyAllSubviews:(UIView *) theView
{
    theView.userInteractionEnabled = NO;
    for(UIView* subview in [theView subviews])
    {
        [self disableRecursivelyAllSubviews:subview];
    }
}

-(void) disableAllSubviewsOf:(UIView *) theView
{
    for(UIView* subview in [theView subviews])
    {
        [self disableRecursivelyAllSubviews:subview];
    }
} 

Теперь вызов disableAllSubviewsOf будет делать то, что вы хотели сделать.

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

Ответ 4

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

Что-то вроде этого:

- (void)disableTouchesOnView:(UIView *)view {
    UIButton *ghostButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)];
    [ghostButton setBackgroundColor:[UIColor clearColor]];
    ghostButton.tag = 42; // Any random number. Use #define to avoid putting numbers in code.

    [view addSubview:ghostButton];
}

И метод включения parentView.

- (void)enableTouchesOnView:(UIView *)view {
    [[view viewWithTag:42] removeFromSuperview];
}

Итак, чтобы отключить все представления в parentViev позади yourView, я бы сделал следующее:

YourView *yourView = [[YourView alloc] initWithCustomInitializer];
// It is important to disable touches on the parent view before adding the top most view.
[self disableTouchesOnView:parentView];
[parentView addSubview:yourView];

Ответ 5

Просто parentView.UserInteractionEnabled = NO выполнит эту работу.  Родительский взгляд будет отключить взаимодействие пользователя во всех подзонах представления. Но включить не поддерживает включение всех подзонов (по умолчанию UIImageView не взаимодействует). Таким образом, простой способ - найти родительское представление и использовать вышеприведенный код, и нет необходимости перебирать все подпункты для выполнения селектора.

Ответ 6

setUserInteractionEnabled = NO в представлении, которое вы хотите отключить

Ответ 7

Я дам 2 цента этой проблеме. Итеративно запускайте userInteractionEnabled = false в один конец. Другой способ - добавить UIView, как показано ниже.

EZEventEater.h

#import <UIKit/UIKit.h>
@interface EZEventEater : UIView
@end

EZEventEater.m

#import "EZEventEater.h"
@implementation EZEventEater

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor clearColor];
        self.userInteractionEnabled = false;
    }
    return self;
}


- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   //EZDEBUG(@"eater touched");
}

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

}

В своем коде вы добавляете представление EZEventEater, чтобы охватить все виды, которые могут заблокировать событие касания. Всякий раз, когда вы хотите заблокировать сенсорное событие для этих представлений, просто вызовите

eater.userInteractionEnabled = YES;

Надеюсь, что это поможет.

Ответ 8

Для моего приложения, я думаю, будет достаточно отключить навигацию к другим вкладкам приложения (в течение ограниченного времени, пока я делаю некоторую обработку):

self.tabBarController.view.userInteractionEnabled = NO;

Кроме того, я отключил текущий контроллер представления -

self.view.userInteractionEnabled = NO;

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

Ответ 9

Добавьте TapGestureRecognizer в свой "фоновый вид" (полупрозрачный, который "вычеркивает" ваш обычный интерфейс) и установите для него "Отменяет прикосновения в представлении" без добавления действия.

let captureTaps = UITapGestureRecognizer()
captureTaps.cancelsTouchesInView = true
dimmedOverlay?.addGestureRecognizer(captureTaps)

Ответ 10

У меня была та же проблема, но вышеупомянутые решения не помогли. Затем я заметил, что вызов super.touchesBegan(...) была проблема. После удаления это событие обрабатывалось только самым верхним видом.

Я надеюсь, что это поможет кому угодно.