상단과 하단의 높이에 안전한 영역을 확보합니다.
안전하지 않은 지역에 대해 위아래 높이를 모두 얻는 가장 적절한 방법은 무엇일까요?
다음을 시도해 보십시오.
목표 C에서
if (@available(iOS 11.0, *)) {
UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
CGFloat topPadding = window.safeAreaInsets.top;
CGFloat bottomPadding = window.safeAreaInsets.bottom;
}
인스위프트
if #available(iOS 11.0, *) {
let window = UIApplication.shared.keyWindow
let topPadding = window?.safeAreaInsets.top
let bottomPadding = window?.safeAreaInsets.bottom
}
Swift - iOS 13.0 이후
// Windows 어레이의 첫 번째 요소를 Key Window가 사용하지 않도록 사용
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.first
let topPadding = window.safeAreaInsets.top
let bottomPadding = window.safeAreaInsets.bottom
}
레이아웃 가이드 사이의 높이를 구하려면
let guide = view.safeAreaLayoutGuide
let height = guide.layoutFrame.size.height
★★★★★★★★★★★★★★★★★.full frame height = 812.0
,safe area height = 734.0
녹색 뷰의 프레임은 다음과 같습니다.guide.layoutFrame
스위프트 4, 5
뷰는 API에 의해 큐잉되고 뷰가 메모리에 로드된 후 처리되기 때문에 뷰 컨트롤러의 라이프사이클 중 어느 곳에서나 구속조건을 사용하여 뷰를 안전한 영역 앵커에 고정시킬 수 있습니다.그러나 안전 뷰.를 들어 뷰 컨트롤러의 라이프 사이클이 끝날 때까지 기다려야 합니다.viewDidLayoutSubviews()
.
이는 모든 뷰 컨트롤러에 연결됩니다.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let topSafeArea: CGFloat
let bottomSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = view.safeAreaInsets.top
bottomSafeArea = view.safeAreaInsets.bottom
} else {
topSafeArea = topLayoutGuide.length
bottomSafeArea = bottomLayoutGuide.length
}
// safe area values are now available to use
}
API의 설계방법과 디바이스 방향 변경 등 모든 뷰 변경 시 값이 갱신되기 때문에 윈도우에서 (가능한 경우) 해제하는 것보다 이 방법을 선호합니다.
그러나 일부 커스텀 표시 뷰 컨트롤러는 위의 방법을 사용할 수 없습니다(일시 컨테이너 뷰에 있기 때문에 의심됩니다).이 경우 루트 뷰 컨트롤러에서 값을 얻을 수 있습니다.이 값은 현재 뷰 컨트롤러의 라이프 사이클 중 어디에서나 항상 사용할 수 있습니다.
anyLifecycleMethod()
guard let root = UIApplication.shared.keyWindow?.rootViewController else {
return
}
let topSafeArea: CGFloat
let bottomSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = root.view.safeAreaInsets.top
bottomSafeArea = root.view.safeAreaInsets.bottom
} else {
topSafeArea = root.topLayoutGuide.length
bottomSafeArea = root.bottomLayoutGuide.length
}
// safe area values are now available to use
}
여기 있는 다른 대답들은 다 통하지 않았지만, 이건 통했어
var topSafeAreaHeight: CGFloat = 0
var bottomSafeAreaHeight: CGFloat = 0
if #available(iOS 11.0, *) {
let window = UIApplication.shared.windows[0]
let safeFrame = window.safeAreaLayoutGuide.layoutFrame
topSafeAreaHeight = safeFrame.minY
bottomSafeAreaHeight = window.frame.maxY - safeFrame.maxY
}
여기 있는 모든 답변이 도움이 됩니다. 도움을 주신 모든 분들 덕분입니다.
그러나 안전 구역의 토픽은 조금 혼란스러워서 잘 문서화되어 있지 않은 것 같습니다.
한 한 하겠습니다.safeAreaInsets
,safeAreaLayoutGuide
★★★★★★★★★★★★★★★★★」LayoutGuide
.
7에서는, 이 iOS 을 도입했습니다.topLayoutGuide
★★★★★★★★★★★★★★★★★」bottomLayoutGuide
의 UIViewController
상태, 네비게이션, 탭바 등의 UIKit 바에 의해 컨텐츠가 숨겨지지 않도록 제약조건을 작성할 수 있었습니다.이러한 레이아웃 가이드에서는 컨텐츠의 제약조건을 지정할 수 있었습니다.상단 또는 하단의 네비게이션 요소(UIKit 바, 상태 바, 네비게이션, 탭 바…)에 의해 컨텐츠가 숨겨지는 것을 피할 수 있었습니다.
예를 들어 tableView를 작성하려면 위의 화면에서 다음과 같은 작업을 수행합니다.
self.tableView.contentInset = UIEdgeInsets(top: -self.topLayoutGuide.length, left: 0, bottom: 0, right: 0)
iOS 11에서는 Apple이 이러한 속성을 단일 안전 영역 레이아웃 가이드로 대체하는 것을 권장하지 않습니다.
애플에 의한 안전 구역
안전 영역은 전체 인터페이스의 가시적인 부분 내에 뷰를 배치하는 데 도움이 됩니다.UIKit 정의 뷰 컨트롤러는 콘텐츠 위에 특별한 뷰를 배치할 수 있습니다.예를 들어 네비게이션컨트롤러는 기본 뷰컨트롤러의 콘텐츠 위에 네비게이션바를 표시합니다.이러한 보기는 부분적으로 투명하더라도 여전히 아래에 있는 내용을 차단합니다.TVOS에서 세이프 영역에는 스크린 베젤로 덮인 영역을 나타내는 오버스캔 삽입도 포함됩니다.
iPhone 8 및 iPhone X 시리즈의 안전 영역을 다음에 나타냅니다.
safeAreaLayoutGuide
의 특성입니다.UIView
★★★★★★★★★★★★★★의 높이를 .safeAreaLayoutGuide
:
extension UIView {
var safeAreaHeight: CGFloat {
if #available(iOS 11, *) {
return safeAreaLayoutGuide.layoutFrame.size.height
}
return bounds.height
}
}
그러면 사진의 화살표 높이가 반환됩니다.
이제 홈 스크린의 최고 "노치" 표시 높이와 최저 표시 높이를 얻는 것은 어떨까요?
에서는 ★★★★★★를 사용합니다.safeAreaInsets
뷰의 안전 영역에는 뷰 컨트롤러의 뷰를 가리는 탐색 막대, 탭 막대, 도구 모음 및 기타 상위 항목이 포함되지 않은 영역이 반영됩니다.(tvOS에서는 세이프 영역은 화면 베젤에 가려지지 않는 영역을 반영합니다.)뷰의 경계 직사각형에 이 특성의 삽입물을 적용하여 뷰에 대한 안전 영역을 얻습니다.뷰가 현재 뷰 계층에 설치되어 있지 않거나 아직 화면에 표시되지 않으면 이 속성의 가장자리 삽입은 0입니다.
다음은 iPhone 8 및 iPhone X 시리즈 중 하나에서 안전하지 않은 영역과 가장자리와의 거리를 보여 줍니다.
네비게이션 바가 추가된 경우
'어,어,어,어,어,어,어,어,어?'를 사용하겠습니다.safeAreaInset
솔루션에는 중요한 점에서 차이가 있지만
첫 번째:
self.view.safeAreaInsets
그러면 EdgeInset이 반환되며, 이제 상단 및 하단에 액세스하여 삽입된 내용을 확인할 수 있습니다.
두 번째:
UIApplication.shared.windows.first{$0.isKeyWindow }?.safeAreaInsets
첫 번째 뷰는 삽입되므로 네비게이션바가 있는 경우 고려되지만 두 번째 뷰는 창의 safeAreaInset에 액세스하기 때문에 네비게이션바는 고려되지 않습니다.
Swift 5, X코드 11.4
`UIApplication.shared.keyWindow`
폐지 경고가 표시됩니다.iOS 13.0에서는 "key Window"가 사용되지 않습니다. 연결된 모든 장면에서 키 창을 반환하므로 여러 장면을 지원하는 애플리케이션에는 사용하지 마십시오.저는 이렇게 써요.
extension UIView {
var safeAreaBottom: CGFloat {
if #available(iOS 11, *) {
if let window = UIApplication.shared.keyWindowInConnectedScenes {
return window.safeAreaInsets.bottom
}
}
return 0
}
var safeAreaTop: CGFloat {
if #available(iOS 11, *) {
if let window = UIApplication.shared.keyWindowInConnectedScenes {
return window.safeAreaInsets.top
}
}
return 0
}
}
extension UIApplication {
var keyWindowInConnectedScenes: UIWindow? {
return windows.first(where: { $0.isKeyWindow })
}
}
iOS 11에는 safeArea가 변경되었음을 알려주는 메서드가 있습니다.
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
let top = view.safeAreaInsets.top
let bottom = view.safeAreaInsets.bottom
}
이는 Swift의 심플한 2라인 솔루션으로서 뷰 라이프 사이클 전체에 걸쳐 유효합니다.
let top = UIApplication.shared.windows[0].safeAreaInsets.top
let bottom = UIApplication.shared.windows[0].safeAreaInsets.bottom
난 개인적으로 그게 필요했어viewDidLoad
그리고.view.safeAreaInsets
아직 계산되지 않았습니다.
safeAreaLayoutGuide 뷰가 화면에 표시되는 경우 이 가이드에는 탐색 막대, 탭 막대, 도구 모음 및 기타 상위 뷰에서 다루지 않는 뷰 부분이 반영됩니다.(tvOS에서 세이프 영역은 화면 베젤을 덮지 않은 영역을 나타냅니다.)뷰가 현재 뷰 계층에 설치되어 있지 않거나 아직 화면에 표시되지 않는 경우 레이아웃 가이드 가장자리는 뷰의 가장자리와 동일합니다.
스크린샷의 빨간색 화살표 높이를 확인하려면 다음과 같이 하십시오.
self.safeAreaLayoutGuide.layoutFrame.size.height
Swift 5 확장
이는 내선번호로 사용할 수 있으며 UIApplication.topSafeAreaHeight와 함께 호출할 수 있습니다.
extension UIApplication {
static var topSafeAreaHeight: CGFloat {
var topSafeAreaHeight: CGFloat = 0
if #available(iOS 11.0, *) {
let window = UIApplication.shared.windows[0]
let safeFrame = window.safeAreaLayoutGuide.layoutFrame
topSafeAreaHeight = safeFrame.minY
}
return topSafeAreaHeight
}
}
UIApplication의 확장은 옵션이며, UIView의 확장 또는 원하는 모든 기능을 사용할 수 있습니다.또, 글로벌 기능의 확장도 가능합니다.
저는 코코아팟 프레임워크로 일하고 있는데 만약을 위해UIApplication.shared
사용할 수 없습니다.safeAreaInsets
의 시야에 있는window
:
if #available(iOS 11.0, *) {
let insets = view.window?.safeAreaInsets
let top = insets.top
let bottom = insets.bottom
}
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
CGFloat fBottomPadding = window.safeAreaInsets.bottom;
Swift의 경우UI:
코드
private struct SafeAreaInsetsKey: EnvironmentKey {
static var defaultValue: EdgeInsets {
UIApplication.shared.windows[0].safeAreaInsets.insets
}
}
extension EnvironmentValues {
var safeAreaInsets: EdgeInsets {
self[SafeAreaInsetsKey.self]
}
}
private extension UIEdgeInsets {
var insets: EdgeInsets {
EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
}
}
사용.
struct MyView: View {
@Environment(\.safeAreaInsets) private var safeAreaInsets
var body: some View {
Text("Ciao")
.padding(safeAreaInsets)
}
}
또는 Swift 사용UI GeometryReader API.
struct V: View {
var body: some View {
GeometryReader { geometry in
Text("\(geometry.safeAreaInsets.top)")
Text("\(geometry.safeAreaInsets.bottom)")
}
}
}
코드가 작동하지 않을 수 있지만, 아이디어를 보여줍니다.
목표-C 키창이 0일 때 문제가 발생한 사용자위의 코드를 viewDidEar에 넣기만 하면 됩니다(viewDidLoad가 아님).
iOS 13+/Swift 5의 경우, 여기에서는 이것 말고는 아무것도 동작하지 않았습니다.
if #available(iOS 13.0, *) {
topPadding = UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0
bottomPadding = UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0
}
보다 포괄적인 어프로치
import SnapKit
let containerView = UIView()
containerView.backgroundColor = .red
self.view.addSubview(containerView)
containerView.snp.remakeConstraints { (make) -> Void in
make.width.top.equalToSuperView()
make.top.equalTo(self.view.safeArea.top)
make.bottom.equalTo(self.view.safeArea.bottom)
}
extension UIView {
var safeArea: ConstraintBasicAttributesDSL {
if #available(iOS 11.0, *) {
return self.safeAreaLayoutGuide.snp
}
return self.snp
}
var isIphoneX: Bool {
if #available(iOS 11.0, *) {
if topSafeAreaInset > CGFloat(0) {
return true
} else {
return false
}
} else {
return false
}
}
var topSafeAreaInset: CGFloat {
let window = UIApplication.shared.keyWindow
var topPadding: CGFloat = 0
if #available(iOS 11.0, *) {
topPadding = window?.safeAreaInsets.top ?? 0
}
return topPadding
}
var bottomSafeAreaInset: CGFloat {
let window = UIApplication.shared.keyWindow
var bottomPadding: CGFloat = 0
if #available(iOS 11.0, *) {
bottomPadding = window?.safeAreaInsets.bottom ?? 0
}
return bottomPadding
}
}
가로 모드로 변경하는 사용자는 회전 후에 반드시 viewSafeAreaInsetsDidChange를 사용하여 최신 값을 얻어야 합니다.
private var safeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
override func viewSafeAreaInsetsDidChange() {
if #available(iOS 11.0, *) {
safeAreaInsets = UIApplication.shared.keyWindow!.safeAreaInsets
}
}
스위프트 4
if let window = UIApplication.shared.windows.first {
let topPadding = window.safeAreaInsets.top
let bottomPadding = window.safeAreaInsets.bottom
}
수업에서 사용
class fitToTopInsetConstraint: NSLayoutConstraint {
override func awakeFromNib() {
if let window = UIApplication.shared.windows.first {
let topPadding = window.safeAreaInsets.top
self.constant += topPadding
}
}
}
class fitToBottomInsetConstraint: NSLayoutConstraint {
override func awakeFromNib() {
if let window = UIApplication.shared.windows.first {
let bottomPadding = window.safeAreaInsets.bottom
self.constant += bottomPadding
}
}
}
애플리케이션을 빌드할 때 안전 영역 패딩을 볼 수 있습니다.
extension UIViewController {
var topbarHeight: CGFloat {
return
(view.window?.safeAreaInsets.top ?? 0) +
(view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
(self.navigationController?.navigationBar.frame.height ?? 0.0)
}
}
다음은 rootController를 배치한 후 호출할 수 있는 다른 응답에 기초한 무료 함수입니다.프리 스탠딩 기능으로 사용할 수 있습니다.
func safeAreaInsets() -> UIEdgeInsets? {
(UIApplication
.shared
.keyWindow?
.rootViewController)
.flatMap {
if #available(iOS 11.0, *) {
return $0.view.safeAreaInsets
} else {
return .init(
top: $0.topLayoutGuide.length,
left: .zero,
bottom: $0.bottomLayoutGuide.length,
right: .zero
)
}
}
}
iPhone 14 디바이스의 경우 다음과 같이 사용합니다.
let app = UIApplication.shared
var statusBarHeight: CGFloat = 0.0
let window = app.windows.filter {$0.isKeyWindow}.first
statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
let topPadding = window?.safeAreaInsets.top ?? 0.0
statusBarHeight = statusBarHeight >= topPadding ? statusBarHeight:topPadding
여기 모든 아이폰의 안전 영역 높이를 찾는 간단한 답이 있습니다.
let window = UIApplication.shared.windows[0]
let SafeAreaHeight = window.safeAreaLayoutGuide.layoutFrame.size.height
언급URL : https://stackoverflow.com/questions/46829840/get-safe-area-inset-top-and-bottom-heights
'programing' 카테고리의 다른 글
MVVM: ListBox에 바인딩하고 있습니다.선택된항목이 업데이트되지 않습니까? (0) | 2023.04.15 |
---|---|
Bash가 다른 디렉토리 컨텍스트에서 명령을 실행하려면 어떻게 해야 합니까? (0) | 2023.04.15 |
엑셀 워크시트를 이름으로 참조하시겠습니까? (0) | 2023.04.15 |
POI를 사용하여 오래된 Excel .xls 파일을 처리하는 방법 (0) | 2023.04.15 |
특정 날짜 이후 행 나열 (0) | 2023.04.15 |