it-swarm.com.ru

строка состояния iOS 7 сталкивается с панелью навигации

В моем приложении есть контроллер представления, на котором в раскадровке перетащена панель навигации. В iOS 6 все работало нормально, но в iOS 7 это выглядит так:

ios 7 status bar nav var

Строка состояния и панель навигации не должны сталкиваться друг с другом. Я видел много таких вопросов о переполнении стека, но они мне не сильно помогли.

Некоторые вопросы говорят, что я должен использовать это "self.edgesForExtendedLayout = UIRectEdgeNone;" но это не сработало. Некоторые говорят, что я должен удалить панель навигации и встроить ее в контроллер навигации, чего я не могу сделать из-за того, как реализована моя программа. Некоторые решения предлагают использовать границы представления и все, но это не сработало и для меня.

Что может помочь мне решить эту проблему? Заранее спасибо!

ОБНОВЛЕНИЕ: Я встроил контроллер вида внутри контроллера навигации. Убрана панель навигации, которая ранее была добавлена ​​в нее вручную. Теперь он выглядит нормально в раскадровке, но когда я запускаю его, он показывает следующее:

iOS 7 Navigation Status bar

Он показывает текст из другого контроллера представления, который в настоящее время находится позади него, который является его родительским контроллером представления. Значит его прозрачный сейчас. Кто-нибудь может указать, что я делаю не так? 

46
AJ112

Последняя версия iOS принесла много визуальных изменений, и с точки зрения разработчика навигация и строка состояния - это два заметных изменения. 

Строка состояния теперь прозрачна, а панель навигации за ней просвечивает. Изображение панели навигации может быть даже расширено за строкой состояния. 

Прежде всего, если вы новичок и только начали разработку iOS и не знаете, как работает строка состояния и панель навигации, вы можете просто просмотреть сообщение в блоге ЗДЕСЬ , которое я считаю очень полезным. В нем есть вся информация, связанная с навигацией и строкой состояния в iOS 7.

Теперь приступим к ответу на ваш вопрос. Прежде всего я вижу две разные проблемы. Во-первых, ваша строка состояния и панель навигации как бы сталкиваются друг с другом, как показано вами в вопросе с изображением. 

ПРОБЛЕМА: Ну, проблема в том, что вы ранее перетаскивали панель навигации в контроллере представления, который работал корректно в iOS 6, но с появлением iOS 7 SDK этот подход приводит к тому, что строка состояния и панель навигации перекрываются с друг с другом. 

Решение первой проблемы: Вы можете использовать UIBarPositionTopAttached или использовать границы и рамки просмотра, я также могу предложить и связать вас с документацией Apple и бла-бла-бла, но это займет некоторое время, чтобы вы решить вопрос. 

Лучший и самый простой способ решить эту проблему - просто встроить свой контроллер представления в контроллер навигации и все. Вы можете сделать это, просто выбрав контроллер представления и перейдя в «Редактор»> «Встроить»> «Контроллер навигации». (Если на старой панели навигации есть какой-либо контент, вы можете сначала перетащить его вниз, встроить контроллер представления в контроллер навигации, а затем переместить кнопки панели на новую панель навигации и затем удалить старую панель навигации)

Решение второй проблемы: Это решение предназначено для вашего конкретного вопроса, который вы упомянули в обновлении, и не предназначено для широкой публики, читающей это. Как видите, панель навигации и состояния не видна, а в прозрачной области показан родительский контроллер представления. Я не совсем понимаю, почему вы столкнулись с этой проблемой, но, скорее всего, из-за какой-либо сторонней библиотеки, например ECSlidingView или любой другой. Вы можете выбрать этот контроллер представления в своей раскадровке и установить цвет фона представления таким же, как на панели навигации. Это перестанет показывать родительский контроллер представления позади, и ваша панель навигации и строка состояния начнут отображаться. Теперь вы можете покрыть остальную часть вашего контроллера представления текстовым представлением или чем-либо еще, что вы используете в нем. 

Надеюсь это поможет!

66
KC.

Панель навигации находится слишком близко к строке состояния, потому что, начиная с iOS 7, строка состояния является скорее наложением на представление контроллера всего представления. Поскольку ваша панель навигации имеет значение (0, 0), строка состояния будет отображаться в верхней части панели навигации. Чтобы решить эту проблему, просто переместите панель навигации вниз (или, как уже говорили другие), создайте ограничение между панелью навигации и topLayoutGuide.

Когда вы сделаете это, вы увидите, что теперь между панелью навигации и верхней частью экрана есть разрыв в 20 пунктов. Это потому, что вы только что переместили панель навигации вниз на 20 пунктов. «Но UINavigationController может сделать это правильно!» Абсолютно, и это делается путем реализации UIBarPositioningDelegate на вашем контроллере представления. Это протокол с одним методом, который должен быть реализован следующим образом:

- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar {
    return UIBarPositionTopAttached;
}

После добавления контроллера представления в качестве делегата для панели навигации вы заметите, что панель навигации по-прежнему сдвинута на 20 пунктов вниз, но ее фон будет расширяться под строкой состояния, как в UINavigationController.

Еще одна вещь, которую вы видите, это то, что панель навигации является полупрозрачной, то есть все, что находится под панелью навигации, будет в некоторой степени видно. Свойство translucent в UINavigationBar по умолчанию установлено на YES в iOS 7. До iOS 7 по умолчанию было NO.

33
Scott Berrevoets

вы можете просто сделать это:

1) добавить ограничение между навигационной панелью и верхним руководством по компоновке (выберите навигационную панель, удерживайте клавишу Ctrl и перейдите к «Нижнему гиду по раскладке», открепите клавишу Ctrl)

Add vertical Contrain

2) выберите вертикальный интервал :

vertical spacing

3) установить константу в 0 :

vertical spacing constant

Результат:

result

ОБНОВЛЕНИЕ

В вашем файле AppDelegate вы можете добавить это:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
{
  // Prevent Navigationbar to cover the view
  UINavigationBar.appearance().translucent = false
}
4
Masterfego

Я предлагаю вам в вашем методе viewDidLoad вы пытаетесь:

self.navigationController.navigationBar.translucent = NO;

(по умолчанию это да сейчас)

https://developer.Apple.com/library/ios/documentation/uikit/reference/UINavigationBar_Class/Reference/UINavigationBar.html#//Apple_ref/occ/instp/UINavigationBar/translucent

3
The dude

Если ваш UIViewController НЕ находится в UINavigationController, и вы используете UIStoryBoard, вы можете установить для «iOS 6/7 Deltas» значение 20 для дельты Y, для каждого подпредставления, которое должно быть смещено от UIStatusBar.

enter image description here

2
Nate Potter

Использование Swift :

Как сказал @Scott Berrevoets в своем ответе, вам нужно реализовать метод positionForBar в протоколе UIBarPositioningDelegate, но так как протокол UINavigationBarDelegate реализует этот протокол:

public protocol UINavigationBarDelegate : UIBarPositioningDelegate {
   ...
}

Вам нужно только установить delegate из UINavigationBar, который вы установили с помощью Storyboard, и реализовать метод, и все готово, вот так:

class ViewController: UIViewController, UINavigationBarDelegate {

   @IBOutlet weak var navigationBar: UINavigationBar!

   override func viewDidLoad() {
       super.viewDidLoad()
       self.navigationBar.delegate = self 
   }

   override func didReceiveMemoryWarning() {
       super.didReceiveMemoryWarning()
       // Dispose of any resources that can be recreated.
   }

   func positionForBar(bar: UIBarPositioning) -> UIBarPosition {
       return UIBarPosition.TopAttached
   }
}

ПРИМЕЧАНИЕ: Стоит отметить, что если вы установите положение оси y на панели навигации, скажем, до 40 сверху, то из этого будет проходить снизу вверх положение, чтобы имитировать поведение UINavigationController вам нужно установить на 20 сверху.

Я надеюсь, что это поможет вам.

2
Victor Sigler

Это работает для меня, я надеюсь, вам тоже повезет :)).
Добавьте ниже код на ваш взгляд.

-(void) viewDidLayoutSubviews
{
    CGRect tmpFram = self.navigationController.navigationBar.frame;
    tmpFram.Origin.y += 20;
    self.navigationController.navigationBar.frame = tmpFram;
}

Это в основном меняет местоположение навигационной панели.

2
Jageen

Если это все еще кому-то помогает, это то, что мне помогло немного переместить панель навигации в ios 7 и выше:

-(void)viewWillLayoutSubviews
{
    float iosVersion = 7.0;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= iosVersion) {
        // iOS 7+
        CGRect viewFrame = self.view.frame;
        viewFrame.Origin.y += 10;
        self.view.frame = viewFrame;
    }
}

На устройстве с ios 6.1 и ниже панель навигации не изменится, как это было раньше.

И вот что я использовал, чтобы сделать содержимое строки состояния светлее:

-(UIStatusBarStyle)preferredStatusBarStyle{
    return UIStatusBarStyleLightContent;
}
2
derekg

Сначала установите для UIViewControllerBasedStatusBarAppearance значение NO в Info.plist . Затем в методе AppDelegate's application:didFinishLaunchingWithOptions: добавьте:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
   [application setStatusBarStyle:UIStatusBarStyleLightContent];
   self.window.clipsToBounds = YES;
   self.window.frame = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height-20);
   self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
 }
 return YES;
2
PJR

Это новая функция с IOS7. Вместо того, чтобы смотреть на 20 пикселей, панель навигации в IOS7 смотрит на 0 пикселей. В качестве решения сдвиньте весь вид вниз до 20 пикселей или вы можете использовать изображение для панели навигации с высотой 64 пикселя.

2
PgmFreek

в более раннем окне iOS начинается после строки состояния, а в iOS 7 окно начинается с 0px, в более ранней версии высота просмотра составляет 460 (iPhone 4s и более ранние версии) и 548 (iPhone 5), но в iOS 7 высота просмотра составляет 480 (iPhone 4s и более ранние версии) и 568 (iPhone 5 и более поздние версии), поэтому вы должны начать компоновку после 20 пикселей или начать просмотр с 20 пикселей.

вы можете написать приведенный ниже код в rootviewcontroller или во всех viewcontroller для set view от 20px

#define IOS7_HEIGHT             64

- (void)viewDidLayoutSubviews {
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending)
    {
        CGRect frame=[self.view frame];
        if (frame.Origin.y!=IOS7_HEIGHT) {

            frame.Origin.y = IOS7_HEIGHT;
            frame.size.height -= IOS7_HEIGHT;
            [self.view setFrame:frame];
            [self.view layoutSubviews];
        }
    }
}

здесь высота 64, потому что 20 для строки состояния и 44 для панели навигации ... попробуйте ниже код, это поможет вам. и ваша проблема будет решена. 

1
Pratik

Для тех, у кого есть проблемы с реализацией решения @Masterfego (которое также является официальным, но у меня были проблемы с Xcode 6.3 и автоматическими ограничениями), вот что я сделал:

У меня есть UIViewController с добавленной панелью навигации. Я выбрал панель навигации и добавил ограничение высоты 64 пикселя. Позже мы увидим предупреждение о том, что навигационная панель будет выше (но это то, что мы делаем). Наконец, вы можете видеть, что строка состояния выглядит красиво и имеет тот же цвет, что и панель навигации. :) 

PS: я не могу размещать изображения еще. 

1
cduguet

В iOS 7 приложение занимает 100% размера экрана. Это не проблема . http://www.doubleencore.com/2013/09/developers-guide-to-the-ios-7-status-bar/

1
Amulya

Вероятно, вы можете создать ограничения, прикрепленные к верхнему руководству по макету, чтобы указать положение панели навигации относительно строки состояния. См. Руководство по переходу с пользовательского интерфейса iOS 7: раздел «Внешний вид и поведение» для получения дополнительной информации об использовании руководств по макету.

0
Greg

это лучший ответ . Но я хотел знать, как использовать Storyboard и перетащил UINavigationBar на него . Когда я реализовал метод делегата и установил возвращаемый результат на UIBarPositionTopAttached, он не работал.

- (void)viewDidLoad{
    self.navigationbar.delegate = self;
}
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar{
    NSLog(@"Got it");
    //
    //    CGRect frame = self.navigaitonBar.frame;
    //
    //    frame = CGRectMake(0, 20, CGRectGetWidth(frame), CGRectGetHeight(frame));
    //    self.navigaitonBar.frame = frame;
    //
    //    NSLog(@"frame %f",frame.Origin.y);
    return UIBarPositionTopAttached;
}
0
rbbtsn0w

Если вы используете Xcode 6 и Swift, вы можете сделать это:

  1. Откройте файл info.plist вашего приложения.
  2. Добавьте логический ключ ViewControllerBasedStatusBarAppearance, если он не существует, и присвойте значение «НЕТ».
  3. Добавьте клавишу «Стиль строки состояния», если она не существует, и выберите для нее значение «Непрозрачный черный стиль».
0
Alexsander

Я столкнулся с проблемой, когда полноэкранный режим ModalViewController открывался из моей MainViewController, позиция NavigationBar менялась, когда пользователь возвращался к MainViewController из ModalViewController.

Проблема, которую я заметил, это то, что высота строки состояния не была включена, когда пользователь вернулся к MainViewController. Пожалуйста, отладьте и проверьте происхождение вашего NavigationBar до и после возвращения к вашему ViewController.

// This method will adjust navigation bar and view content.
    private func adjustNavigationControllerIfNeeded() {

        var frame = self.view.frame
        let navigationBarHeight = self.navigationController!.navigationBar.frame.size.height

        if(frame.Origin.y == navigationBarHeight && !UIApplication.shared.isStatusBarHidden) { 

   // If status bar height is not included but it is showing then we have to adjust 
      our Navigation controller properly

            print("Adjusting navigation controller")
            let statusBarHeight = UIApplication.shared.statusBarFrame.height

            frame.Origin.y += statusBarHeight // Start view below navigation bar
            frame.size.height -= statusBarHeight
            self.view.frame = frame

            self.navigationController!.navigationBar.frame.Origin.y = statusBarHeight // Move navigation bar
        }
    }

И вызвать его из метода viewWillAppear -

override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)
        self.adjustNavigationControllerIfNeeded()
}
0
Rahul