Подтвердить что ты не робот

Как заблокировать строку состояния от перекрытия содержимого с помощью 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 в представлении таблицы, но это не помогло. Есть ли какое-либо другое решение, чтобы скрыть строку состояния вместе с навигационной панелью или сделать ее непрозрачной?

4b9b3361

Ответ 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;