CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.
Bài viết blog CFSDN này giải thích chi tiết về iOS 11 safeArea và chuyển thể cho iPhoneX được tác giả sưu tầm và biên soạn. Nếu các bạn quan tâm đến bài viết này thì nhớ like nhé.
Gần đây tôi đã đọc rất nhiều bài viết về iPhone
Hiện nay đối với việc điều chỉnh iPhone X, một phương pháp phổ biến là thêm khoảng cách cố định vào thanh điều hướng hoặc thanh tab, chẳng hạn như thêm 44pt ở trên cùng và 34pt ở dưới cùng. Phương pháp viết khoảng cách chết này thoạt nhìn có vẻ đơn giản nhưng thực chất nó không tốt vì những lý do sau.
-
Nó không phù hợp để thích ứng với nhiều mẫu máy. Nếu trong tương lai một chiếc iPad có tiếng nổ được phát hành, khoảng cách cần đặt trước có thể không phải là khoảng cách đã được mã hóa cứng hiện nay.
-
Nó không phù hợp với các ứng dụng cần hỗ trợ màn hình ngang và dọc. Không cần tăng khoảng cách ở phía trên màn hình ngang. Thay vào đó, khoảng cách ở phía dưới cũng khác nhau. từ màn hình dọc.
-
Không đủ năng động. Ví dụ: nếu có cuộc gọi đến, thanh điều hướng sẽ di chuyển xuống và chế độ xem có thể vẫn bị chặn tại thời điểm này.
Ở đây tôi muốn thảo luận về cách sử dụng safearealayoutguide và safeareainsets một cách năng động để giải quyết vấn đề thích ứng của iPhone X và thậm chí tất cả các mẫu tiếp theo một lần và mãi mãi.
hướng dẫn bố trí vùng an toàn。
Trước tiên hãy xem hướng dẫn về khu vực an toàn là gì.

Nhìn có vẻ phức tạp nhưng thực ra nó rất đơn giản.
-
Nó là thuộc tính chỉ đọc của uiview, có nghĩa là tất cả các đối tượng uiview đều có nó và nó được hệ thống tạo ra cho chúng ta.
-
Nó kế thừa uilayoutguide và bố cục có nghĩa là nó có thể đại diện cho một khu vực.
-
Khu vực mà nó đại diện sẽ tránh tất cả các chế độ xem chính như thanh điều hướng, thanh tab hoặc các chế độ xem chính khác có thể chặn hiển thị đối tượng uiview của bạn. Điều này có nghĩa là miễn là đối tượng chế độ xem của bạn được bố trí tương ứng với hướng dẫn bố cục an toàn của một chế độ xem khác. bạn không phải lo lắng về việc nó có gì đó kỳ lạ.
-
Đối với hướng dẫn khu vực an toàn của chế độ xem của bộ điều khiển, khu vực của nó cũng tránh thanh trạng thái hoặc những thứ khác có thể chặn hiển thị chế độ xem. Chúng tôi thậm chí có thể sử dụng thuộc tính bổ sung khu vực an toàn của bộ điều khiển để chỉ định thêm phần lồng ghép.
-
Nếu chế độ xem hoàn toàn nằm trong vùng an toàn của chế độ xem gốc hoặc chế độ xem không nằm trong phân cấp chế độ xem hoặc trên màn hình thì khu vực hướng dẫn khu vực an toàn của chế độ xem thực sự có cùng kích thước với chính chế độ xem đó.
safearealayoutguide là một khái niệm tương đối trừu tượng, chúng ta có thể coi safearealayoutguide như một "view". Hệ thống "view" này tự động giúp chúng ta điều chỉnh giới hạn của nó để không bị chặn bởi mọi thứ lạ, bao gồm cả. khu vực tóc mái của iPhone X và khu vực thanh ngang phía dưới, có thể coi là mọi nội dung đều có thể hiển thị đầy đủ trên "view" này.
Phần màu xanh bên dưới là vùng safealayoutguide của chế độ xem bộ điều khiển hiện tại.

bounds.png của iphone x màn hình dọc safearealayoutguide.

bounds.png của iphone x màn hình ngang safearealayoutguide.
Ảnh chụp màn hình từ https://developer.apple.com/videos/play/fall2017/801/.
Nhưng có một điều cần lưu ý là "view" này sẽ không được hiển thị trong hệ thống phân cấp view của chúng ta. uilayoutguides sẽ không hiển thị trong hệ thống phân cấp chế độ xem nhưng có thể được sử dụng làm các mục trong một ràng buộc nslayout và biểu thị một hình chữ nhật trong công cụ bố cục.
Theo tôi, vai trò lớn nhất của nó là tham chiếu, cho phép view được bố trí tương ứng với safearealayoutguide của một view nhất định, từ đó đảm bảo rằng view có thể được hiển thị một cách bình thường và an toàn (view tương đối không nhất thiết phải là view cha). xem).
Trong trường hợp sử dụng thông thường, một trong các chế độ xem của tôi trước đây được bố trí tương ứng với chế độ xem của bộ điều khiển, nhưng bây giờ nó được bố trí tương ứng với chế độ xem safearealayoutguide của chế độ xem của bộ điều khiển.
Nó từng được viết như thế này [nslayoutconstraint ràng buộcwithitem:someview attribute:nslayoutattributetop liên quanby:nslayoutrelationequal toitem:self.vc.view attribute:nslayoutattributetop multiplier:1.0 constant:0],
Hướng dẫn này có sẵn [nslayoutconstraint constraintswithitem:someview attribute:nslayoutattributetop relatedby:nslayoutrelationequal toitem:self.vc.view.safearealayoutguide attribute:nslayoutattributetop multiplier:1.0 constant:0],
Hiệu ứng trước và sau khi thích ứng.

Trước khi thích ứng.png.

Sau khi thay đổi thành safearealayoutguide liên quan đến chế độ xem - dọc screen.png.

Sau khi thay đổi thành safearealayoutguide liên quan đến chế độ xem - màn hình ngang.png.
Có thể thấy, trong cùng một bố cục, khi không có thanh trạng thái ở màn hình ngang thì khoảng cách từ trên xuống là 0 và bên trái là 44. Nếu có thanh trạng thái thì khoảng cách từ trên xuống là 20. Dù sao đi nữa, dù chúng ta làm như thế nào, miễn là chúng ta bố trí nó phù hợp với safearealayoutguide, thì chế độ xem của chúng ta có thể được hiển thị một cách an toàn và đầy đủ.
Vậy tôi phải làm gì nếu đó không phải là iOS 11?
Không phải iOS11 vẫn chỉ có thể xem bố cục, vì vậy bạn cần viết hai bộ mã bố cục, sẽ được giới thiệu sau.
Điều này có đủ để giải quyết mọi tình huống không?
Không thực sự.
Một bên của chế độ xem tùy chỉnh của chúng tôi cần phải sát mép màn hình. Ví dụ: trong dự án của tôi, có một thanh điều hướng tùy chỉnh và phần trên cùng của nó nằm cạnh phần trên cùng của màn hình. out so với hướng dẫn bố trí khu vực an toàn của chế độ xem, nếu không phần trên sẽ trống trong một thời gian.
bố cục khung.
Bây giờ đến lượt các khu vực an toàn đóng một vai trò nào đó.
khu vực an toàn 。
Trước tiên, chúng ta hãy xem lời giải thích chính thức về các bộ khu vực an toàn.

Bạn có nghĩ nó tương tự như safearealayoutguide không? safearealayoutguide có thể điều chỉnh giới hạn của nó dựa trên các tập hợp vùng an toàn.
Vùng an toàn của chế độ xem của bộ điều khiển chiếm toàn bộ màn hình khi iPhone
Trong trường hợp này, đối với thanh điều hướng trên cùng được tùy chỉnh, chúng ta có thể thêm vc.view.safeareains.top vào chiều cao của thanh điều hướng để làm cho nó cao hơn một chút, sao cho trên x, khi màn hình thẳng đứng, top = 44 Khi màn hình nằm ngang, top = 0 và chiều cao của thanh điều hướng có thể phản hồi với những thay đổi.
Cần lưu ý rằng cả safealayoutguide và safeareainsets chỉ có thể được sử dụng trên ios11. Đối với các vùng an toàn, chúng ta có thể viết phán quyết phiên bản trong một hàm.
Chúng ta có thể viết nó như thế này.
?
1
2
3
4
5
6
|
tĩnh
nội tuyến
uiedgeinsets sgm_safeareainset(uiview *view) {
nếu như
(@available(ios 11.0, *)) {
trở lại
view.safeareainsets;
}
trở lại
uiedgeinsetszero;
}
|
?
1
2
3
|
uiedgeinsets safeareainsets = sgm_safeareainset(self.view);
chiều cao cgfloat = kdefaulttopviewheight;
chiều cao += safeareainsets.top > 0 ? safeareainsets.top : 20.0;
|
Câu hỏi lại xuất hiện, đâu là nơi thích hợp để đặt mã này? Như đã đề cập trong tài liệu chính thức trước đó, nếu chế độ xem không nằm trên màn hình hoặc trong hệ thống phân cấp hiển thị, thì safeareainsets của chế độ xem = uiedgeinsetszero, vì vậy chúng ta cần biết rõ khi nào các vùng an toàn thay đổi.
Trên thực tế, hệ thống đã cung cấp lệnh gọi lại.
cho bộ điều khiển uiview.
。
Sao chép mã Mã này như sau:
-(void)viewsafeareainsetsdidchange ns_requires_super api_available(ios(11.0), tvos(11.0));
。
cho uiview.
?
1
|
-(
vô hiệu
)safeareainsetsdidchange api_available(ios(11.0),tvos(11.0));
|
Ở đây chúng ta chủ yếu thảo luận về lệnh gọi lại của bộ điều khiển và lệnh gọi lại của khung nhìn cũng tương tự. Miễn là các vùng an toàn của chế độ xem của bộ điều khiển thay đổi, hệ thống sẽ gọi viewsafeareainsdidchange. Đương nhiên, chúng tôi muốn đặt đoạn mã trên ở đây, nhưng có một lỗ hổng lớn ở đây. Bạn sẽ thấy rằng khi bộ điều khiển này được đẩy vào với hoạt ảnh, chiều cao của thanh điều hướng cũng sẽ cao hơn với hoạt ảnh, dẫn đến thừa không cần thiết. hình ảnh động và một trải nghiệm khủng khiếp.
Vậy nó nên được đặt ở đâu? Chúng ta cần xem xét trình tự gọi trình điều khiển khung nhìn mới.
Sau đây là thời gian gọi từ đầu ra bảng điều khiển đẩy "rootvc" đến "pushvc" và các vùng an toàn của chế độ xem của bộ điều khiển tương ứng.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
2017-10-04 16:59:59.594811+0800 xxx[15662:803767] bắt đầu pushviewcontroller tới [<_ttcc8xxxtests27containerviewcontrollertest20mockuiviewcontroller: 0x7f9c07b643b0>]
viewdidload()---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 0.0, bên trái: 0.0, bên dưới: 0.0, bên phải: 0.0)
sẽ di chuyển(đến parentviewcontroller:)---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 0.0, bên trái: 0.0, bên dưới: 0.0, bên phải: 0.0)
viewwilldisappear---tùy chọn(
"rootvc"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
viewwillappear---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 0.0, bên trái: 0.0, bên dưới: 0.0, bên phải: 0.0)
viewsafeareainsetsdidchange()---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
viewwilllayoutsubviews()---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
viewdidlayoutsubviews()---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
viewwilllayoutsubviews()---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
viewdidlayoutsubviews()---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
viewdidappear---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
viewdiddisappear---tùy chọn(
"rootvc"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
didmove(toparentviewcontroller:)---tùy chọn(
"đẩy"
)---uiedgeinsets(trên cùng: 44.0, bên trái: 0.0, bên dưới: 34.0, bên phải: 0.0)
2017-10-04 16:59:59.604563+0800 xxx[15662:803767] đã đẩy viewcontroller [<_ttcc8xxxtests27containerviewcontrollertest20mockuiviewcontroller: 0x7f9c0790d170>]->[<_ttcc8xxxtests27containerviewcontrollertest20mockuiviewcontroller: 0x7f9c07b643b0>]
thời gian
= [0,009772]
|
Có thể thấy viewsafeareainsdidchange được gọi từ rất sớm, sau viewwillappear, đó là lý do vì sao animation dư thừa xuất hiện. Và các tập hợp vùng an toàn của "pushvc" là uiedgeinsetszero cho đến khi viewsafeareainsetsdidchange được gọi và sau đó chúng là các tập hợp uiedgeinsets chính xác (trên cùng: 44.0, bên trái: 0.0, dưới cùng: 34.0, bên phải: 0.0).
Và viewdidlayoutsubviews sẽ được gọi 2 lần sau viewsafeareainsetsdidchange nên chúng ta nên viết code thay đổi chiều cao hoặc bố cục trong viewdidlayoutsubviews để không có hiệu ứng animation thừa. Cần lưu ý rằng viewdidlayoutsubviews có thể được kích hoạt thường xuyên bởi các thao tác khác, vì vậy nếu mã điều chỉnh bố cục vùng an toàn tốn nhiều thời gian, bạn có thể cân nhắc thêm dấu trạng thái và chỉ thực hiện điều chỉnh bố cục một lần sau khi didchange.
Mã cuối cùng sẽ trông như thế này.
?
1
2
3
4
5
6
7
8
|
- (
vô hiệu
)viewdidlayoutsubviews {
[siêu xemđãbố cụccác chế độ xem phụ];
uiedgeinsets safeareainsets = sgm_safeareainset(self.view);
chiều cao cgfloat = 44.0;
chiều cao += safeareainsets.top > 0 ? safeareainsets.top : 20.0;
nếu như
(_navigationbar && _navigationbar.height != chiều cao) {
_navigationbar.height = chiều cao;
}
|
Hiệu ứng trước và sau khi thích ứng.

trước khi thích ứng.

Sau khi thích ứng.
Bằng cách này, có một giải pháp thích ứng động cho các tình huống bố cục khung và bố cục tự động bố trí khác nhau, đó là sử dụng các bộ hướng dẫn an toàn và vùng an toàn tương ứng để xử lý bố cục một cách linh hoạt. So với việc ghi một khoảng cách cố định, các mô hình hiện tại và tương lai khác nhau có thể Một bộ. thích ứng mã, khả năng mở rộng tốt hơn. Dự án của chúng tôi hiện đang áp dụng phương pháp này. Nếu dự án của bạn cần thích ứng với màn hình ngang và dọc hoặc bố cục điều khiển giao diện người dùng tương đối phức tạp, bạn thực sự nên cân nhắc sử dụng vùng an toàn.
Nhân tiện, vfl dường như đã lỗi thời, vì | chỉ có thể biểu thị cạnh của chế độ xem gốc và không có biểu tượng nào biểu thị cạnh của safearealayoutguide của chế độ xem gốc. Rất nhiều mã vfl mà chúng tôi đã viết trước đây cần phải làm. có thể bị thay đổi và việc thay đổi nó sẽ rất rắc rối. Tôi khuyên bạn nên ngừng sử dụng vfl.
Vấn đề cuối cùng với phán đoán phiên bản là safeareainsets và safearealayoutguide là các API của iOS 11. Nếu chúng được viết trực tiếp trong mã mà không đóng gói, chắc chắn sẽ có một số lượng lớn các câu lệnh @available phiên bản có ở khắp mọi nơi trong mã. trông rất hỏng, phá hủy khả năng đọc mã.
Bởi vì trước đây tôi đã viết một khung bố cục tự động nên lần này tôi đã gói gọn safearealayoutguide và phán đoán phiên bản trong đó. Cá nhân tôi nghĩ rằng khung này dễ sử dụng hơn nslayoutanchor. Chức năng chính của nó là đơn giản hóa việc viết mã bố cục. tạo ra một ràng buộc nslayout.
?
1
2
3
4
5
6
7
8
9
10
|
nếu như
(@available(ios 11.0, *)) {
[nslayoutconstraint ràng buộc với mục:self.topleftview thuộc tính:nslayoutattributetop liên quan theo:nslayoutrelationequal với mục:self.view.safearealayoutguide thuộc tính:nslayoutattributetop hệ số nhân:1.0 hằng số:0];
}
khác
{
[nslayoutconstraint ràng buộc với mục:self.topleftview thuộc tính:nslayoutattributetop liên quan theo:nslayoutrelationequal với mục:self.view thuộc tính:nslayoutattributetop hệ số nhân:1.0 hằng số:0];
}
self.topleftview.top_attr = self.view.top_attr_safe
|
Sẽ không có bất kỳ phán xét phiên bản nào trong mã doanh nghiệp. Nếu quan tâm, bạn có thể dùng thử.
Trên đây là toàn bộ nội dung bài viết này hi vọng nó sẽ giúp ích cho việc học của mọi người và cũng mong mọi người ủng hộ mình.
Link gốc: https://www.jianshu.com/p/1432a94ef66f.
Cuối cùng, bài viết này về phần giải thích chi tiết về việc thích ứng iOS 11 safeArea và iphoneX kết thúc ở đây. Nếu bạn muốn biết thêm về phần giải thích chi tiết về việc thích ứng iOS 11 safeArea và iphoneX, vui lòng tìm kiếm bài viết CFSDN hoặc tiếp tục duyệt qua các bài viết liên quan. tất cả các bạn hãy ủng hộ blog của tôi trong tương lai! .
Tôi là một lập trình viên xuất sắc, rất giỏi!