为啥将 UILabel 设置为完全透明会丢失点击手势?

Posted

技术标签:

【中文标题】为啥将 UILabel 设置为完全透明会丢失点击手势?【英文标题】:Why does setting a UILabel to be fully transparent lose tap gestures?为什么将 UILabel 设置为完全透明会丢失点击手势? 【发布时间】:2013-01-05 09:13:23 【问题描述】:

我想不通,我认为this 也没有真正解释它。

我有一个UILabel,用户可以点击它来隐藏或显示它,设置如下:

self.numberLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] 
    initWithTarget:self action:@selector(hideOrShowNumber)];
[self.numberLabel addGestureRecognizer:tapGesture];

我想通过在UILabel 上设置alpha 值来为标签的隐藏和显示设置动画。但是,如果我将 alpha 值设置为0.0f,标签不再接受点击,所以即使用户可以隐藏标签,她也无法再显示了!

我的解决方法是这样的:

隐藏标签时: - 将 alpha 值设置为 0.0f。 - 将标签的文本颜色设置为黑色(由于背景为黑色,因此使其不可见) - 将 alpha 重置为 1.0f。

显示标签时: - 将 alpha 设置为 0.0f(因为当标签被隐藏时它保持在 1.0f)。 - 将文本颜色设置为黑色以外的其他颜色(取决于游戏状态)。 - 将 alpha 值设置为 1.0f。

代码如下所示(包含一些状态变量,但self.numberLabel是对UILabel的引用):

NSTimeInterval duration = 0.6f;

if (self.numberIsVisible) 
    [UIView animateWithDuration:duration
                     animations:^
                         self.numberLabel.alpha = 0.0f;
                     
                     completion:^(BOOL done) 
                         self.numberLabel.textColor = [UIColor blackColor];
                         self.numberLabel.alpha = 1.0f;
                     
    ];
    self.numberIsVisible = NO;

else 
    UIColor *rightColor = [UIColor whiteColor];

    if ([GameState sharedGameState].haveMatch) 
        rightColor = [UIColor colorWithRed:0.0/255.0 green:127.0/255.0 blue:255.0/255.0 alpha:1.0];
    

    self.numberLabel.alpha = 0.0f;
    self.numberLabel.textColor = rightColor;

    [UIView animateWithDuration:duration
                     animations:^
                         self.numberLabel.alpha = 1.0f;
                     
    ];

    self.numberIsVisible = YES;

它可以工作,但有点笨重。

所以问题是,为什么设置UILabel 的透明度会使其失去用户交互?这是设计使然吗,是否记录在某处?我在 UIGestureRecognizer 文档中找不到任何关于此的内容。

【问题讨论】:

看看 Ole Begemann 的 OBShapedButton - 他的代码应该可以帮助您解决这个问题。 @rokjarc 谢谢,但我有一个解决方法(见上文),另一个组件对此真的是矫枉过正。我对标签很满意,我不需要非矩形按钮。所以这不是一个真正的问题;我在问为什么会这样。我个人认为“隐藏”与(完全)“透明”略有不同,但 UIKit 似乎认为不同,正如许多答案中所指出的那样。 嗨,Jere,我认为您不会使用 OBShapedButton 代替标签。这个想法是看看应该如何处理这个透明度/触摸问题:使用cublasing和使用hitTest。 好的,我明白了。是的,这是一个有趣的想法,而且 OB 有很多很棒的东西。 【参考方案1】:

来自官方doc(规范触摸事件传递部分

关闭触摸事件的传递。默认情况下,视图接收 触摸事件,但您可以将其 userInteractionEnabled 属性设置为 NO 关闭触摸事件的传递。 一个视图也没有收到 这些事件是隐藏的还是透明的

在视图上具有完全透明 (alpha = 0) 被认为与隐藏视图类似,因此在这种情况下没有理由处理用户交互。您可以尝试使用几乎透明的UILabel0.1 的 alpha 似乎是极限。

【讨论】:

【参考方案2】:

似乎任何 alpha post。

【讨论】:

【参考方案3】:

至少在 ios 8 中,您可以将 alpha 设置为 0.01(不再是限制 0.1)并且会触发触摸事件。如果是 0.0 则不会触发触摸事件。

更新:我发现在 iOS 8.2 和更早的版本中,限制是 0.001960785。非常接近完全透明。也许这个数字可能会更小,我没有更进一步的小数位。

【讨论】:

【参考方案4】:

显然这种行为曾经被记录在案,但我在当前文档中找不到它。

看到这个答案:Why doesn't touchesBegan fire on UIViews when alpha is set to zero?

“默认情况下,视图接收触摸事件,但您可以将其 userInteractionEnabled 属性设置为 NO 以关闭事件传递。视图在隐藏或透明时也不会接收事件。”

没有理由您隐藏的UILabel 需要与接收触摸的视图相同。一个更简单的解决方法是:

    在您希望用户能够点击的地方添加一个包装器 UIView 将手势识别器添加到包装视图 让手势识别器的动作只是隐藏或显示标签

【讨论】:

【参考方案5】:

根据设计,当 alpha 设置为 0 时,视图不会收到触摸。您可以尝试将 alpha 设置为 0.1。查看苹果链接https://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MultitouchEvents/MultitouchEvents.html

【讨论】:

【参考方案6】:

我通过创建一个包含空格的 UILabel 解决了这个问题,然后根据需要使用自动布局约束来增长/缩小。

【讨论】:

以上是关于为啥将 UILabel 设置为完全透明会丢失点击手势?的主要内容,如果未能解决你的问题,请参考以下文章

当我将 IncludeStyleBlock 属性设置为 True 时,为啥 CSS“会丢失”?

为啥我的 UILabel 的 AutoLayout 不起作用

华为手升级成了鸿蒙系统,恢复出厂设置后为啥不能变回安卓系统

为啥使用半透明导航栏刹车推动动画将“hidesBottomBarWhenPushed”设置为 YES?

为啥WORD转换PDF时字体会丢失?

为啥 ProgressDialog 的背景没有设置为透明?