Thanh trạng thái và thanh điều hướng xuất hiện trên giới hạn chế độ xem của tôi trong iOS 7


435

Gần đây tôi đã tải xuống Xcode 5 DP để kiểm tra các ứng dụng của mình trong iOS 7. Điều đầu tiên tôi nhận thấy và xác nhận là giới hạn của chế độ xem của tôi không phải lúc nào cũng được thay đổi kích thước để tính đến thanh trạng thái và thanh điều hướng.

Trong viewDidLayoutSubviews, tôi in giới hạn của khung nhìn:

{{0, 0}, {320, 568}}

Điều này dẫn đến nội dung của tôi xuất hiện bên dưới thanh điều hướng và thanh trạng thái.

Tôi biết tôi có thể tự tính toán chiều cao bằng cách lấy chiều cao của màn hình chính, trừ đi chiều cao của thanh trạng thái và chiều cao của thanh điều hướng, nhưng dường như đó là công việc phụ không cần thiết.

Làm thế nào tôi có thể khắc phục vấn đề này?

Cập nhật:

Tôi đã tìm thấy một giải pháp cho vấn đề cụ thể này. Đặt thuộc tính mờ của thanh điều hướng thành NO:

self.navigationController.navigationBar.translucent = NO;

Điều này sẽ sửa chế độ xem khỏi bị đóng khung bên dưới thanh điều hướng và thanh trạng thái.

Tuy nhiên, tôi chưa tìm thấy bản sửa lỗi cho trường hợp khi bạn muốn thanh điều hướng trong mờ. Ví dụ, xem ảnh toàn màn hình, tôi muốn có thanh điều hướng mờ và chế độ xem được đóng khung bên dưới nó. Điều đó hoạt động, nhưng khi tôi chuyển đổi hiển thị / ẩn thanh điều hướng, tôi đã trải nghiệm kết quả thậm chí xa lạ. Subview đầu tiên (một UIScrollView) có giới hạn y gốc của nó thay đổi mỗi lần.


Tôi cũng đang gặp vấn đề tương tự trong xcode 5 DP
Gopesh Gupta

Hãy cho tôi biết nếu bạn sẽ nhận được một số giải pháp
Gopesh Gupta

1
Nhìn vào thanh điều hướng cho một thuộc tính màu sắc, bạn sẽ có thể thay đổi màu xanh đó thành bất cứ điều gì bạn muốn.
beebcon

9
Tôi ghét việc nâng cấp ios đôi khi vì Apple không bao giờ cho bạn cơ hội để giữ cho ứng dụng của bạn tương thích ngược.
Bagusflyer

3
Nếu sự cố liên quan đến chế độ xem nằm dưới thanh trạng thái sau khi ẩn thanh trên cùng của bộ điều khiển điều hướng, tôi sẽ tham khảo câu trả lời của @Stunner stackoverflow.com/a/18976660/235206 làm giải pháp
MiKL

Câu trả lời:


495

Bạn có thể đạt được điều này bằng cách triển khai một thuộc tính mới có tên edgesForExtendedLayouttrong SDK iOS7. Vui lòng thêm mã sau đây để đạt được điều này,

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

Bạn cần thêm ở trên trong -(void)viewDidLoadphương pháp của bạn .

iOS 7 mang đến một số thay đổi về cách bạn bố trí và tùy chỉnh giao diện của UI . Những thay đổi trong bố cục của trình điều khiển chế độ xem, màu sắc và phông chữ ảnh hưởng đến tất cả các đối tượng UIKit trong ứng dụng của bạn. Ngoài ra, các cải tiến đối với API nhận dạng cử chỉ cho phép bạn kiểm soát chi tiết hơn đối với các tương tác cử chỉ.

Sử dụng bộ điều khiển xem

Trong iOS 7, bộ điều khiển xem sử dụng bố cục toàn màn hình. Đồng thời, iOS 7 cung cấp cho bạn quyền kiểm soát chi tiết hơn đối với cách trình điều khiển chế độ xem đưa ra các chế độ xem. Cụ thể, khái niệm bố cục toàn màn hình đã được tinh chỉnh để cho phép bộ điều khiển chế độ xem chỉ định bố cục của từng cạnh của chế độ xem.

Các wantsFullScreenLayoutthuộc tính view controller bị phản đối trong iOS 7. Nếu bạn đang xác định wantsFullScreenLayout = NO, bộ điều khiển xem có thể hiển thị nội dung của nó ở một vị trí màn hình bất ngờ khi nó chạy trong iOS 7.

Để điều chỉnh cách trình điều khiển khung nhìn hiển thị các khung nhìn của nó, UIViewController cung cấp các thuộc tính sau:

  • edgeForExtendsLayout

Các edgesForExtendedLayoutbất động sản sử dụng các UIRectEdgeloại, trong đó quy định cụ thể mỗi người trong số bốn cạnh của một hình chữ nhật, ngoài việc xác định không và tất cả. Sử dụng edgesForExtendedLayoutđể chỉ định các cạnh của chế độ xem nên được mở rộng, bất kể độ mờ của thanh. Theo mặc định, giá trị của tài sản này là UIRectEdgeAll.

  • ExtendedLayoutIncludesOpaqueBars

Nếu thiết kế của bạn sử dụng các thanh mờ, hãy tinh chỉnh edgesForExtendedLayoutbằng cách đặt thuộc extendedLayoutIncludesOpaqueBarstính thành NO . (Giá trị mặc định extendedLayoutIncludesOpaqueBarsNO .)

  • tự độngAdjustScrollViewInsets

Nếu bạn không muốn các bộ chèn nội dung của chế độ xem cuộn được tự động điều chỉnh, hãy đặt automaticallyAdjustsScrollViewInsetsthành KHÔNG . (Giá trị mặc định automaticallyAdjustsScrollViewInsets .)

  • topLayoutGuide, bottomLayoutGuide

Các thuộc tính topLayoutGuidebottomLayoutGuidechỉ ra vị trí của các cạnh của thanh trên cùng hoặc dưới cùng trong chế độ xem của bộ điều khiển xem. Nếu các thanh phải chồng lên trên cùng hoặc dưới cùng của chế độ xem, bạn có thể sử dụng Trình tạo giao diện để định vị chế độ xem so với thanh bằng cách tạo các ràng buộc ở dưới cùng topLayoutGuidehoặc trên đỉnh của bottomLayoutGuide. (Nếu không có thanh nào chồng lên chế độ xem, phần dưới cùng của topLayoutGuide cùng giống với phần trên của chế độ xem và phần trên bottomLayoutGuidecùng giống với phần dưới của chế độ xem.) Cả hai thuộc tính được tạo một cách lười biếng khi được yêu cầu.

Vui lòng tham khảo, táo doc


2
Nó sẽ không biên dịch dưới iOS6. Tôi nghĩ nó nên được viết dưới dạng trình diễn ...
Shmidt

8
Có, đó là lý do tại sao tôi đã bao gồm kiểm tra bộ chọn với điều kiện if, nếu ([tự trả lờiToSelector: @selector (edgeForExtendsLayout)])
Nandha

19
Điều này sẽ không hoạt động nếu tôi không có thanh điều hướng. Trong trường hợp đó, quan điểm của tôi được mở rộng phía sau thanh trạng thái ..
Van Du Tran

4
Tôi có cùng một vấn đề như @VanDuTran. edgeForExtendsLayout không giúp ích gì nếu thanh điều hướng bị ẩn.

6
nó hoạt động nhưng ... không còn hiệu ứng mờ nữa ... làm thế nào chúng ta có thể duy trì hiệu ứng mờ cũng ...
Dipu Rajak

110

Bạn không cần phải tính toán bao xa để thay đổi mọi thứ, có một tài sản cho việc này. Trong Trình tạo giao diện, tô sáng trình điều khiển chế độ xem của bạn, rồi điều hướng đến trình kiểm tra thuộc tính. Ở đây bạn sẽ thấy một số hộp kiểm bên cạnh dòng chữ "Mở rộng các cạnh". Như bạn có thể thấy, trong ảnh chụp màn hình đầu tiên, lựa chọn mặc định là cho nội dung xuất hiện dưới các thanh trên cùng và dưới cùng, nhưng không phải dưới các thanh mờ, đó là lý do tại sao cài đặt kiểu thanh thành không mờ cho bạn.

Như bạn có thể thấy phần nào trong ảnh chụp màn hình đầu tiên, có hai thành phần UI ẩn bên dưới thanh điều hướng. (Tôi đã kích hoạt khung lưới trong IB để minh họa điều này) Các yếu tố này, UIButton và UISegmentedControl đều có gốc "y" được đặt thành 0 và bộ điều khiển chế độ xem được đặt để cho phép nội dung bên dưới thanh trên cùng.

nhập mô tả hình ảnh ở đây

Ảnh chụp màn hình thứ hai này cho thấy những gì xảy ra khi bạn bỏ chọn hộp kiểm "Dưới thanh trên cùng". Như bạn có thể thấy, khung nhìn của bộ điều khiển khung nhìn đã được chuyển xuống một cách thích hợp để gốc y của nó nằm ngay bên dưới thanh điều hướng.

nhập mô tả hình ảnh ở đây

Điều này cũng có thể được thực hiện theo chương trình thông qua việc sử dụng -[UIViewController edgesForExtendedLayout]. Đây là một liên kết đến tham chiếu lớp cho edgeForExtendsLayout và cho UIRectEdge

[self setEdgesForExtendedLayout:UIRectEdgeNone];

15
Làm thế nào để tôi làm tương tự cho chỉ xem trong .xib?
bobics

2
Tôi đã thêm một nhãn vào chế độ xem và tôi đã làm theo hướng dẫn của bạn nhưng điều này không hiệu quả với tôi
RMRAHUL

5
@bobics Câu trả lời cho câu hỏi XIB là "Bạn không thể." Không thông qua IB nào. Nộp một radar và hy vọng Apple cuối cùng sẽ giải quyết nó.
memmons

Cảm ơn @ 0x7fffffff, Đây chỉ là thông tin tôi đang tìm kiếm và rất hữu ích.
campo

33

Tôi đã tạo ra quan điểm của mình theo lập trình và điều này đã kết thúc với tôi:

- (void) viewDidLayoutSubviews {
    // only works for iOS 7+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;

        // snaps the view under the status bar (iOS 6 style)
        viewBounds.origin.y = topBarOffset * -1;

        // shrink the bounds of your view to compensate for the offset
        viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
        self.view.bounds = viewBounds;
    }
}

Nguồn (trong phần topLayoutGuide ở cuối trang 39).


Cuối cùng tìm thấy một câu trả lời thực sự hoạt động cho việc này. Làm tốt lắm!
StuartM

1
Để giải quyết vấn đề theo đó chế độ xem của trình điều khiển chế độ xem hiển thị dưới thanh trạng thái khi thanh điều hướng bị ẩn, đây là mã sẽ chặn chế độ xem dưới thanh trạng thái.
MiKL

Lưu ý: điều này sẽ đẩy phần dưới của màn hình của bạn ra khỏi màn hình.
memmons

1
Ngoài ra, trừ khi bạn đang xây dựng chỉ cho iOS7, đoạn mã trên sẽ gây ra lỗi -topLayoutGuide là iOS7.
memmons

1
Cũng lưu ý rằng khi chế độ xem chính của bạn là UITableView, viewDidLayoutSubview sẽ được gọi trên mỗi cuộn. UITableView của bạn sẽ được thu nhỏ lại cho đến khi chiều cao của nó là 15px. Thêm một cờ để chỉ chạy mã này một lần. ;)
Thomas Johannesmeyer

30

Giải pháp Swift 3 / Swift 4 cũng hoạt động với các tệp NIB / XIB trong iOS 10+:

override func viewDidLoad() {
    super.viewDidLoad()

    edgesForExtendedLayout = []
}

Đây là những gì đã giúp tôi ... Thật đơn giản. Cảm ơn :-)
Hernan Arber

Cảm ơn bạn, nó thực sự hữu ích
Muhammad Ahmed Baig

Đây là giải pháp tốt nhất cho 10.x Swift 3+ IMO
shokaveli

10

Nếu bạn muốn chế độ xem có thanh điều hướng mờ (loại này đẹp), bạn phải thiết lập một ContentInset hoặc tương tự.

Đây là cách tôi làm điều đó:

// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) {
      CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
      float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;

      myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);
}

3
tại sao bạn không thể so sánh trực tiếp với 7.0
Leena

1
lol tôi hiểu rồi: kiểm tra đối với một phiên bản cụ thể có thêm phụ là kém mạnh mẽ. Nhưng bạn đang kiểm tra xem giá trị đó là LỚN hay bằng so với so với 7.0 sẽ chỉ tốt ở đây;)
EeKay

1
@leena - Đây là tính năng trong 7.x trở lên - vì vậy tôi kiểm tra xem phiên bản có phải là 7 hoặc cao hơn không và bỏ qua các sửa đổi nhỏ trong kiểm tra.
Magnus

2
Tôi có một vấn đề với bảng ong của tôi Hiển thị phía sau Tabbar của tôi. Điều này làm cho hàng cuối cùng của bảng của tôi không bao giờ cuộn lên trên Tabbar. Tôi đã sửa nó như thế: myTableView.contentInset = UIEdgeInsetsMake (0, 0.0, TabbarHeight, 0)
James Laurenstin

contentInsetlà một tài sản của UIScrollView. Điều gì xảy ra nếu quan điểm chính của tôi không phải là một lớp con của UIScrollView. Sau đó, làm thế nào tôi sẽ khắc phục vấn đề chồng chéo?
Pwner

9

edgesForExtendedLayoutthực hiện thủ thuật cho iOS 7. Tuy nhiên, nếu bạn xây dựng ứng dụng trên SDK iOS 7 và triển khai nó trong iOS 6, thanh điều hướng sẽ xuất hiện mờ và các chế độ xem nằm bên dưới nó. Vì vậy, để khắc phục nó cho cả iOS 7 cũng như iOS 6, hãy làm điều này:

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific

9

Trong tệp ứng dụng của bạn, hãy thêm một hàng, gọi nó là "Xem sự xuất hiện của thanh trạng thái dựa trên bộ điều khiển" và đặt thành KHÔNG .


7

Thủ thuật đơn giản nhất là mở tệp NIB và thực hiện hai bước đơn giản sau:

  1. Chỉ cần chuyển nó và đặt nó thành cái bạn thích:

Nhập mô tả hình ảnh ở đây

  1. Chọn những / UIMiew's / UIIMageView's / ... mà bạn muốn được chuyển xuống. Trong trường hợp của tôi, chỉ có logo bị chồng chéo và tôi đã đặt delta là +15; (HOẶC -15 nếu bạn chọn iOS 7 ở bước 1)

Nhập mô tả hình ảnh ở đây

kết quả :

Trước Sau


6
Nó hoạt động, nhưng điều này trông giống như một giải pháp khó để duy trì. Tốt nhất chỉ nên khắc phục sự cố thay vì vá nó.
NLemay

tốt nhất nên thực hiện theo chương trình cho tất cả các cuộc phỏng vấn của người xem vì nó không hoạt động nếu được áp dụng cho chế độ xem chính
wildmonkey

5

Giải pháp nhanh chóng:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None
}

4
Bây giờ là edgeForExtendsLayout = []
Leon

1
Vì đây là câu trả lời công khai, chúng tôi không nên quên gọi:super.viewWillAppear(animated)
prodos

4

Tôi muốn mở rộng câu trả lời của Stunner và thêm một if tuyên bố để kiểm tra xem đó có phải là iOS-7 không, vì khi tôi thử nghiệm nó trên iOS 6, ứng dụng của tôi sẽ bị sập.

Việc bổ sung sẽ được thêm vào:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

Vì vậy, tôi sẽ đề nghị thêm phương pháp này vào MyViewControler.mtập tin của bạn :

- (void) viewDidLayoutSubviews {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;
        viewBounds.origin.y = topBarOffset * -1;
        self.view.bounds = viewBounds;
    }
}

4

Swift 3

override func viewWillAppear(_ animated: Bool) {
    self.edgesForExtendedLayout = []
}

3

Tôi có một kịch bản trong đó tôi sử dụng BannerViewControll do Apple viết để hiển thị quảng cáo của mình và ScrollViewControll được nhúng trong BannerViewControll.

Để ngăn thanh điều hướng ẩn nội dung của tôi, tôi phải thực hiện hai thay đổi.

1) Sửa đổi BannerViewControll.m

- (void)viewDidLoad
{
   [super viewDidLoad];
   float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
   if (systemVersion >= 7.0) {
      self.edgesForExtendedLayout = UIRectEdgeNone;
   }
}

2) Sửa đổi ScrollViewContoller của tôi

- (void)viewDidLoad
{
    [super viewDidLoad];
    float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (systemVersion >= 7.0) {
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

Bây giờ quảng cáo hiển thị chính xác ở cuối chế độ xem thay vì được bao phủ bởi thanh Điều hướng và nội dung ở trên cùng không bị cắt bỏ.


2

chỉ cần đặt mã sau đây trong chế độ xem sẽ xuất hiện.

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
 }

Đây là điều duy nhất làm việc trong hoàn cảnh của tôi.
goobliata


2

Swift 4.2 - Xcode 10.0 - iOS 12.0:

if #available(iOS 11.0, *) {} else {
  self.edgesForExtendedLayout = []
  self.navigationController?.view.backgroundColor = .white
}

1

Đối với tôi, giải pháp đơn giản nhất là thêm hai khóa vào bảng

nhập mô tả hình ảnh ở đây


+1, tôi đã có "Thanh trạng thái ban đầu bị ẩn" = CÓ, nhưng khi thêm "Xem giao diện thanh trạng thái dựa trên bộ điều khiển" = KHÔNG Tôi đã thoát khỏi thanh trạng thái.
Jonas Byström

1

Thêm khóa "Xem giao diện thanh trạng thái dựa trên Bộ điều khiển" từ danh sách thả xuống dưới dạng một hàng info.plist. Một cái gì đó như thế này:

Nhập mô tả hình ảnh ở đây


Thú vị
Kursat Turkay

1

Tôi đã gặp vấn đề tương tự với ứng dụng của mình bởi iPad (armv7, armv7s, amr64) chỉ bằng cách trình bày một UIViewContoder khác và sau khi loại bỏ chúng đi vào thanh điều hướng dưới thanh trạng thái ... Tôi dành nhiều thời gian để tìm bất kỳ giải pháp nào cho điều đó. Tôi đang sử dụng bảng phân cảnh và trong InterfaceBuilder cho UIViewControll, điều này khiến tôi đặt bản trình bày từ FullScreen -> Bối cảnh hiện tại và nó khắc phục vấn đề này. Nó chỉ hoạt động trong ứng dụng của tôi cho iPad => iOS8.0 (thử nghiệm với iOS8.1) và cho iPad với iOS 7.1 không hoạt động !!xem ảnh chụp màn hình


Trong trường hợp của tôi, chế độ xem chính của tôi đã chồng chéo tabBar của tôi và tôi không biết tại sao. Nó chỉ ra các mở rộng Edges> Under bottom Bars đã được kiểm tra. Thật sự rất khó để nhận ra điều đó bởi vì nền của ứng dụng của tôi màu trắng và nó chỉ tạo ra độ mờ ở mức độ trên tabBar của tôi. Cảm ơn!
Jesus Rodriguez

0

Các bước để ẩn thanh trạng thái trong iOS 7:

1.Đi tới tập tin thông tin ứng dụng của bạn.

2.And Set, Xem giao diện thanh trạng thái dựa trên bộ điều khiển: Boolean NO

Hy vọng tôi đã giải quyết vấn đề thanh trạng thái .....


0

Trong trường hợp của tôi có loadView () bị gián đoạn
mã này: self.edgesForExtendsLayout = UIRectEdgeNone

nhưng sau khi xóa loadView () mọi thứ đều hoạt động tốt

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.