iOS 11 안전 영역 레이아웃 가이드 하위 호환성
안전 영역 레이아웃 가이드가 11 미만의 iOS와 호환됩니까?
새로운 안전 영역 레이아웃 가이드로 작업하고 iOS 9 및 iOS 10과의 하위 호환성을 유지했습니다. (편집 : @NickEntin의 주석에서 지적했듯이이 구현은 상태 표시 줄이 존재한다고 가정합니다. iPhone X의 가로 모드에서는 사실입니다. 결과적으로 상단에 많은 공간 (20 포인트)이 생겼지 만 완벽하게 작동합니다.
예를 들어보기를 상태 표시 줄 아래 10 포인트 (iPhone X의 센서 하우징 아래 10 포인트)로 설정하려는 경우 :
- XIB에서
File Inspector
를 확인하여 금고 로 이동하여 활성화하십시오Use Safe Area Layout Guides
. >=
(크거나 같음) 제약 조건, 상수30
(20 점 높이 인 상태 표시 줄에 10 점 간격을두기를 원하기 때문에 30) 및 우선 순위High
(750) 를 사용하여 뷰의 상단에서 기본 뷰의 상단까지 제약 조건을 만듭니다 .=
(동일) 제약, 상수10
및 우선 순위Low
(250) 를 사용하여 뷰의 상단에서 안전 영역의 상단까지 제약 조건을 만듭니다 .
하단의보기 (및 안전 영역의 앞 / 뒤 또는 왼쪽 / 오른쪽)에 대해서도 동일하게 수행 할 수 있습니다.
- XIB에서
File Inspector
를 확인하여 금고 로 이동하여 활성화하십시오Use Safe Area Layout Guides
. >=
(크거나 같음) 제약, 상수10
및 우선 순위High
(750) 를 사용하여 뷰의 맨 아래에서 기본 뷰의 맨 아래까지 제약 조건을 만듭니다 .=
(동일) 제약, 상수10
및 우선 순위Low
(250) 를 사용하여 뷰의 하단에서 안전 영역의 하단까지 제약 조건을 만듭니다 .
iOS 9 및 iOS 10 용 안전 영역의 하위 호환성은 스토리 보드를 사용하는 경우에만 작동합니다. xibs를 사용하는 경우 대체 할 레이아웃 가이드가 없습니다. https://forums.developer.apple.com/thread/87329
해결 방법은 다음 중 하나 인 것 같습니다.
(a) xib를 스토리 보드로 마이그레이션하거나
(b) 프로그래밍 방식으로 몇 가지 추가 제약 조건을 추가합니다.
(a)가 실제로 옵션이 아닌 경우 수동 접근 방식은 다음과 같습니다.
xib에 안전 영역 (즉, 상태 표시 줄 또는 탐색 표시 줄 아래) 내에 유지하려는보기가 있다고 가정합니다.
보기와 iOS 11의 안전 영역 사이에 xib에 제약 조건을 추가합니다. 최상위 제약 조건에 우선 순위 750을 할당합니다.
뷰 컨트롤러에서 속성을 추가합니다.
@property (nonatomic, strong) NSLayoutConstraint *topLayoutConstraint;
그리고 viewDidLayoutSubviews에서 :
- (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; if (@available(iOS 11, *)) { // safe area constraints already set } else { if (!self.topLayoutConstraint) { self.topLayoutConstraint = [self.<yourview>.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor]; [self.topLayoutConstraint setActive:YES]; } } }
새로운 제약 조건은 iOS 9 및 iOS 10에 대해서만 생성되며 기본 우선 순위는 1000이며 xib의 제약 조건을 재정의합니다.
홈 인디케이터를 피해야하는 경우 하단 구속에 대해 반복합니다.
Swift 4 버전 :
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11, *) {
// safe area constraints already set
} else {
if topLayoutConstraint == nil {
topLayoutConstraint = <yourview>.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
topLayoutConstraint?.isActive = true
}
}
}
Xcode 9 GM에서 관찰 한 iOS 11의 안전 영역 제약과 관련하여 적어도 하나의 하위 호환성 문제가 있습니다. 안전 영역 제약이있는 푸시 된 뷰 컨트롤러입니다.
탐색 모음이 숨겨져 있고 안전 영역 상단 제한보기를 푸시하면 푸시 된보기가 iOS 9 및 10의 상태 표시 줄과 겹칩니다.
탐색 표시 줄이 표시되고 "상단 표시 줄 아래"가 비활성화 된 경우, 푸시 된보기는 여전히 탐색 표시 줄 아래로 슬라이드하여 화면 상단으로 이동합니다. 탐색 모음이 올바르게 배치됩니다.
iOS 11에서는 두 경우 모두 레이아웃이 정확합니다.
다음은 간단한 예입니다. http://www.filedropper.com/foobar
그리고 여기에 탐색 표시 줄이 숨겨진 비디오가 있습니다 (왼쪽에 iOS 10.3, 오른쪽에 iOS 11) : https://vimeo.com/234174841/1e27a96a87
다음은 탐색 모음이 표시되는 버전입니다 (니브에서 활성화 됨) : https://vimeo.com/234316256/f022132d57
나는 이것을 레이더 # 34477706으로 제출했습니다.
탐색 모음 표시 사례를 지적 해 주신 @Sander 에게 감사드립니다 .
스토리 보드없이 xib를 사용하는 경우 iOS 10에 레이아웃 가이드가 없습니다. 따라서 xib를 스토리 보드로 이동하여 이전 버전과의 호환성을 유지하세요.
예, 프로젝트 / 앱은 문제없이 iOS 11 이전의 iOS 버전에서 작동합니다. iOS 11 이전 버전에서는 Safe Area Layout을 일반 AutoLayout으로 대체 / 고려하며 Rules of Top and Bottom 레이아웃 가이드를 따릅니다.
두 플랫폼 (iOS 11 및 이전 버전 iOS 10)에서 'SafeAreaLayout'을 사용하거나 사용하지 않고 기존 프로젝트를 테스트했습니다. 잘 작동합니다.
다음 사항을 확인하십시오.
AutoLayout에서 프로젝트 / 사용자 인터페이스를 디자인 한 경우; UIElement의 제약 조건은 상위 및 하단 레이아웃 가이드 (superview가 아님)를 따릅니다. 따라서 SafeAreaLayout 옵션을 한 번 클릭 (활성화)하면 스토리 보드의 모든 인터페이스 빌더 파일에 대해 SafeArea 레이아웃이 자동으로 올바르게 구현됩니다.
SafeAreaLayout에서 프로젝트 / 사용자 인터페이스를 디자인 한 경우; 그런 다음 iOS 이전 버전의 상단 및 하단 레이아웃 가이드를 자동으로 따릅니다.
다음은 결과가 포함 된 샘플 스냅 샷입니다. 안전 영역 레이아웃을 활성화 또는 비활성화하면 기존 디자인에 영향을주지 않습니다.
AutoLayout
간단히 말해서, 귀하의 질문에 대한 대답은 "11 이전의 iOS와 호환되는 안전 영역 레이아웃 가이드 활성화"입니다.
프로젝트 / 앱에서 안전 영역 레이아웃을 구현할 수 있으며 안전 영역 레이아웃을 Top으로 변환하여 이전 iOS 버전에서 잘 작동합니다. 및 하단 레이아웃.
Objective-C에서 iOS 10에서 좋은 결과를 얻었습니다. xib에서 SafeArea를 사용하는 경우 다음을 추가 할 수 있습니다 viewDidLoad
.
if (@available(iOS 11.0, *)) {}
else {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
"안전 영역 레이아웃 가이드"는 이전 버전과 호환됩니다. 글쎄, xib에서 사용하지 않는 한. 스토리 보드를 사용하면 괜찮아 보입니다.
내보기 상단의 첫 번째 개체에서 "상단 레이아웃 제약"에 액세스하여 문제를 해결했습니다.
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;
그런 다음 상수 값을 해당 제약 조건으로 변경하고보기를 새로 고칩니다. 예를 들어 탐색 모음 (높이 44)과 상태 표시 줄 (높이 20)을 사용하는 경우 :
if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
_topLayoutConstraint.constant = 64;
[self.view layoutIfNeeded];
}
다음과 같이 정의 된 SYSTEM_VERSION_LESS_THAN으로 :
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
NSLayoutConstraint
.NET에 고정 된 하위 클래스 만 있으면 더 편리한 방법을 찾았습니다 safeArea
.
UIView에서 ViewController를 가져와야하므로 다소 엉망이지만 Apple이 마침내 Xibs의 safeArea에 대한 하위 호환성을 수정하기 전까지는 쉽고 좋은 대안입니다.
아강:
class SafeAreaBackwardsCompatabilityConstraint: NSLayoutConstraint {
private weak var newConstraint: NSLayoutConstraint?
override var secondItem: AnyObject? {
get {
if #available(iOS 11.0, *) {}
else {
if let vc = (super.secondItem as? UIView)?.parentViewController, newConstraint == nil {
newConstraint = (self.firstItem as? UIView)?.topAnchor.constraint(equalTo: vc.topLayoutGuide.bottomAnchor)
newConstraint?.isActive = true
newConstraint?.constant = self.constant
}
}
return super.secondItem
}
}
override var priority: UILayoutPriority {
get {
if #available(iOS 11.0, *) { return super.priority }
else { return 750 }
}
set { super.priority = newValue }
}
}
private extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
Xib :
iOS 9에서 WKWebView 및 안전 영역과의 하위 호환성 문제가 있습니다. 어떤 이유로 WKWebView는 단순히 안전 영역 레이아웃 설정을 무시합니다.
Objective-C에서 iPhone-X의 상단 및 하단 여백
if (@available(iOS 11, *)) {
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.parentView.safeAreaLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.parentView.safeAreaLayoutGuide
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0];
} else {
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.parentView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.parentView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0];
}
내 프로젝트로 한 작업은 다음과 같습니다.
제 경우에는 my topConstraint
와 bottomConstraint
s가 모두 @IBOutlet
s입니다. 이것은 iOS 8
.
상단 및 하단 제약 조건에 대한 초기 구성은 일반 iPhone 용이므로 iPhone X에 대한 제약 조건 만 편집하고 있습니다.
// iOS 11 Layout Fix. (For iPhone X)
if #available(iOS 11, *) {
self.topConstraint.constant = self.topConstraint.constant + self.view.safeAreaInsets.top
self.bottomConstraint.constant = self.bottomConstraint.constant + self.view.safeAreaInsets.bottom
}
.
참고 : self.view
SuperView를 사용하는 이유입니다.safeAreaInsets
모든 ViewController가 확장하는 일반 ViewController가있는 경우 다른 솔루션은 조정해야하는 항목을 IBOutletCollection에 넣고 해당 GenericViewController에서 프로그래밍 방식으로 조정하는 것입니다. 내 코드는 다음과 같습니다.
@IBOutlet var adjustTopSpaceViews: [UIView]?
override func viewDidLoad() {
super.viewDidLoad()
adjustViews()
....
}
func adjustViews() {
guard let views = adjustTopSpaceViews,
ProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11 else {
return
}
let statusBarHeight = UIApplication.shared.statusBarFrame.height
for subview in views {
subview.superview?.constraints.filter({ (constraint) -> Bool in
return constraint.firstAttribute == .top
&& constraint.secondAttribute == .top
&& (constraint.firstItem as? UIView == subview || constraint.secondItem as? UIView == subview)
}).forEach({ (constraint) in
constraint.constant += (constraint.firstItem as? UIView == subview) ? statusBarHeight : -statusBarHeight
})
}
}
다음은 신속한 4+의 iOS 9에서 iOS 11+ 솔루션 래퍼입니다.
let safeAreaTopAnchor:NSLayoutYAxisAnchor?
if #available(iOS 11.0, *) {
safeAreaTopAnchor = contentView.safeAreaLayoutGuide.topAnchor
} else {
// Fallback on earlier versions
var parentViewController: UIViewController? {
var parentVCResponder: UIResponder? = self
while parentVCResponder != nil {
parentVCResponder = parentVCResponder!.next
if let viewController = parentVCResponder as? UIViewController {
return viewController
}
}
return nil
}
safeAreaTopAnchor = parentViewController?.topLayoutGuide.bottomAnchor
}
스위프트 5
그냥 해요. 간단하고 실물에 매우 가깝습니다 ( 'r'만 추가됨).
extension UIView {
var saferAreaLayoutGuide: UILayoutGuide {
get {
if #available(iOS 11.0, *) {
return self.safeAreaLayoutGuide
} else {
return self.layoutMarginsGuide
}
}
}
다음과 같이 사용하십시오.
button.topAnchor.constraint(equalTo: view.saferAreaLayoutGuide.topAnchor, constant: 16)
참고 URL : https://stackoverflow.com/questions/46184197/ios-11-safe-area-layout-guide-backwards-compatibility
'developer tip' 카테고리의 다른 글
쿼리 문자열 키는 대소 문자를 구분합니까? (0) | 2020.12.04 |
---|---|
Java 8의 문자열 중복 제거 기능 (0) | 2020.12.04 |
두 개의 큰 정수를 곱하는 동안 오버플로를 잡아서 계산 (0) | 2020.12.03 |
참조 주소를 찾을 수있는 방법이 있습니까? (0) | 2020.12.03 |
JPQL Select 문에서 새 개체 만들기-피하거나 포용 하시겠습니까? (0) | 2020.12.03 |