Ser*_*nce 10 iphone cocoa-touch uiview ios
我有一个UIView被部分卡下方的UINavigationBar上UIViewController这是在全屏模式下.的UINavigationBar块这个视图,它的覆盖它的部分的触摸.我希望能够解锁这些视图并让它们通过.我已经使用以下内容将UINavigationBar子类化:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *view = [super hitTest:point withEvent:event];
if (view.tag == 399)
{
return view;
}
else
{
return nil;
}
}
Run Code Online (Sandbox Code Playgroud)
...我用数字399标记了有问题的视图.是否有可能通过这个视图的触摸而没有指向它的指针(就像我在上面标记它一样)?对于如何使用hittest方法(或者甚至可能)进行此操作,我有点困惑.
这是一个不需要设置您想要在下面启用的特定视图的版本。相反,它允许任何触摸通过,除非该触摸发生在 aUIControl或带有UIGestureRecognizer.
import UIKit
/// Passes through all touch events to views behind it, except when the
/// touch occurs in a contained UIControl or view with a gesture
/// recognizer attached
final class PassThroughNavigationBar: UINavigationBar {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
guard nestedInteractiveViews(in: self, contain: point) else { return false }
return super.point(inside: point, with: event)
}
private func nestedInteractiveViews(in view: UIView, contain point: CGPoint) -> Bool {
if view.isPotentiallyInteractive, view.bounds.contains(convert(point, to: view)) {
return true
}
for subview in view.subviews {
if nestedInteractiveViews(in: subview, contain: point) {
return true
}
}
return false
}
}
fileprivate extension UIView {
var isPotentiallyInteractive: Bool {
guard isUserInteractionEnabled else { return false }
return (isControl || doesContainGestureRecognizer)
}
var isControl: Bool {
return self is UIControl
}
var doesContainGestureRecognizer: Bool {
return !(gestureRecognizers?.isEmpty ?? true)
}
}
Run Code Online (Sandbox Code Playgroud)
我修改了 Tricky 的解决方案,将 SwiftUI 作为Extension. 非常适合解决这个问题。将此代码添加到代码库后,所有视图都将能够捕获屏幕顶部的点击。
还将此更改发布到我的博客。
import UIKit
/// Passes through all touch events to views behind it, except when the
/// touch occurs in a contained UIControl or view with a gesture
/// recognizer attached
extension UINavigationBar {
open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
guard nestedInteractiveViews(in: self, contain: point) else { return false }
return super.point(inside: point, with: event)
}
private func nestedInteractiveViews(in view: UIView, contain point: CGPoint) -> Bool {
if view.isPotentiallyInteractive, view.bounds.contains(convert(point, to: view)) {
return true
}
for subview in view.subviews {
if nestedInteractiveViews(in: subview, contain: point) {
return true
}
}
return false
}
}
private extension UIView {
var isPotentiallyInteractive: Bool {
guard isUserInteractionEnabled else { return false }
return (isControl || doesContainGestureRecognizer)
}
var isControl: Bool {
return self is UIControl
}
var doesContainGestureRecognizer: Bool {
return !(gestureRecognizers?.isEmpty ?? true)
}
}
Run Code Online (Sandbox Code Playgroud)
子类UINavigationBar并覆盖- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event,以便NO为要接收的视图触摸的rect 返回,否则返回YES.
例如:
UINavigationBar子类.h:
@property (nonatomic, strong) NSMutableArray *viewsToIgnoreTouchesFor;
Run Code Online (Sandbox Code Playgroud)
UINavigationBar子类.m:
- (NSMutableArray *)viewsToIgnoreTouchesFor
{
if (!_viewsToIgnoreTouchesFor) {
_viewsToIgnoreTouchesFor = [@[] mutableCopy];
}
return _viewsToIgnoreTouchesFor;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL pointInSide = [super pointInside:point withEvent:event];
for (UIView *view in self.viewsToIgnoreTouchesFor) {
CGPoint convertedPoint = [view convertPoint:point fromView:self];
if ([view pointInside:convertedPoint withEvent:event]) {
pointInSide = NO;
break;
}
}
return pointInSide;
}
Run Code Online (Sandbox Code Playgroud)
在您的全屏viewController中,您可以在navBar后面添加这些行 viewDidLoad
UINavigationBarSubclass *navBar =
(UINavigationBarSubclass*)self.navigationController.navigationBar;
[navBar.viewsToIgnoreTouchesFor addObject:self.buttonBehindBar];
Run Code Online (Sandbox Code Playgroud)
请注意:这不会向navigationBar发送触摸,这意味着如果您添加一个位于导航栏按钮后面的视图,导航栏上的按钮将不会接收到触摸.
var viewsToIgnore = [UIView]()
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let ignore = viewsToIgnore.first {
let converted = $0.convert(point, from: self)
return $0.point(inside: converted, with: event)
}
return ignore == nil && super.point(inside: point, with: event)
}
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅文档pointInside:withEvent:
此外,如果pointInside:withEvent:不能按您的意愿工作,则可能值得尝试上面的代码hitTest:withEvent:.