确定UIView是否对用户可见?

是否有可能确定我的UIView是否对用户可见?

我的视图作为subview视图被添加到Tab Bar Controller

这个视图的每个实例都有一个NSTimer来更新视图。

但是我不想更新用户不可见的视图。

这可能吗?

谢谢

你可以检查:

  • 它是隐藏的,通过检查view.hidden
  • 它在视图层次结构中,通过检查view.superview != nil
  • 你可以检查一个视图的边界,看看它是否在屏幕上

我能想到的另一件事是,如果你的观点被埋在别人的后面,而且不能被看到。 你可能需要仔细阅读所有的观点,看看是否模糊了你的观点。

对于任何最终在这里的人:

要确定一个UIView是否在屏幕上,而不是检查superview != nil ,最好检查一下window != nil 。 在前一种情况下,视图有可能是超视图,但超视图不在屏幕上:

 if (view.window != nil) { // do stuff } 

当然,你也应该检查它是否hidden或者是否有alpha > 0

关于不希望NSTimer在视图不可见的情况下运行,应尽可能手动隐藏这些视图,并在隐藏视图时使计时器停止。 但是,我并不确定你在做什么。

这将确定一个视图的框架是否在其所有超级视图的范围内(直到根视图)。 一个实际的用例是确定子视图是否(至less部分)在滚动视图内可见。

 func isVisible(view: UIView) -> Bool { func isVisible(view: UIView, inView: UIView?) -> Bool { guard let inView = inView else { return true } let viewFrame = inView.convertRect(view.bounds, fromView: view) if CGRectIntersectsRect(viewFrame, inView.bounds) { return isVisible(view, inView: inView.superview) } return false } return isVisible(view, inView: view.superview) } 

潜在的改进:

  • 尊重alphahidden
  • 尊重clipsToBounds ,因为一个视图如果为false,可能会超出其clipsToBounds的范围。

我真的想知道,如果用户可以看到一个视图,则必须考虑以下几点:

  • 视图的窗口不是零和等于最上面的窗口
  • 是视图和它的所有超级视图alpha> = 0.01(UIKit用来确定是否应该处理触摸的阈值)并且不隐藏
  • 是否视图的z-index(堆栈值)高于同一层次结构中的其他视图。
  • 即使z-index较低,如果顶部的其他视图具有透明背景颜色(alpha 0或隐藏),也可以看到它。

特别是前面的视图的透明背景颜色可能会造成一个问题,以编程方式进行检查。 要真正确定的唯一方法是对视图进行程序化快照,以便在整个屏幕快照的框架内检查和区分它。 然而,对于不够明显的视图(例如全白),这将不起作用。

有关灵感,请参阅iOS Calabash-server项目中的方法是ViewVisible

我的解决scheme是首先检查视图是否有窗口,然后遍历超级检查,并检查是否:

  1. 视图不隐藏。
  2. 该视图在其超级视图范围内。

似乎到目前为止工作得很好。

Swift 3.0

 public func isVisible(view: UIView) -> Bool { if view.window == nil { return false } var currentView: UIView = view while let superview = currentView.superview { if (superview.bounds).intersects(currentView.frame) == false { return false; } if currentView.isHidden { return false } currentView = superview } return true } 

在viewWillAppear中将值“isVisible”设置为true,在viewWillDisappear中将其设置为false。 知道UITabBarController子视图的最佳方法也适用于导航控制器。

这可以帮助你弄清楚你的UIView是否是最顶层的视图。 可以帮助:

 let visibleBool = view.superview?.subviews.last?.isEqual(view) //have to check first whether it's nil (bc it's an optional) //as well as the true/false if let visibleBool = visibleBool where visibleBool { value //can be seen on top } else { //maybe can be seen but not the topmost view } 

如果你使用隐藏的视图属性,那么:

view.hidden(objective C)或view.isHidden(swift)是读/写属性。 所以你可以很容易地读或写

对于迅速3.0

 if(view.isHidden){ print("Hidden") }else{ print("visible") }