UIView
がユーザーに表示されるかどうかを判断することはできますか?
私のビューはsubview
としてTab Bar Controller
に数回追加されます。
このビューの各インスタンスには、ビューを更新するNSTimer
があります。
ただし、ユーザーに表示されていないビューを更新する必要はありません。
これは可能ですか?
ありがとう
以下を確認できます。
view.superview != nil
をチェックすることにより、ビュー階層にあります私が考えることができる唯一の他のことは、あなたの意見が他の人の後ろに埋もれていて、その理由で見ることができない場合です。ビューが不明瞭になるかどうかを確認するために、後に続くすべてのビューを確認する必要がある場合があります。
ここで終わる他の人のために:
UIViewが画面上にあるかどうかを判断するために、superview != nil
、window != nil
。前者の場合、ビューにはスーパービューがあるが、スーパービューは画面上にない可能性があります。
if (view.window != nil) {
// do stuff
}
もちろん、hidden
かどうか、またはalpha > 0
。
ビューが表示されていないときにNSTimer
を実行したくない場合、可能であればこれらのビューを手動で非表示にし、ビューが非表示になったらタイマーを停止する必要があります。しかし、私はあなたが何をしているのか全くわかりません。
これにより、ビューのフレームがそのスーパービューのすべての範囲内にあるかどうか(ルートビューまで)が判断されます。実用的な使用例の1つは、スクロールビュー内で子ビューが(少なくとも部分的に)表示されるかどうかを判断することです。
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
を尊重してください。私のために働いた解決策は、最初にビューにウィンドウがあるかどうかを確認し、次にスーパービューを反復して次のことを確認することでした:
これまでのところうまくいくようです。
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
}
ビューがユーザーに表示されるかどうかを本当に知りたいのは、次のことを考慮する必要があるからです。
特に、前面のビューの透明な背景色は、プログラムで確認する際に問題を引き起こす可能性があります。本当に確実にする唯一の方法は、ビューのプログラムによるスナップショットを作成し、画面全体のスナップショットとフレーム内でチェックして比較することです。ただし、これは十分に際立っていないビュー(完全な白など)では機能しません。
インスピレーションについては、 iOS Calabash-serverプロジェクト のisViewVisibleメソッドを参照してください。
ViewWillAppearで値「isVisible」をtrueに設定し、viewWillDisappearで値をfalseに設定します。 UITabBarControllerサブビューを知る最良の方法は、Navigation Controllerでも機能します。
これは、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)は読み取り/書き込みプロパティです。簡単に読み書きできます
Swift 3.の場合
if(view.isHidden){
print("Hidden")
}else{
print("visible")
}
テスト済みのソリューション。
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
}
これを試して:
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
}