사용자에게 UIView가 보이는지 확인합니다.
합니까 할 수 ?UIView사용자가 볼 수 있습니까?
내 보기는 다음으로 추가됩니다.subviewa에 몇 Tab Bar Controller.
의 각 과 같이 구성됩니다.NSTimer보기를 업데이트합니다.
그러나 사용자에게 보이지 않는 보기를 업데이트하고 싶지 않습니다.
가능한가요?
감사해요.
여기까지 오는 다른 사람들을 위해:
UI를 하는 대신 가 화면 superview != nil인지 .window != nil 수 전자의 경우 뷰에 수퍼뷰가 있지만 수퍼뷰가 화면에 표시되지 않을 수 있습니다.
if (view.window != nil) {
// do stuff
}
합니다.hidden가 있는 .alpha > 0.
의 를 않는 것에 .NSTimer뷰가 보이지 않는 동안 실행하려면 이러한 뷰를 수동으로 숨기고 뷰가 숨겨지면 타이머가 중지되도록 해야 합니다.하지만 저는 당신이 무엇을 하고 있는지 전혀 확신할 수 없습니다.
다음을 확인할 수 있습니다.
- 보기를 확인하여 숨깁니다.숨겨진
- 선택하여 .
view.superview != nil - 보기의 경계를 확인하여 화면에 표시되는지 확인할 수 있습니다.
내가 생각할 수 있는 유일한 것은 당신의 견해가 다른 사람들 뒤에 묻혀 있고 그 이유로 볼 수 없는 경우입니다.여러분은 자신의 시야를 흐리게 하는지 알아보기 위해 뒤에 오는 모든 시야를 살펴봐야 할 수도 있습니다.
이렇게 하면 뷰의 프레임이 모든 뷰의 경계(루트 뷰까지) 내에 있는지 여부가 결정됩니다.실제 사용 사례 중 하나는 하위 보기가 스크롤 보기 내에 (부분적으로) 표시되는지 여부를 판단하는 것입니다.
Swift 5.x:
func isVisible(view: UIView) -> Bool {
func isVisible(view: UIView, inView: UIView?) -> Bool {
guard let inView = inView else { return true }
let viewFrame = inView.convert(view.bounds, from: view)
if viewFrame.intersects(inView.bounds) {
return isVisible(view: view, inView: inView.superview)
}
return false
}
return isVisible(view: view, inView: view.superview)
}
이전 swift 버전
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할 수 ,
저에게 효과적인 해결책은 먼저 뷰에 창이 있는지 확인한 다음, 뷰에 대한 반복 및 다음 사항을 확인하는 것이었습니다.
- 뷰는 숨기지 않습니다.
- 시야는 시야 범위 내에 있습니다.
아직까지는 잘 되는 것 같습니다.
스위프트 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
}
저는 @Audrey M.과 @John Gibb의 솔루션을 모두 벤치마킹했습니다.
그리고 @Audrey M. his way가 더 좋은 성적을 거두었습니다(10회).
그래서 저는 그것을 관찰할 수 있도록 하기 위해 그것을 사용했습니다.
UIView가 표시되면 알림을 받기 위해 RxSwift Observable을 만들었습니다.
이벤트 기'다를 할 수 .
import Foundation
import UIKit
import RxSwift
extension UIView {
var isVisibleToUser: Bool {
if isHidden || alpha == 0 || superview == nil {
return false
}
guard let rootViewController = UIApplication.shared.keyWindow?.rootViewController else {
return false
}
let viewFrame = convert(bounds, to: rootViewController.view)
let topSafeArea: CGFloat
let bottomSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = rootViewController.view.safeAreaInsets.top
bottomSafeArea = rootViewController.view.safeAreaInsets.bottom
} else {
topSafeArea = rootViewController.topLayoutGuide.length
bottomSafeArea = rootViewController.bottomLayoutGuide.length
}
return viewFrame.minX >= 0 &&
viewFrame.maxX <= rootViewController.view.bounds.width &&
viewFrame.minY >= topSafeArea &&
viewFrame.maxY <= rootViewController.view.bounds.height - bottomSafeArea
}
}
extension Reactive where Base: UIView {
var isVisibleToUser: Observable<Bool> {
// Every second this will check `isVisibleToUser`
return Observable<Int>.interval(.milliseconds(1000),
scheduler: MainScheduler.instance)
.map { [base] _ in
return base.isVisibleToUser
}.distinctUntilChanged()
}
}
다음과 같이 사용합니다.
import RxSwift
import UIKit
import Foundation
private let disposeBag = DisposeBag()
private func _checkBannerVisibility() {
bannerView.rx.isVisibleToUser
.filter { $0 }
.take(1) // Only trigger it once
.subscribe(onNext: { [weak self] _ in
// ... Do something
}).disposed(by: disposeBag)
}
검증된 해결책.
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
}
사용자가 보기를 볼 수 있는지 알고 싶다면 다음 사항을 고려해야 합니다.
- 뷰의 창이 0이 아니며 맨 위의 창과 같습니까?
- 뷰, 및 모든 뷰는 alpha >= 0.01 (UIKit에서 터치를 처리해야 하는지 여부를 판단하기 위해 사용하는 threshold 값)이며 숨김이 없습니다.
- 뷰의 z 인덱스(적층 값)가 동일한 계층의 다른 뷰보다 높습니까?
- z-index가 낮더라도 맨 위의 다른 보기에 투명 배경색, 알파 0 또는 숨겨진 경우 볼 수 있습니다.
특히 투명한 배경색의 전방 뷰는 프로그래밍적으로 확인하기에 문제가 될 수 있습니다.진정으로 확신할 수 있는 유일한 방법은 전체 화면의 스냅샷을 사용하여 해당 프레임 내에서 확인 및 차이를 확인할 수 있는 프로그램 스냅샷을 만드는 것입니다.그러나 이는 충분히 고유하지 않은 보기(예: 완전 흰색)에서는 작동하지 않습니다.
영감은 iOS Calabash-server 프로젝트에서 ViewVisible 메서드를 참조하십시오.
내 상황에서 작동하는 가장 간단한 Swift 5 솔루션(테이블에 내장된 버튼을 찾고 있었습니다View바닥).
존 깁스의 해결책도 효과가 있었지만 저로서는 모든 재귀를 필요로 하지 않았습니다.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let viewFrame = scrollView.convert(targetView.bounds, from: targetView)
if viewFrame.intersects(scrollView.bounds) {
// targetView is visible
}
else {
// targetView is not visible
}
}
보기에서 "isVisible" 값을 true로 설정하고 보기에서 WillDispare는 false로 설정합니다.UITabBarController 하위 보기에 가장 적합한 방법은 탐색 컨트롤러에도 적용됩니다.
또 다른 유용한 방법은didMoveToWindow()예:뷰 컨트롤러를 누르면 이전 뷰 컨트롤러의 뷰가 이 메서드를 호출합니다.체킹self.window != nil안에didMoveToWindow()화면에서 보기가 표시되는지 또는 사라지는지 확인하는 데 도움이 됩니다.
이를 통해 UI 보기가 최상위 보기인지 확인할 수 있습니다.도움이 될 수 있음:
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
}
시도해 보십시오.
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
}
숨겨진 뷰 속성을 사용하는 경우:
view.hidden(객관적 C) 또는 view.isHidden(swift)은 읽기/쓰기 속성입니다.그래서 쉽게 읽거나 쓸 수 있습니다.
빠른 3.0용
if(view.isHidden){
print("Hidden")
}else{
print("visible")
}
언급URL : https://stackoverflow.com/questions/1536923/determine-if-uiview-is-visible-to-the-user
'programing' 카테고리의 다른 글
| SQL: 전체 이름 필드에서 이름, 중간 및 성을 구문 분석합니다. (0) | 2023.10.11 |
|---|---|
| phphmyadmin을 사용하여 캐스케이드 삭제 및 업데이트 제한에 추가하는 방법은? (0) | 2023.10.11 |
| 헤더 파일의 정적 인라인 함수 (0) | 2023.10.11 |
| MYSQL로 연결된 동적 PHP 사이트를 CMS로 변환하는 쉬운 방법? (0) | 2023.10.11 |
| CSS 애니메이션 종료 시 최종 상태 유지 (0) | 2023.10.11 |