Как отключить мультитач?

мое приложение имеет несколько кнопок, которые вызывают различные события. Пользователь не должен иметь возможность удерживать несколько кнопок. Во всяком случае, удерживая несколько кнопок, приложение падает.

и поэтому я пытаюсь отключить мультитач в своем приложении.

Я снял флажок "множественное касание" во всех файлах xib, и, насколько я могу понять, свойства "multipleTouchEnabled" и "exclusiveTouch" контролируют, использует ли представление мультитач. Так что в моем applicationDidFinishLaunching я положите это:

self.mainViewController.view.multipleTouchEnabled=NO;
self.mainViewController.view.exclusiveTouch =YES;

и в каждом из моих контроллеров представления я поместил это в viewDidLoad

self.view.multipleTouchEnabled=NO;
self.view.exclusiveTouch=YES;

однако,еще принимает несколько штрихов. Я мог бы сделать что-то вроде отключения других кнопок после получения события касания, но это был бы уродливый Хак. Конечно, есть способ правильно отключить multi-touch?

18 ответов


Если вы хотите, чтобы только одна кнопка отвечала на прикосновения одновременно, вам нужно установить exclusiveTouch для этой кнопки, а не для родительского представления. Кроме того, вы можете отключить другие кнопки, когда кнопка получает событие "Touch Down".


вот пример последнего, который лучше работал в моем тестировании. Настройка exclusiveTouch для кнопок вроде бы работала, но привела к некоторым интересным проблемам, когда вы переместили палец с края кнопки, а не просто щелкнул.

вам нужно иметь розетки в контроллере, подключенные к каждой кнопке, и иметь события" Touch Down"," Touch Up Inside "и" Touch Up Outside", подключенные к соответствующим методам вашего контроллера.

#import "multibuttonsViewController.h"

@implementation multibuttonsViewController

// hook this up to "Touch Down" for each button
- (IBAction) pressed: (id) sender
{
    if (sender == one)
    {
        two.enabled = false;
        three.enabled = false;
        [label setText: @"One"]; // or whatever you want to do
    }
    else if (sender == two)
    {
        one.enabled = false;
        three.enabled = false;
        [label setText: @"Two"];  // or whatever you want to do
    }
    else
    {
        one.enabled = false;
        two.enabled = false;
        [label setText: @"Three"];  // or whatever you want to do
    }
}

// hook this up to "Touch Up Inside" and "Touch Up Outside"
- (IBAction) released: (id) sender
{
    one.enabled = true;
    two.enabled = true;
    three.enabled = true;
}

@end

- (void)viewDidLoad {
    [super viewDidLoad];

    for(UIView* v in self.view.subviews)
    {
        if([v isKindOfClass:[UIButton class]])
        {
            UIButton* btn = (UIButton*)v;
            [btn setExclusiveTouch:YES];
        }
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];

    for(UIView* v in self.view.subviews)
    {
        if([v isKindOfClass:[UIButton class]])
        {
            UIButton* btn = (UIButton*)v;
            [btn setExclusiveTouch:YES];
        }
    }
}

этот код протестирован и отлично работает для меня.нет никакого сбоя приложения при нажатии более одной кнопки за раз.


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

Edit:

хорошо, хорошо, я должен признать, что был немного резок. Вы должны установить свойство exclusiveTouch на каждая кнопка. Вот и все. Свойство multipleTouchEnabled не имеет значения.


основываясь на ответе neoevoke, только немного улучшив его, чтобы он также проверял дочерние элементы subviews, я создал эту функцию и добавил ее в файл utils:

// Set exclusive touch to all children

+ (void)setExclusiveTouchToChildrenOf:(NSArray *)subviews
{
    for (UIView *v in subviews) {
        [self setExclusiveTouchToChildrenOf:v.subviews];
        if ([v isKindOfClass:[UIButton class]]) {
            UIButton *btn = (UIButton *)v;
            [btn setExclusiveTouch:YES];
        }
    }
}

затем, простой вызов:

[Utils setExclusiveTouchToChildrenOf:self.view.subviews];

... сделаем трюк.


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

@implementation UIView (ExclusiveTouch)

- (BOOL)isExclusiveTouch
{
    return YES;
}

чтобы отключить мультитач в SWIFT:

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

yourButton.exclusiveTouch = true.

/ / на самом деле не обязательно, но вы также можете добавить:

self.view.multipleTouchEnabled = false


довольно просто вы можете использовать использовать свойство ExclusiveTouch в этом случае

[youBtn setExclusiveTouch:YES];

Это логическое значение, указывающее, является ли приемник обрабатывает события касания исключительно.

установка для этого свойства значения YES приводит к тому, что приемник блокирует доставку событий касания в другие представления в том же окне. По умолчанию это свойство имеет значение NO.


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

прежде всего, вы абсолютно уверены, что мультитач включен? Можно довольно быстро генерировать отдельные штрихи в последовательности. Мультитач больше о том, что вы делаете с двумя или более пальцами, как только они находятся на поверхности. Возможно, у вас есть одно прикосновение, но нет правильно справляясь с тем, что происходит, если две кнопки нажимаются почти одновременно.


У меня только что была именно эта проблема.

решение, которое мы придумали, было просто наследовать новый класс от UIButton, который переопределяет метод initWithCoder, и использовать его там, где нам нужно было нажимать одну кнопку за раз (т. е. везде):

@implementation ExclusiveButton

(id)initWithCoder: (NSCoder*)decoder 
{ 
   [self setExclusiveTouch:YES]; 
   return [super initWithCoder:decoder]
}

@end

обратите внимание, что это работает только с кнопками, загруженными из файлов nib.


Я создал расширение класса UIView и добавил Эти две функции. и когда я хочу отключить view touch, я просто вызываю [view makeExclusiveTouch];

- (void) makeExclusiveTouchForViews:(NSArray*)views {
    for (UIView * view in views) {
        [view makeExclusiveTouch];
    }
}

- (void) makeExclusiveTouch {
    self.multipleTouchEnabled = NO;
    self.exclusiveTouch = YES;
    [self makeExclusiveTouchForViews:self.subviews];
}

Если вы хотите отключить мультитач программным способом или используете cocos2d (без опции multipleTouchEnabled), вы можете использовать следующий код для делегата ccTouches:

- (BOOL)ccTouchesBegan:(NSSet *)touches
 withEvent:(UIEvent *)event {
       NSSet *multiTouch = [event allTouches];
       if( [multiTouch count] > 1) { 
            return; 
       }
       else {
           //else your rest of the code  
}

отключить все кнопки на просмотр в "Приземлиться" событие и включить их в "Touch Up Inside" событие.

- (void) handleTouchDown {
    for (UIButton *btn in views) {
        btn.enable = NO;
    }
}

- (void) handleTouchUpInside {
    for (UIButton *btn in views) {
        btn.enable = Yes;
    }
    ------
    ------
}

Я решил эту проблему таким образом:

NSTimeInterval intervalButtonPressed;

- (IBAction)buttonPicturePressed:(id)sender{ 

    if (([[NSDate date] timeIntervalSince1970] - intervalButtonPressed) > 0.1f) {
        intervalButtonPressed = [[NSDate date] timeIntervalSince1970];
        //your code for button
    }
}

Я боролся с некоторыми странными случаями при перетаскивании объектов вокруг представления, где, если вы коснетесь другого объекта одновременно, он запустит метод touchesBegan. Моя работа заключалась в отключении взаимодействия с пользователем для родительского представления до вызова touchesEnded или touchesCancelled.

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { 
   // whatever setup you need
   self.view.userInteractionEnabled = false 
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
   // whatever setup you need
   self.view.userInteractionEnabled = true
}

override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
   // whatever setup you need
   self.view.userInteractionEnabled = true
}

если вы хотите отключить multi touch во всем приложении и не хотите писать код для каждой кнопки, вы можете просто использовать Appearance кнопки. Напишите ниже строку в didFinishLaunchingWithOptions.

UIButton.appearance().isExclusiveTouch = true

это замечательно!! UIAppearance

вы даже можете использовать его для любых UIView класс, поэтому, если вы хотите отключить multi touch для нескольких кнопок. Сделайте CustomClass кнопки, а затем

CustomButton.appearance().isExclusiveTouch = true

есть еще одно преимущество, которое может помочь вам. В если вы хотите отключить мультитач кнопок в частности ViewController

UIButton.appearance(whenContainedInInstancesOf: [ViewController2.self]).isExclusiveTouch = true

для отключения глобального мультитач в Xamarin.iOS

скопируйте и вставьте код ниже:

[DllImport(ObjCRuntime.Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")]
internal extern static IntPtr IntPtr_objc_msgSend(IntPtr receiver, IntPtr selector, bool isExclusiveTouch);
static void SetExclusiveTouch(bool isExclusiveTouch)
{
    var selector = new ObjCRuntime.Selector("setExclusiveTouch:");
    IntPtr_objc_msgSend(UIView.Appearance.Handle, selector.Handle, isExclusiveTouch);
}

и установите его на AppDelegate:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    ...
    SetExclusiveTouch(true); // setting exlusive to true disables the multitouch
    ...
}

просто установите для свойства exclusiveTouch все соответствующие UIView значение false.