ist es möglich festzustellen, ob mein UIView
für den Benutzer sichtbar ist oder nicht?
Meine Ansicht wird mehrmals als subview
zu einem Tab Bar Controller
Hinzugefügt.
Jede Instanz dieser Ansicht verfügt über ein NSTimer
, das die Ansicht aktualisiert.
Ich möchte jedoch keine Ansicht aktualisieren, die für den Benutzer nicht sichtbar ist.
Ist das möglich?
Vielen Dank
Sie können überprüfen, ob:
view.superview != nil
Das einzige andere, woran ich denken kann, ist, wenn Ihre Sicht hinter anderen verborgen ist und aus diesem Grund nicht gesehen werden kann. Möglicherweise müssen Sie alle folgenden Ansichten durchgehen, um festzustellen, ob sie Ihre Ansicht verdecken.
Für alle anderen, die hier landen:
So stellen Sie fest, ob ein UIView irgendwo auf dem Bildschirm angezeigt wird, anstatt superview != nil
, es ist besser zu überprüfen, ob window != nil
. Im ersten Fall ist es möglich, dass die Ansicht eine Übersicht enthält, diese jedoch nicht auf dem Bildschirm angezeigt wird:
if (view.window != nil) {
// do stuff
}
Natürlich sollten Sie auch prüfen, ob es sich um hidden
handelt oder ob es ein alpha > 0
.
Wenn Sie nicht möchten, dass Ihr NSTimer
ausgeführt wird, während die Ansicht nicht sichtbar ist, sollten Sie diese Ansichten nach Möglichkeit manuell ausblenden und den Timer anhalten lassen, wenn die Ansicht ausgeblendet ist. Ich bin mir jedoch nicht sicher, was Sie tun.
Hiermit wird bestimmt, ob der Frame einer Ansicht innerhalb der Grenzen aller Superviews liegt (bis zur Stammansicht). Ein praktischer Anwendungsfall besteht darin, zu bestimmen, ob eine untergeordnete Ansicht (zumindest teilweise) in einer Bildlaufansicht sichtbar ist.
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)
}
Mögliche Verbesserungen:
alpha
und hidden
.clipsToBounds
, da eine Ansicht die Grenzen ihrer Übersicht überschreiten kann, wenn sie falsch ist.Die Lösung, die für mich funktioniert hat, war, zuerst zu überprüfen, ob die Ansicht ein Fenster hat, dann über die Übersichten zu iterieren und zu überprüfen, ob:
Scheint soweit gut zu funktionieren.
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
}
Wenn Sie wirklich wissen möchten, ob eine Ansicht für den Benutzer sichtbar ist, müssen Sie Folgendes berücksichtigen:
Insbesondere die transparente Hintergrundfarbe der Ansichten im Vordergrund kann zu Problemen bei der programmgesteuerten Überprüfung führen. Die einzige Möglichkeit, um wirklich sicher zu sein, besteht darin, einen programmgesteuerten Schnappschuss der Ansicht zu erstellen, um ihn innerhalb seines Rahmens mit dem Schnappschuss des gesamten Bildschirms zu vergleichen. Dies funktioniert jedoch nicht für Ansichten, die nicht unterscheidungskräftig genug sind (z. B. vollständig weiß).
Inspiration finden Sie in der Methode isViewVisible im Abschnitt iOS Calabash-Server-Projekt
In viewWillAppear setzen Sie einen Wert "isVisible" auf true, in viewWillDisappear setzen Sie ihn auf false. Die beste Methode, um für einen UITabBarController Unteransichten zu ermitteln, funktioniert auch für Navigationscontroller.
Dies kann Ihnen dabei helfen, herauszufinden, ob Ihre UIView-Ansicht die Ansicht mit der höchsten Priorität ist. Kann hilfreich sein:
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
}
Wenn Sie eine versteckte Eigenschaft der Ansicht verwenden, gehen Sie wie folgt vor:
view.hidden (Objective C) oder view.isHidden (Swift) ist eine Lese-/Schreibeigenschaft. So können Sie leicht lesen oder schreiben
Für Swift 3.
if(view.isHidden){
print("Hidden")
}else{
print("visible")
}
Getestete Lösung.
func isVisible(_ view: UIView) -> Bool {
if view.isHidden || view.superview == nil {
return false
}
if let rootViewController = UIApplication.shared.keyWindow?.rootViewController,
let rootView = rootViewController.view {
let viewFrame = view.convert(view.bounds, to: rootView)
let topSafeArea: CGFloat
let bottomSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = rootView.safeAreaInsets.top
bottomSafeArea = rootView.safeAreaInsets.bottom
} else {
topSafeArea = rootViewController.topLayoutGuide.length
bottomSafeArea = rootViewController.bottomLayoutGuide.length
}
return viewFrame.minX >= 0 &&
viewFrame.maxX <= rootView.bounds.width &&
viewFrame.minY >= topSafeArea &&
viewFrame.maxY <= rootView.bounds.height - bottomSafeArea
}
return false
}
versuche dies:
func isDisplayedInScreen() -> Bool
{
if (self == nil) {
return false
}
let screenRect = UIScreen.main.bounds
//
let rect = self.convert(self.frame, from: nil)
if (rect.isEmpty || rect.isNull) {
return false
}
// 若view 隐藏
if (self.isHidden) {
return false
}
//
if (self.superview == nil) {
return false
}
//
if (rect.size.equalTo(CGSize.zero)) {
return false
}
//
let intersectionRect = rect.intersection(screenRect)
if (intersectionRect.isEmpty || intersectionRect.isNull) {
return false
}
return true
}