Tap blocking in GenericViewBlock

commit_hash:ce1bc24cde851c2411491ac3972672ca8916989e
This commit is contained in:
booster
2026-05-13 00:33:58 +03:00
parent 18c6482da2
commit e0e8ead9ba
2 changed files with 73 additions and 10 deletions
@@ -37,6 +37,7 @@ public final class GenericViewBlock: BlockWithTraits {
public let content: Lazy<Content>
public let width: Trait
public let height: Trait
public let isExclusiveTouch: Bool
public var widthTrait: LayoutTrait { width.layoutTrait }
public var heightTrait: LayoutTrait { height.layoutTrait }
@@ -56,41 +57,57 @@ public final class GenericViewBlock: BlockWithTraits {
public init(
lazyContent: Lazy<Content>,
width: Trait,
height: Trait
height: Trait,
isExclusiveTouch: Bool = false
) {
self.content = lazyContent
self.width = width
self.height = height
self.isExclusiveTouch = isExclusiveTouch
}
public convenience init(
content: Content,
width: Trait,
height: Trait
height: Trait,
isExclusiveTouch: Bool = false
) {
self.init(
lazyContent: Lazy<Content>(
onMainThreadGetter: { content }
),
width: width,
height: height
height: height,
isExclusiveTouch: isExclusiveTouch
)
}
public convenience init(
view: ViewType,
width: CGFloat? = nil,
height: CGFloat? = nil
height: CGFloat? = nil,
isExclusiveTouch: Bool = false
) {
self.init(content: .view(view), width: width.trait, height: height.trait)
self.init(
content: .view(view),
width: width.trait,
height: height.trait,
isExclusiveTouch: isExclusiveTouch
)
}
public convenience init(
layer: LayerType,
width: CGFloat? = nil,
height: CGFloat? = nil
height: CGFloat? = nil,
isExclusiveTouch: Bool = false
) {
self.init(content: .layer(layer), width: width.trait, height: height.trait)
self.init(
content: .layer(layer),
width: width.trait,
height: height.trait,
isExclusiveTouch: isExclusiveTouch
)
}
public func intrinsicContentHeight(forWidth width: CGFloat) -> CGFloat {
@@ -106,8 +123,10 @@ public final class GenericViewBlock: BlockWithTraits {
return false
}
return content.currentValue === other.content.currentValue && width == other
.width && height == other.height
return content.currentValue === other.content.currentValue
&& width == other.width
&& height == other.height
&& isExclusiveTouch == other.isExclusiveTouch
}
public func getImageHolders() -> [ImageHolder] { [] }
@@ -17,7 +17,9 @@ extension GenericViewBlock {
overscrollDelegate _: ScrollDelegate?,
renderingDelegate _: RenderingDelegate?
) {
(view as! GenericView).content = content.value
let genericView = view as! GenericView
genericView.content = content.value
genericView.exclusiveTouchEnabled = isExclusiveTouch
}
}
@@ -34,8 +36,31 @@ private final class GenericView: UIView, BlockViewProtocol, VisibleBoundsTrackin
}
}
var exclusiveTouchEnabled = false {
didSet {
guard oldValue != exclusiveTouchEnabled else { return }
tapAbsorber.isEnabled = exclusiveTouchEnabled
}
}
private let tapAbsorber = UITapGestureRecognizer()
var effectiveBackgroundColor: UIColor? { backgroundColor }
override init(frame: CGRect) {
super.init(frame: frame)
tapAbsorber.addTarget(self, action: #selector(absorbTap))
tapAbsorber.delegate = self
tapAbsorber.cancelsTouchesInView = false
tapAbsorber.isEnabled = false
addGestureRecognizer(tapAbsorber)
}
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
content?.setFrame(bounds)
@@ -49,6 +74,25 @@ private final class GenericView: UIView, BlockViewProtocol, VisibleBoundsTrackin
return result
}
}
@objc private func absorbTap() {}
}
extension GenericView: UIGestureRecognizerDelegate {
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
guard gestureRecognizer === tapAbsorber else { return false }
guard let otherTap = otherGestureRecognizer as? UITapGestureRecognizer,
otherTap.numberOfTapsRequired == 1
else { return false }
guard let otherView = otherTap.view,
otherView !== self,
isDescendant(of: otherView)
else { return false }
return true
}
}
extension GenericViewBlock.Content {