简体   繁体   English

添加为 UIWindow 子视图的 UIView 不响应点击

[英]UIView added as an UIWindow subview doesn't respond to taps

I've added a UIView containing a UITapGestureRecognizer as my key window's subview.我添加了一个包含UITapGestureRecognizerUIView作为我的关键窗口的子视图。 It shows properly, however when I tap my view, the target method is not fired.它显示正确,但是当我点击我的视图时,目标方法不会被触发。 I've even tried to replace the gesture recognizer with a UIButton , still to no avail.我什至尝试用UIButton替换手势识别器,但仍然无济于事。

Here is my code.这是我的代码。

NotificationView.h通知视图.h

#import <UIKit/UIKit.h>

typedef NS_ENUM(int, NotificationKind) {
    NotificationKindActivity,
    NotificationKindReply,
};

@interface NotificationView : UIView {

    NotificationKind currentNotificationKind;

}

-(id)initWithMessage:(NSString*)message andColor:(UIColor*)color andKind:(NotificationKind)kind;
-(void)show;

@end

NotificationView.m通知视图.m

#import "NotificationView.h"

@implementation NotificationView

- (id)initWithMessage:(NSString*)message andColor:(UIColor*)color andKind:(NotificationKind)kind
{
    self = [super initWithFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), 60)];
    if (self) {
        // Initialization code
        [self setAlpha:0];
        [self setBackgroundColor:color];
        [self setUserInteractionEnabled:YES];


        currentNotificationKind = kind;

        UILabel *label = [[UILabel alloc] initWithFrame:self.bounds];
        [label setNumberOfLines:0];
        [label setFont:[UIFont fontWithName:@"Roboto-Italic" size:20]];
        [label setTextColor:[UIColor whiteColor]];
        [label setTextAlignment:NSTextAlignmentCenter];
        [label setPreferredMaxLayoutWidth:290];
        [label setText:message];
        [label setUserInteractionEnabled:YES];
        [self addSubview:label];

        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(notificationTapped)];
        [tap setNumberOfTapsRequired:1];
        [self addGestureRecognizer:tap];

        [[[UIApplication sharedApplication] keyWindow] addSubview:self];

    }
    return self;
}

-(void)show{
    [UIView animateWithDuration:0.3 animations:^{

        [self setAlpha:1];

    } completion:^(BOOL finished) {

        [UIView animateWithDuration:0.3 delay:3 options:UIViewAnimationOptionCurveLinear animations:^{
            [self setAlpha:0];

        } completion:^(BOOL finished) {
            [self removeFromSuperview];
        }];

    }];
}

-(void)notificationTapped{

    DDLogDebug(@"Notification tapped!");

}

@end

When this happens to me it's usually because I screwed up my UIView frame.当我遇到这种情况时,通常是因为我搞砸了UIView框架。 I see all the content as expected because my UIView isn't clipping to bounds, but I can't interact with anything because my taps are outside the bounds of the UIView .我按预期看到所有内容,因为我的UIView没有剪裁到边界,但我无法与任何内容交互,因为我的点击超出了UIView的边界。

My simple test is to change the background color of the UIView and see if it covers the area I expect or if I screwed up size/placement somehow.我的简单测试是更改UIView的背景颜色,看看它是否覆盖了我期望的区域,或者我是否以某种方式搞砸了尺寸/位置。

I used to pound my head against the wall with this issue, struggling for hours, but I've done it so many times now it's 5min fix of "Oh that again".我曾经因为这个问题把我的头撞在墙上,挣扎了几个小时,但我已经做了很多次了,现在是“哦,又一次”的 5 分钟修复。

Edit:编辑:

Then I'd look at your show code.然后我会看看你的show代码。 Your calling code isn't here, but if I'm to assume your are just using your show code and your view is only on screen for 3 seconds, then that's you problem.你的调用代码不在这里,但如果我假设你只是使用你的show代码并且你的视图只在屏幕上显示 3 秒,那么这就是你的问题。

As Justin mentioned (comment above) and Apple's docs正如贾斯汀提到的(上面的评论)和苹果的文档

During an animation, user interactions are temporarily disabled for all views involved in the animation, regardless of the value in this property.在动画期间,无论此属性中的值如何,动画中涉及的所有视图都将暂时禁用用户交互。 You can disable this behavior by specifying the UIViewAnimationOptionAllowUserInteraction option when configuring the animation.您可以通过在配置动画时指定 UIViewAnimationOptionAllowUserInteraction 选项来禁用此行为。

Since the entire time your view is on the screen it's part of an animation block, all interaction will be disable for the entire time it's visible.由于您的视图在屏幕上的整个时间都是动画块的一部分,因此在它可见的整个时间内所有交互都将被禁用。 I've never quite tested the delay bit and whether animation was disabled during that piece, but it would not surprise me animation is disabled during the delay.我从来没有完全测试过delay位以及动画在那个片段中是否被禁用,但是在延迟期间动画被禁用我不会感到惊讶。 The second animation is still inside the primary animation block, so I'd assume animations will be blocked until both are complete.第二个动画仍然在主动画块内,所以我假设动画将被阻止,直到两者都完成。

Updated NotificationView.m file, as suggested by @DBD...根据@DBD 的建议更新了NotificationView.m文件...

#import "NotificationView.h"

@implementation NotificationView

- (id)initWithMessage:(NSString*)message andColor:(UIColor*)color andKind:(NotificationKind)kind
{
    self = [super initWithFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), 60)];
    if (self) {
        // Initialization code
        [self setAlpha:0];
        [self setBackgroundColor:color];
        [self setClipsToBounds:YES];

        currentNotificationKind = kind;

        UILabel *label = [[UILabel alloc] initWithFrame:self.bounds];
        [label setNumberOfLines:0];
        [label setFont:[UIFont fontWithName:@"Roboto-Italic" size:20]];
        [label setTextColor:[UIColor whiteColor]];
        [label setTextAlignment:NSTextAlignmentCenter];
        [label setPreferredMaxLayoutWidth:290];
        [label setText:message];
        [self addSubview:label];

        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(notificationTapped)];
        [tap setNumberOfTapsRequired:1];
        [self addGestureRecognizer:tap];

        [[[UIApplication sharedApplication] keyWindow] addSubview:self];

    }
    return self;
}

-(void)show{

    [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{

        [self setAlpha:1];

    } completion:nil];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{

        [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
            [self setAlpha:0];

        } completion:^(BOOL finished) {
            [self removeFromSuperview];
        }];

    });


}

-(void)notificationTapped{

    DDLogDebug(@"Notification tapped!");

}

@end

I ended up being able to create a full-screen subview which accepted gestures by adding it to the app's keyWindow, assuming makeKeyAndVisible has been called first:假设首先调用 makeKeyAndVisible,我最终能够创建一个全屏子视图,通过将其添加到应用程序的 keyWindow 来接受手势:

myView.hidden = YES;
[[[UIApplication sharedApplication] keyWindow] addSubview:myView];

Then to show it above the status bar:然后在状态栏上方显示它:

[[UIApplication sharedApplication] keyWindow].windowLevel = UIWindowLevelStatusBar + 1;
myView.hidden = NO;

And to change it back:并将其改回:

[[UIApplication sharedApplication] keyWindow].windowLevel = UIWindowLevelNormal;
myView.hidden = YES;

This just changes the position of your app's main window (including all of its subviews) within the window hierarchy.这只会更改应用程序主窗口(包括其所有子视图)在窗口层次结构中的位置。 Hope that helps!希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM