我有一个应用程序,有许多不同的按钮排列在计算器,如方形/矩形格式。它实际上与默认的iOS计算器非常相似。大约有6行,每个按钮有4列。
问题
我遇到的问题涉及底行中的按钮(大约是iPhone 4屏幕的底部10)。当按下它们时,它们不能正常工作,按下它们时必须按住它们(大约不到一秒钟)以注册“按下按钮”。这与标准短抽头相反。
除此底行之外没有其他按钮以这种方式运行。
此外,如果这些按钮在其上边缘轻敲,它们会表现正常,一旦触摸就会响应。这让我相信按钮本身不是问题,但是我的视图布局存在一些问题。
还应注意,该问题仅存在于物理设备上。在模拟器上,按钮表现正常。
上下文
包含这些按钮的视图不是应用程序的根视图控制器。相反,它转变为如此(这里没什么特别的):
[self presentViewController:navController animated:YES completion:nil];
self是根视图控制器
我遇到问题的视图控制器包含在导航控制器中,并由根视图控制器以模态方式显示,您可以在上面看到。
到目前为止我尝试过的
附加信息
这听起来像按钮和UIScreenEdgePanGestureRecognizer(或其他任何东西)之间的交互,负责检测用户想要启动系统的控制中心。
这里实际上有两个潜在的问题:
导致此问题的原因是Apple似乎在屏幕底部放置了一个GestureRecognizer,可以延迟任何其他视图中的触摸。在App的窗口上摆弄手势识别器后,我想出了一个包含UIButton子类的解决方案:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL inside = [super pointInside: point withEvent: event];
if (inside && !self.isHighlighted && event.type == UIEventTypeTouches)
{
self.highlighted = YES;
}
return inside;
}
虽然touchesBegan:被称为延迟,但调用给定的方法。检查视图是否位于屏幕底部可能适合于防止此修复可能出现的任何副作用。
快速回答Lukas并取消选择突出显示
extension UIButton {
public override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
var inside = super.pointInside(point, withEvent: event)
if inside != highlighted && event?.type == .Touches {
highlighted = inside
}
return inside
}
}
Swift 3解决方案
extension UIControl {
open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let inside = super.point(inside: point, with: event)
if inside != isHighlighted && event?.type == .touches {
isHighlighted = inside
}
return inside
}
}
我已根据Luka's的答案在swift中写了一个完整的解决方案。只需使任何冲突按钮符合此类,问题就会消失:
class BorderBugFixButton : UIButton {
override func awakeFromNib() {
super.awakeFromNib()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "unHighlight", name: UIApplicationWillResignActiveNotification, object: nil)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
let inside = super.pointInside(point, withEvent: event)
if inside != highlighted && event?.type == .Touches {
highlighted = inside
}
return inside
}
internal func unHighlight() {
highlighted = false
}
}
P.S。:对于那些不喜欢Storyboards / Xib的人,只需将awakeFromNib()
的实现迁移到init()
在处理将旧版故事板更新到iOS 7+时,我经常遇到这种情况,通常当有问题的ViewController有一个UIScrollView形式时。在ViewController对象的故事板中仔细检查这两个设置(不是视图,带黄色圆圈的视图)。当我取消选中顶部和底部栏下的“Extend Edges”时,scrollView的框架向下调整了64个点(导航和状态栏的高度)。
将NavBar.bottom和scrollView.top之间的空间设置回0后,该按钮开始工作。这可能是由于scrollView.frame.bottom在窗口底部上方64像素的事实,因此该区域中的触摸被忽略,因为它们在技术上不在scrollView的框架中,但仍然由于某种原因在视觉上显示。
iOS 9.3,Xcode 7.3
我建议您应该为实现Lukas' answer的UIButton类创建一个类别。有关如何创建类别的说明,请参阅此帖子:How do I create a category in Xcode 6 or higher?
使用传统的“+”符号为其指定一个合适的名称,即如果将其命名为“BottomOfScreen”,则生成的文件名将为“UIButton + BottomOfScreen”。
如果您使用的是objective-c,那么您将获得带有新类别的* .h和* .m文件。
*。H
#import <UIKit/UIKit.h>
@interface UIButton (BottomOfScreen)
@end
* .M
#import "UIButton+BottomOfScreen.h"
@implementation UIButton (BottomOfScreen)
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL inside = [super pointInside:point withEvent:event];
if (inside && !self.isHighlighted && (event.type == UIEventTypeTouches))
{
self.highlighted = true;
}
else
{
nil;
}
return inside;
}
@end
我能够通过在delaysTouchesBegan
中禁用viewWillAppear
来解决这个问题
self.navigationController?.interactivePopGestureRecognizer?.delaysTouchesBegan = false