确定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) }
潜在的改进:
- 尊重
alpha
和hidden
。 - 尊重
clipsToBounds
,因为一个视图如果为false,可能会超出其clipsToBounds
的范围。
我真的想知道,如果用户可以看到一个视图,则必须考虑以下几点:
- 视图的窗口不是零和等于最上面的窗口
- 是视图和它的所有超级视图alpha> = 0.01(UIKit用来确定是否应该处理触摸的阈值)并且不隐藏
- 是否视图的z-index(堆栈值)高于同一层次结构中的其他视图。
- 即使z-index较低,如果顶部的其他视图具有透明背景颜色(alpha 0或隐藏),也可以看到它。
特别是前面的视图的透明背景颜色可能会造成一个问题,以编程方式进行检查。 要真正确定的唯一方法是对视图进行程序化快照,以便在整个屏幕快照的框架内检查和区分它。 然而,对于不够明显的视图(例如全白),这将不起作用。
有关灵感,请参阅iOS Calabash-server项目中的方法是ViewVisible
我的解决scheme是首先检查视图是否有窗口,然后遍历超级检查,并检查是否:
- 视图不隐藏。
- 该视图在其超级视图范围内。
似乎到目前为止工作得很好。
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") }