簡體   English   中英

防止禁用的 UIButton 傳播觸摸事件

[英]Prevent disabled UIButton from propagating touch events

我的應用程序有兩個重疊的 UIButton。 有時可能會禁用頂部按鈕。 但是,在這種情況下,它接收到的任何觸摸事件似乎都傳遞給了底層視圖,在我的情況下是另一個按鈕。

我需要的是頂部按鈕攔截所有觸摸並阻止它們到達底部按鈕,即使在禁用狀態下也是如此(即使在禁用狀態下調用它的指定操作,我也會很高興)。

到目前為止,我已經嘗試過:

[topButton setUserInteractionEnabled:YES];

[topButton setExclusiveTouch:YES];

雖然后一種情況可能是不可取的,因為如果它是點擊的第一個視圖,我仍然需要底部按鈕響應事件。 無論哪種方式,它們都不起作用。

我在禁用按鈕的超級視圖中添加了以下方法:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (!self.watchButton.enabled &&
        [self.watchButton pointInside:[self convertPoint:point toView:self.watchButton]
                            withEvent:nil]) {
        return nil;
    }
    return [super hitTest:point withEvent:event];
}

這適用於 UITableView 單元格。

我設法根據需要使用上面@kolyuchiy答案的稍微修改版本來完成這項工作。 我覆蓋了UIButton子類中的hitTest:withEvent:方法,在禁用時返回self並且該點位於視圖的框架內,以便消耗觸摸,但不會調用按鈕的事件處理。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if ( !self.enabled && [self pointInside:[self convertPoint:point toView:self] withEvent:event] )
    {
        return self;
    }
    return [super hitTest:point withEvent:event];
}

迅捷版:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    if !isEnabled, self.point(inside: point, with: event) {
        return self
    }
    return super.hitTest(point, with: event)
}

我知道這已經晚了,但是我正在閱讀很多類似的問題,但我閱讀的所有答案都沒有對我有幫助(其中一些是因為不起作用,而另一些是因為我不喜歡該解決方案),所以我發現一個更好的解決方案形式,我在這里分享它以幫助可能閱讀此問題的未來用戶。

解決方案

我總是有一個容器,里面有一些(或只有一個)按鈕。 所以我將按鈕容器的IBOutlet連接到我正在使用的UIViewControllerUIView

@property (weak, nonatomic) IBOutlet UIView *buttonsContainer;

我設置了一個 nil 單擊手勢識別器,如下所示:

[self.buttonsContainer addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:nil]];

使用此解決方法,如果按鈕被禁用,則buttonsContainer捕獲此事件並且不對其執行任何操作。

希望這會有所幫助。

在嘗試@kolyuchiy(需要修改其范圍之外的UIButton行為)和@patrick-lynch(對我不起作用)解決方案后,出現了更優雅的解決方案,適用於UIButton子類:

private static let dummyView: UIView = {
    let view = UIView(frame: .zero)
    view.userInteractionEnabled = true
    return view
}()

public override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
    if !enabled && pointInside(point, withEvent: event) {
        return self.dynamicType.dummyView
    }
    return super.hitTest(point, withEvent: event)
}

我所做的是在 UIButton 下放置與 UIButton 相同大小的 UIImageView。 然后即使您禁用 UIButton,觸摸事件也不會傳播 UIImageView。

創建按鈕的子類,然后覆蓋這些方法,以便按鈕將捕獲事件,但如果按鈕的某些屬性設置為 NO,則忽略它們:

touchesBegan:withEvent:
touchesCancelled:withEvent:
touchesEnded:withEvent:
touchesMoved:withEvent:

這些是 UIResponder 的方法。

如果你想處理事件,讓他們調用他們的 [super ...] 方法,否則如果你想要事件“吃掉”就不要調用它並返回。

如果有必要,也可以看看這個: Observing pinch multi-touchges in a UITableView

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM