无法点击4“iPhone左侧的按钮

时间:2013-09-25 04:19:53

标签: ios ios6 ios7

这绝对令人困惑。在3.5英寸iPhone模拟器上,我的应用程序上的所有UIButton工作正常。但是,当我在4英寸iPhone模拟器上启动时,应用程序左侧的所有UIButton都不会收到任何点击事件。

以下是3.5英寸大小和4英寸大小的屏幕截图。在4“大小,我添加了一行。在该行的左边,没有任何按钮接收点击事件。在该行的右侧,所有按钮都表现正常。按钮2,5和8的左侧做不响应点击,但这些按钮的右侧确实响应。

enter image description here

enter image description here

UPDATE ---- 感谢@iccir,我发现了更多信息。显然,我的UIWindow只有320x480而不是568x320。我没有在我的代码中触摸UIWindow,只是让它变得键和可见。在我的MainWindow.xib中,我将其IBOutlet连接到我的rootViewController。

<UIWindow: 0xc097d50; frame = (0 0; 320 480); opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0xc098460>; layer = <UIWindowLayer: 0xc097e70>>

我很乏味。知道为什么UIWindow的大小不正确吗?

2 个答案:

答案 0 :(得分:8)

这是一个非常常见的问题:您的UIButton超出了其中一个超级视图的范围。如果clipsToBounds / masksToBounds设置为NO(默认值),您的UIButton仍会显示,但触摸事件不会发送给它。

让我们简化这种情况。假设一个视图控制器具有以下代码:

- (void) viewDidLoad
{
    [super viewDidLoad];

    UIColor *fadedRedColor  = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.25];
    UIColor *fadedBlueColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.25];

    CGRect containerFrame = CGRectMake(25,  25,  100, 100);
    CGRect buttonFrame    = CGRectMake(100, 100, 64,  44);

    UIView *container = [[UIView alloc] initWithFrame:containerFrame];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"Button" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [button setFrame:buttonFrame];
    [button addTarget:self action:@selector(_handleButton:) forControlEvents:UIControlEventTouchUpInside];

    [container setBackgroundColor:fadedRedColor];
    [button    setBackgroundColor:fadedBlueColor];

    [container addSubview:button];

    [[self view] addSubview:container];
}

- (void) _handleButton:(id)sender
{
    NSLog(@"Moooooo!");
}

看起来像这样: Screenshot 1

该按钮包含在container中,但它位于容器边界之外(容器宽100像素,高100像素,按钮的原点位于100, 100)。

当您触摸屏幕时,UIKit将从视图层次结构(UIWindow)的顶部开始,并递归调用-[UIView hitTest:withEvent:],直到找到应该处理触摸的视图。但是,在这个例子中,UIKit永远不会进入容器(因为你触及它的边界之外),因此按钮子视图不会被击中。

如果我们改为将buttonFrame更改为50, 50,它看起来像这样: Screenshot 2

与容器重叠的按钮部分将响应触摸事件。驻留在容器外部的部分不会:

Screenshot 3

要调试不完全可触摸的视图,您可以尝试以下调试功能:

static void sDebugViewThatIsntTouchable(UIView *view)
{
    UIView *superview = [view superview];

    while (superview) {
        CGRect rectInSuperview = [view convertRect:[view bounds] toView:superview];

        CGPoint topLeft     = CGPointMake(CGRectGetMinX(rectInSuperview), CGRectGetMinY(rectInSuperview));
        CGPoint topRight    = CGPointMake(CGRectGetMaxX(rectInSuperview), CGRectGetMinY(rectInSuperview));
        CGPoint bottomLeft  = CGPointMake(CGRectGetMinX(rectInSuperview), CGRectGetMaxY(rectInSuperview));
        CGPoint bottomRight = CGPointMake(CGRectGetMaxX(rectInSuperview), CGRectGetMaxY(rectInSuperview));

        if (![superview pointInside:topLeft withEvent:nil]) {
            NSLog(@"Top left point of view %@ not inside superview %@", view, superview);
        }

        if (![superview pointInside:topRight withEvent:nil]) {
            NSLog(@"Top right point of view %@ not inside superview %@", view, superview);
        }

        if (![superview pointInside:bottomLeft withEvent:nil]) {
            NSLog(@"Bottom left point of view %@ not inside superview %@", view, superview);
        }

        if (![superview pointInside:bottomRight withEvent:nil]) {
            NSLog(@"Bottom right point of view %@ not inside superview %@", view, superview);
        }

        superview = [superview superview];
    }
};

编辑: 正如您在评论中提到的,罪魁祸首视图是主UIWindow,其大小为320x480而不是320x568。 在xib中启用“启动时全屏”修复此

当然,问题是:“为什么?” :)

如果您在文本编辑器中提取xib文件,您会注意到宽度为320,高度为480的硬编码到窗口。当xib在启动时被解码时,窗口最初是用这个320x480帧构建的。

UIKit然后查询-[UIWindow resizesToFullScreen](私有方法)。如果返回YES,则UIWindow执行相当于[self setFrame:[[self window] bounds]]的操作。

在Interface Builder中切换“启动时全屏”标志直接切换私有UIWindow.resizesToFullScreen标志。

答案 1 :(得分:0)

让我猜一下,这只发生在横向模式中,对吧? 当我专门为iPhone-4S开发时,我在我的应用程序中遇到了同样的问题。但是当我开始在iPhone-5上进行测试时,底部触摸不起作用。这是frame。确保frames在代码和bounds文件(如果有)中设置为XIBframesbounds文件中的不同man / xib也可能导致此类行为。

我最终删除了xib个文件,并以编程方式完成了所有操作。我学到的一件事是,用viewWillAppearviewDidAppear方法而不是viewDidLoad设置框架。另请查看frame中的bounds / RootViewController。最后一点,尽量不要为frames使用常量值,使用与superview相关的参考帧。

PS,知道是否真的是导致此行为的帧/边界的一种方法是,为masksToBounds设置YESviews。这样,您的观点就不会在他们的视野之外显现出来。