Skip to content

Commit

Permalink
Add passThroughTouches to BlueprintView, PassthroughView.
Browse files Browse the repository at this point in the history
  • Loading branch information
kyleve committed Sep 17, 2024
1 parent ef1869f commit 5748833
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
28 changes: 26 additions & 2 deletions BlueprintUI/Sources/BlueprintView/BlueprintView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ public final class BlueprintView: UIView {
/// Provides performance metrics about the duration of layouts, updates, etc.
public weak var metricsDelegate: BlueprintViewMetricsDelegate? = nil

/// Defaults to `false`. If enabled, Blueprint will pass through any touches
/// not recieved by an element to the view hierarchy behind the `BlueprintView`.
public var passThroughTouches: Bool = false {
didSet {
if oldValue != passThroughTouches {
setNeedsViewHierarchyUpdate()
}
}
}

private var isVisible: Bool = false {
didSet {
switch (oldValue, isVisible) {
Expand All @@ -141,7 +151,7 @@ public final class BlueprintView: UIView {

rootController = NativeViewController(
node: NativeViewNode(
content: UIView.describe { _ in },
content: PassthroughView.describe { _ in },
// Because no layout update occurs here, passing an empty environment is fine;
// the correct environment will be passed during update.
environment: .empty,
Expand Down Expand Up @@ -327,6 +337,18 @@ public final class BlueprintView: UIView {
setNeedsViewHierarchyUpdate()
}

/// Ignore any touches on this view and (pass through) by returning nil if the default `hitTest` implementation returns this view.
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let result = super.hitTest(point, with: event)

if passThroughTouches {
return result == self ? nil : result

} else {
return result
}
}

/// Clears any sizing caches, invalidates the `intrinsicContentSize` of the
/// view, and marks the view as needing a layout.
private func setNeedsViewHierarchyUpdate() {
Expand Down Expand Up @@ -391,7 +413,9 @@ public final class BlueprintView: UIView {
rootController.view.frame = bounds

var rootNode = NativeViewNode(
content: UIView.describe { _ in },
content: PassthroughView.describe { [weak self] config in
config[\.passThroughTouches] = self?.passThroughTouches ?? false
},
environment: environment,
layoutAttributes: LayoutAttributes(frame: rootFrame),
children: viewNodes
Expand Down
13 changes: 10 additions & 3 deletions BlueprintUI/Sources/Internal/PassthroughView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ import UIKit
CATransformLayer.self
}

/// Ignore any touches on this view and (pass through) by returning nil if the
/// default `hitTest` implementation returns this view.
public var passThroughTouches: Bool = true

/// Ignore any touches on this view and (pass through) by returning nil if the default `hitTest` implementation returns this view.
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let result = super.hitTest(point, with: event)
return result == self ? nil : result

if passThroughTouches {
return result == self ? nil : result

} else {
return result
}
}
}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Moved `CornerStyle` out of the `Box` namespace, and is now a root type in `BlueprintUICommonControls`. `Box.CornerStyle` is still available as a typealias.
- `BlueprintView` will now pass through touches to views lower in the view hierarchy if `passThroughTouches` is true.

### Deprecated

Expand Down

0 comments on commit 5748833

Please sign in to comment.