Как отключить сенсорный ввод для всех видов, кроме самого верхнего вида? - PullRequest
42 голосов
/ 23 марта 2011

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

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

Ответы [ 10 ]

53 голосов
/ 23 марта 2011

Надеюсь, что эта справка ...

[[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 о добавлении невидимого представления поверх всех представлений является еще одним способом сделать это ..

46 голосов
/ 23 марта 2011

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

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

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

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

8 голосов
/ 18 июля 2012

Остерегайтесь кода, приведенного здесь Кришнабхадрой в качестве решения:

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

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

-(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, вероятно, лучше.

5 голосов
/ 08 декабря 2015

Я бы сделал это, поместив пользовательскую прозрачную кнопку с той же рамкой, что и 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];
4 голосов
/ 17 марта 2016

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

2 голосов
/ 31 августа 2014

Я дам свои 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;

Надеюсь, что это полезно.

1 голос
/ 18 сентября 2015

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

let captureTaps = UITapGestureRecognizer()
captureTaps.cancelsTouchesInView = true
dimmedOverlay?.addGestureRecognizer(captureTaps)
0 голосов
/ 02 марта 2017

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

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 25 февраля 2013

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

self.tabBarController.view.userInteractionEnabled = NO;

Также я отключил текущий контроллер вида -

self.view.userInteractionEnabled = NO;

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

0 голосов
/ 23 марта 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...