Как заблокировать строку состояния от перекрытия содержимого с помощью hidesBarsOnSwipe, установленного в UINavigationController?
Я пытаюсь использовать новую функцию, добавленную в iOS 8, - скрывая панель навигации, когда пользователь прокручивает представление таблицы (похоже на то, что делает мобильный Safari). Я устанавливаю свойство hidesBarsOnSwipe
от UINavigationController
до YES
в viewDidAppear
методе UITableViewController
:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if([self.navigationController respondsToSelector:@selector(hidesBarsOnSwipe)]) {
self.navigationController.hidesBarsOnSwipe = YES;
}
}
Панель навигации скрывается при прокрутке представления. Все идет нормально. Но строка состояния все еще видна, и содержимое моего представления таблицы отображается через нее, что выглядит уродливо:
![enter image description here]()
Я попытался установить edgesForExtendedLayout
на UIEdgeRectNone
или настроить contentInset
в представлении таблицы, но это не помогло. Есть ли какое-либо другое решение, чтобы скрыть строку состояния вместе с навигационной панелью или сделать ее непрозрачной?
Ответы
Ответ 1
Построение ответа anas, у меня есть рабочее решение (я предполагаю, что tableViewController
является вашим экземпляром UITableViewController
):
В подклассе UINavigationController
(или также потенциально от tableViewController
):
- (void)viewDidLoad {
if ([self respondsToSelector:@selector(barHideOnSwipeGestureRecognizer)]) {
// iOS 8+
self.hidesBarsOnSwipe = YES;
[self.barHideOnSwipeGestureRecognizer addTarget:self action:@selector(swipe:)];
}
}
- (void)swipe:(UISwipeGestureRecognizer *)recognizer {
BOOL shouldHideStatusBar = self.navigationController.navigationBar.frame.origin.y < 0;
tableViewController.hideStatusBar = shouldHideStatusBar;
[UIView animateWithDuration:0.2 animations:^{
[tableViewController setNeedsStatusBarAppearanceUpdate];
}];
}
В tableViewController
:
@property(nonatomic, getter = shouldHideStatusBar) BOOL hideStatusBar;
- (BOOL)prefersStatusBarHidden {
return [self shouldHideStatusBar];
}
Сообщите мне, если это не сработает для вас. Несколько неочевидных вещей:
-
self.navigationController.navigationBar.frame.origin.y
был скрыт и был равен -44 (отрицательная высота панели навигации) и 20 (высота строки состояния) при видимости. Не было промежуточного, даже во время анимации, поэтому отрицательное value == скрыто и неотрицательное value == видно.
- Контроллер дочернего представления запрашивается, должна ли быть скрыта строка состояния. В моем случае у меня есть
UIViewController
внутри UINavigationController
в пределах UITabBarController
, и он не работал, пока я не перевернул prefersStatusBarHidden
на UIViewController
.
- Так как скрытая строка состояния не имеет фрейма, ваш контент может поднять вверх 20 пунктов, если вы не завершите вызов
setNeedsStatusBarAppearanceUpdate
в блоке анимации.
- Надеюсь, синтаксис верен; Я передал это из моего кода Swift.
Ответ 2
На самом деле это довольно легко сделать. Вам просто нужно подключить навигацию isNavigationBarHidden со статусом.
Objective-C
- (BOOL)prefersStatusBarHidden {
return self.navigationController.isNavigationBarHidden;
}
Swift <= 2.3
override func prefersStatusBarHidden() -> Bool {
return navigationController?.navigationBarHidden ?? false
}
Swift 3.0
override var prefersStatusBarHidden: Bool {
return navigationController?.isNavigationBarHidden ?? false
}
И убедитесь, что у вас есть "Просмотр строки состояния на основе контроллера" = "ДА" в файле .plist вашего приложения.
Ответ 3
Это новое свойство поставляется с barHideOnSwipeGestureRecognizer
.
Из Ссылка на класс UINavigationController:
Вы можете внести изменения в распознаватель жестов по мере необходимости, но не должны измените его делегат, и вы не должны удалить целевой объект по умолчанию и действия, которые выполняются с ним. Не пытайтесь заменить это распознавателя жестов путем переопределения свойства.
Но вы можете добавить цель:
[self.navigationController setHidesBarsOnSwipe:YES];
[self.navigationController.barHideOnSwipeGestureRecognizer addTarget:self action:@selector(swipeGesture:)];
... и делать все, что вы хотите в обратном вызове:
- (void)swipeGesture:(UIPanGestureRecognizer*)gesture
{
// Tweak the status bar
}
Возможно, вам придется вручную включить состояния жестов, выяснить, когда скрыть/показать строку состояния и т.д. Надеюсь, что это поможет!
Ответ 4
Ответ от @iOSergey работает отлично!
Вот решение в Swift 1.2. Добавьте следующий код в файл .swift:
override func prefersStatusBarHidden() -> Bool {
return self.navigationController!.navigationBarHidden as Bool
}
Ответ 5
Если вы хотите скрыть строку состояния с анимацией:
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
return .Slide
}
override func prefersStatusBarHidden() -> Bool {
return navigationController?.navigationBarHidden ?? false
}
Ответ 6
После большой борьбы я наконец смог решить эту проблему.
- Изменить TableViewController на UIViewController
- Перетащите TableView в UIViewController и выровняйте его прямо под панелью навигации в main.storyboard.
- Добавьте отсутствующие ограничения.
- нажмите на таблицу и проверьте ограничения
- установить нижнее пространство для: супервизора до 0
- установите для трейдера свободное пространство для просмотра до 0
- установить ведущее пространство для просмотра до 0
- установите "Выровнять по верху вверху: Руководство по макету сверху. Топ к 0 (очень важно)
Добавьте в код UIViewController viewDidLoad следующий код:
//Создаем сплошной цвет фона для строки состояния (в Swift Code)
let statusFrame = CGRectMake (0.0, 0, self.view.bounds.size.width,
UIApplication.sharedApplication(). StatusBarFrame.size.height)
var statusBar = UIView (frame: statusFrame)
statusBar.backgroundColor = UIColor.whiteColor()
self.view.addSubview(STATUSBAR)
Что вы делаете, это создать сплошную панель прямо под панелью навигации. Когда панель навигации перемещается вверх, сплошная панель перемещается вверх и вниз позади строки состояния.
Единственная проблема заключается в том, что когда вы поворачиваете боковые стороны экрана, белая полоса остается там, даже если строка состояния исчезает.
Ответ 7
Хорошо, я весь день делал это, надеюсь, это помогает некоторым людям. Там a barHideOnSwipeGestureRecognizer
. Таким образом, вы можете создать прослушиватель для соответствующего UIPanGesture
, отметив, что если панель навигации скрыта, то ее начало y - -44.0; в противном случае это 0 (не 20, потому что мы спрятали строку состояния!).
В вашем представлении контроллер (swift 2):
// Declare at beginning
var curFramePosition: Double!
var showStatusBar: Bool = true
self.navigationController?.barHideOnSwipeGestureRecognizer.addTarget(self, action: "didSwipe:")
...
override func viewDidLoad(){
self.navigationController?.hidesBarsOnSwipe = true
curFramePosition = 0.0 // Not hidden
self.navigationController?.barHideOnSwipeGestureRecognizer.addTarget(self, action: "didSwipe:")
...
}
func didSwipe(swipe: UIPanGestureRecognizer){
// Visible to hidden
if curFramePosition == 0 && self.navigationController?.navigationBar.frame.origin.y == -44 {
curFramePosition = -44
showStatusBar = false
prefersStatusBarHidden()
setNeedsStatusBarAppearanceUpdate()
}
// Hidden to visible
else if curFramePosition == -44 && self.navigationController?.navigationBar.frame.origin.y == 0 {
curFramePosition = 0
showStatusBar = true
prefersStatusBarHidden()
setNeedsStatusBarAppearanceUpdate()
}
}
override func prefersStatusBarHidden() -> Bool {
if showStatusBar{
return false
}
return true
}
Ответ 8
Еще один способ сделать это - просто добавить еще один вид (над табличным или коллекционным просмотром или веб-просмотром или прокруткой или любым другим) и установить ограничение сверху на "Superview.Top" и его нижнее ограничение на "Top Layout Guide.Bottom", установите цвет фона представления
и это, вы можете даже сделать все это в Interface Builder без какого-либо кода.
И если вы хотите отреагировать на это событие, вы можете добавить наблюдателя ключевых путей к изменению границ представления или подклассировать представление и переопределить его ограничитель...
Ответ 9
Вам нужно подключить навигацию isNavigationBarHidden со статусом.
return self.navigationController.isNavigationBarHidden;