[英]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
連接到我正在使用的UIViewController
或UIView
:
@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.