【问题标题】:How to disable multitouch?如何禁用多点触控?
【发布时间】:2010-11-07 23:30:27
【问题描述】:

我的应用有几个按钮可以触发不同的事件。用户不应该能够按住几个按钮。无论如何,按住几个按钮会使应用程序崩溃。

因此,我正在尝试在我的应用中禁用多点触控。

我在所有 xib 文件中都未选中“Multiple Touch”,据我所知,“multipleTouchEnabled”和“exclusiveTouch”属性控制视图是否使用多点触控。所以在我的 applicationDidFinishLaunching 中,我写了这个:

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

在我的每个视图控制器中,我都将它放在 viewDidLoad 中

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

但是,它仍然接受多次触摸。在发生触地事件后,我可以执行诸如禁用其他按钮之类的操作,但这将是一个丑陋的黑客行为。肯定有办法正确禁用多点触控吗?

【问题讨论】:

  • 我也尝试过这样做,但仍然无法这样做。有谁知道如何在 Cocos2D 中禁用多点触控选择?
  • 你必须在每个按钮上设置exclusiveTouch = YES,而不是在视图上。
  • 您的 VIEW 是单点触控的主要问题,而不是子视图。所以您需要禁用按钮,或者将一个大视图放在按钮上并处理单点触控。

标签: iphone uiview multi-touch


【解决方案1】:

如果您希望一次只有一个按钮响应触摸,则需要为该按钮设置 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

【讨论】:

  • 这是否意味着将 button1.exclusiveTouch = YES;button2.exclusiveTouch = YES;button3.exclusiveTouch = YES;在视图控制器的 viewDidLoad 中?我试过了 - 没有效果。
  • 我只是试了一下,它对我有用。您的 viewController 插座是否设置不正确?可能值得在调试器中检查。
  • 道歉。 IB 中的按钮未正确连接
  • 我认为 setExclusiveTouch = YES 应该是粗体的,因为我相信这是我们大多数人都在寻找的解决方案,其余的只是一个不错的选择 :)
  • extension UIButton { open override func touchesBegan(_ touches: Set, with event: UIEvent?) { super.touchesBegan(touches, with: event) self.isEnabled=false DispatchQueue.main. asyncAfter(deadline: .now() + 1) { self.isEnabled = true } } }
【解决方案2】:
- (void)viewDidLoad {
    [super viewDidLoad];

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

【讨论】:

  • extension UIButton { open override func touchesBegan(_ touches: Set, with event: UIEvent?) { super.touchesBegan(touches, with: event) self.isEnabled=false DispatchQueue.main. asyncAfter(deadline: .now() + 1) { self.isEnabled = true } } }
【解决方案3】:
- (void)viewDidLoad {
    [super viewDidLoad];

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

此代码已经过测试,对我来说完美运行。一次按下多个按钮时不会出现应用程序崩溃。

【讨论】:

    【解决方案4】:

    您的应用崩溃是有原因的。进一步调查,使用调试器,看看出了什么问题,而不是试图隐藏错误。

    编辑:

    好的,好的,我不得不承认我有点苛刻。您必须在每个按钮上设置exclusiveTouch 属性。就这样。 multipleTouchEnabled 属性无关紧要。

    【讨论】:

    • 我不想隐藏这个错误。用户应该不能按多个按钮。
    • 苛刻,是的。但也正确。需要在每个按钮上设置 ExclusiveTouch,在这种情况下,如果没有详细信息,可能很难找到一个错误......调试器将是你最好的朋友。
    • 在每个按钮上设置exclusiveTouch完全没有效果。
    • 是的。尝试在按钮上设置 ExclusiveTouch 的位置进行调试。 IBOutlets 是否已经连接?如果你还是不信,试试我为你设置的示例项目:rapidshare.de/files/47745816/a.zip.html
    • 道歉。 IB 中的按钮未正确连接
    【解决方案5】:

    在 SWIFT 中禁用多点触控:

    您首先需要为每个按钮设置一个插座,然后只需将独占触摸设置为 true。因此,viewDidLoad() 将拥有:

    yourButton.exclusiveTouch = true.

    // 不是很必要,但您也可以添加:

    self.view.multipleTouchEnabled = false

    【讨论】:

      【解决方案6】:

      如果您想在整个应用程序中禁用多点触控并且不想为每个按钮编写代码,那么您可以简单地使用按钮的Appearance。写在didFinishLaunchingWithOptions下面的行。

      UIButton.appearance().isExclusiveTouch = true
      

      太好了!! UI外观

      您甚至可以将它用于任何UIView 类,因此如果您想为几个按钮禁用多点触控。制作一个CustomClass的按钮,然后

      CustomButton.appearance().isExclusiveTouch = true
      

      还有一个优势可以帮助您。如果您想禁用特定 ViewController 中的多点触控按钮

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

      【讨论】:

        【解决方案7】:

        基于 neoevoke 的回答,只对其进行了一些改进,以便它也检查子视图的子视图,我创建了这个函数并将其添加到我的 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];
        

        ... 会成功的。

        【讨论】:

          【解决方案8】:

          这是我们的测试人员经常报告的问题。尽管应该有意识地使用,但我有时使用的一种方法是为UIView 创建类别,如下所示:

          @implementation UIView (ExclusiveTouch)
          
          - (BOOL)isExclusiveTouch
          {
              return YES;
          }
          

          【讨论】:

            【解决方案9】:

            在这种情况下,您可以使用 ExclusiveTouch 属性非常简单

            [youBtn setExclusiveTouch:YES];
            

            这是一个布尔值,指示接收器是否专门处理触摸事件。

            将此属性设置为 YES 会导致接收器阻止将触摸事件传递到同一窗口中的其他视图。此属性的默认值为 NO。

            【讨论】:

              【解决方案10】:

              用于在 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
                  ...
              }
              

              【讨论】:

                【解决方案11】:

                我的经验是,默认情况下,一个新项目甚至不允许多点触控,你必须打开它。但我想这取决于你是如何开始的。您是否使用了多点触控示例作为模板?

                首先,您确定多点触控已开启吗?可以很快地按顺序生成单次触摸。多点触控更多的是关于你用两个或更多手指在表面上所做的事情。也许您只按了一次按钮,但没有正确处理如果几乎同时按下两个按钮会发生什么。

                【讨论】:

                • 我使用的模板是标准的实用程序应用程序。是的,也许我应该担心的是“序列中的单一接触”。按住一个按钮时,我需要禁用所有其他按钮。但我仍然没有接近解决方案。
                【解决方案12】:

                我刚刚遇到过这个问题。

                我们想出的解决方案是简单地从 UIButton 继承一个新类,该类覆盖 initWithCoder 方法,并在我们需要一次按一个按钮的地方(即无处不在)使用它:

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

                请注意,这只适用于从 nib 文件加载的按钮。

                【讨论】:

                  【解决方案13】:

                  我创建了 UIView 类扩展并添加了这两个函数。当我想禁用视图触摸时,我只需调用 [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];
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    如果您想以编程方式禁用多点触控,或者您正在使用 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  
                    }
                    

                    【讨论】:

                      【解决方案15】:

                      “Touch Down” 事件中禁用所有视图中的按钮,并在 “Touch Up Inside” 事件中启用它们。

                      例如

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

                      【讨论】:

                        【解决方案16】:

                        我是这样解决这个问题的:

                        NSTimeInterval intervalButtonPressed;
                        
                        - (IBAction)buttonPicturePressed:(id)sender{ 
                        
                            if (([[NSDate date] timeIntervalSince1970] - intervalButtonPressed) > 0.1f) {
                                intervalButtonPressed = [[NSDate date] timeIntervalSince1970];
                                //your code for button
                            }
                        }
                        

                        【讨论】:

                          【解决方案17】:

                          在视图中拖动对象时,我遇到了一些奇怪的情况,如果您同时触摸另一个对象,它会触发 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
                          }
                          

                          【讨论】:

                            【解决方案18】:

                            一个陷阱:

                            如果您使用的是isExclusiveTouch,请注意在按钮上覆盖point(inside:) 可能会产生干扰,从而有效地使isExclusiveTouch 无用。

                            (有时您需要覆盖 point(inside:) 以处理“iPhone 屏幕底部的按钮没有响应”错误/错误功能(这是由 Apple 在屏幕底部安装 swipe GestureRecognizers 引起的,干扰按钮突出显示。)

                            见:UIButton fails to properly register touch in bottom region of iPhone screen

                            【讨论】:

                              【解决方案19】:

                              只需将所有相关的 UIView 的属性 ExclusiveTouch 设置为 false 即可。

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2019-02-02
                                • 2012-08-20
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多