Строка состояния iOS 7 возвращается к стилю iOS 6 по умолчанию в приложении iPhone?


292

В iOS 7 UIStatusBarон был разработан таким образом, что он сливается с таким представлением:

GUI разработан Тиной Тавчар (GUI разработан Тиной Тавчар )

  • Это круто, но это несколько испортит ваш взгляд, когда у вас есть что-то в верхней части вашего обзора, и это будет перекрываться со строкой состояния.

  • Есть ли простое решение (например, установка свойства в info.plist), которое может изменить способ его работы (не перекрывая) обратно на то, как оно работает в iOS6?

  • Я знаю, что более простое решение состоит в том, чтобы иметь self.view.center.x+ 20 баллов для каждого отдельного контроллера представления, но изменение их приведет к изменению других размеров (другое self.view.center.xможет вызвать проблемы для пользовательских сегментов и т. Д.), И внезапно оно превращается в утомительную работу, которая лучше всего избегать

  • Я действительно буду рад, если кто-то может предоставить мне однострочное решение для этого.

PS Я знаю, что могу скрыть строку состояния, выполняя такие вещи, как

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

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


6
К сожалению, черные строки состояния устарели в ios 7
i_duhh_bomb

Я согласен с @GangstaGraham. Эти цвета просто прекрасны ! Чтобы ответить на ваш вопрос, я боюсь, что вы не можете. Причина, по которой строка состояния теперь выглядит так, заключается в том, что прозрачность - это новая вещь для iOS, и она разработана, чтобы придать приложению «глубину», сказав, что оно находится над чем-то, так что под ним что-то есть.
Коул Джонсон

Вы пытались установить предпочитаемый параметр StatusBarStyle в UIStatusBarDefault? Оформить заказ iOS 7 Документация UIViewController
theaob

1
Наличие UIStatusBarDefaultстроки состояния делает ее содержимое только черным. Он не собирается возвращаться к тому, как он работает в iOS6.
吖 奇 说 - 何魏奇 Арчи Будет ли он

2
Удачи с этим? Я люблю iOS7, но эта вещь сводит меня с ума!
Михай Фрату

Ответы:


449

Это перекрестная публикация из сообщения в блоге, которое я написал , но вот полное краткое описание строк состояния, панелей навигации и контроллеров представления контейнера в iOS 7:

  1. Нет способа сохранить макет строки состояния стиля iOS 6. Строка состояния всегда будет перекрывать ваше приложение на iOS 7

  2. Не путайте внешний вид строки состояния с разметкой строки состояния. Внешний вид (светлый или по умолчанию) не влияет на расположение строки состояния (рамка / высота / перекрытие). Также важно отметить, что строка состояния системы больше не имеет цвета фона. Когда API ссылается на UIStatusBarStyleLightContent, они означают белый текст на чистом фоне. UIStatusBarStyleDefault - черный текст на чистом фоне.

  3. Внешний вид строки состояния контролируется по одному из двух взаимоисключающих базовых путей: вы можете либо установить их программным способом традиционным способом, либо UIKit обновит внешний вид для вас на основе некоторых новых свойств UIViewController. Последний вариант включен по умолчанию. Проверьте значение plist вашего приложения для «Внешний вид строки состояния на основе ViewController», чтобы увидеть, какой из них вы используете. Если для этого значения задано значение YES, каждый контроллер представления верхнего уровня в вашем приложении (кроме стандартного контроллера представления контейнера UIKit) должен переопределить предпочитаемыйStatusBarStyle, возвращая либо стиль по умолчанию, либо стиль освещения. Если вы измените значение plist на NO, то вы можете управлять внешним видом строки состояния, используя знакомые методы UIApplication.

  4. UINavigationController изменит высоту своего UINavigationBar до 44 или 64 точек, в зависимости от довольно странного и недокументированного набора ограничений. Если UINavigationController обнаруживает, что верхняя часть фрейма его вида визуально соприкасается с верхней частью его UIWindow, тогда он рисует свою панель навигации с высотой 64 точки. Если его вершина не соприкасается с вершиной окна UIWindow (даже если она отклонена только на одну точку), тогда она рисует свою навигационную панель «традиционным» способом с высотой 44 точки. Эта логика выполняется UINavigationController, даже если в иерархии контроллера представления вашего приложения есть несколько дочерних элементов. Нет способа предотвратить такое поведение.

  5. Если вы предоставляете пользовательское фоновое изображение панели навигации высотой всего 44 точки (88 пикселей) и границы представления UINavigationController совпадают с границами UIWindow (как описано в # 4), UINavigationController будет рисовать ваше изображение в кадре (0,20,320 , 44), оставляя 20 точек непрозрачного черного пространства над вашим изображением. Это может сбить вас с толку, если вы думаете, что вы умный разработчик, который обошел правило № 1, но вы ошибаетесь. Панель навигации по-прежнему 64 балла. Внедрение UINavigationController в иерархию представлений стиля со слайдом для раскрытия делает это совершенно ясным.

  6. Остерегайтесь запутанно названного свойстваdgeForExtendedLayout UIViewController. Регулировка edgeForExtendedLayout ничего не делает в большинстве случаев. Единственный способ, которым UIKit использует это свойство, - это если вы добавляете контроллер представления в UINavigationController, тогда UINavigationController использует edgeForExtendedLayout, чтобы определить, должен ли его дочерний контроллер представления быть видимым под областью панели навигации / строки состояния. Установка edgeForExtendedLayout в самом UINavigationController не влияет на то, имеет ли UINavigationController область навигации с 44 или 64 точками. Смотрите # 4 для этой логики. Подобная логика компоновки применяется к нижней части вашего представления при использовании панели инструментов или UITabBarController.

  7. Если все, что вы пытаетесь сделать, - это не допустить, чтобы ваш пользовательский дочерний контроллер представления перекрывал панель навигации, когда внутри UINavigationController, тогда задайте дляdgeForExtendedLayout значение UIRectEdgeNone (или, по крайней мере, маску, исключающую UIRectEdgeTop). Установите это значение как можно раньше в жизненном цикле вашего контроллера представления.

  8. UINavigationController и UITabBarController также попытаются дополнить contentInsets табличных представлений и коллекционных представлений своей иерархией подпредставлений. Это происходит аналогично логике строки состояния из # 4. Существует программный способ предотвратить это, автоматически устанавливая AdjustsScrollViewInsets в NO для ваших табличных представлений и представлений коллекции (по умолчанию YES). Это создает некоторые серьезные проблемы для Whisper и Riposte, поскольку мы используем настройки contentInset для управления макетом табличных представлений в ответ на движения панели инструментов и клавиатуры.

  9. Повторим: нет способа вернуться к логике макета строки состояния в стиле iOS 6. Чтобы приблизиться к этому, вы должны переместить все контроллеры представления вашего приложения в представление контейнера, которое смещено на 20 точек от верхней части экрана, оставляя намеренно черный вид за строкой состояния для имитации старого вида. Это метод, который мы в конечном итоге использовали в Riposte и Whisper.

  10. Apple очень старается, чтобы вы не пытались сделать № 9. Они хотят, чтобы мы изменили дизайн всех наших приложений, чтобы перекрыть строку состояния. Однако существует множество убедительных аргументов как по пользовательскому опыту, так и по техническим причинам, почему это не всегда хорошая идея. Вы должны делать то, что лучше для ваших пользователей, а не просто следовать прихоти платформы.


35
Просто хотел добавить, что вы можете добавить ограничение к тому, что находится в верхней части вашего представления и будет прикреплено к верхнему руководству по макету - это оставит пустое пространство за строкой состояния (которую вы можете заполнить любым цветом, который вы хотите) но также позволит представлению автоматически подстраиваться под правильное положение в iOS 6. Таким образом, вам не нужно вручную настраивать положение ваших представлений в коде.
BreadicalMD

4
Это блестящее решение. Вы выставили мое невежество на AutoLayout. Лучше уж быть на этом.
Джаред Синклер

1
Если вы поместите верхнее пространство вашего объекта ниже края верхней направляющей макета, вы можете использовать элемент управления ограничением, чтобы добавить ограничение вертикального интервала к ближайшему соседу, который теперь будет верхней направляющей макета. В качестве альтернативы вы можете использовать ctrl + click от вашего объекта к верхнему руководству по макету, чтобы явно добавить ограничение по вертикали.
BreadicalMD

2
@BreadicalMD Одна часть, которую я не понимаю, это то, что -topLayoutGuide недоступен на iOS 6, значит ли это, что вам нужно использовать различные ограничения Auto Layout на iOS 7 и 6?
Джереми

1
Отличный ответ ... Но у меня есть одно сомнение 1) UINavigationController изменяет высоту. Пожалуйста, объясните это немного подробнее. спасибо
user1010819

122

Обновления от 19 сентября 2013 года:

исправлены ошибки масштабирования путем добавления self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);

исправлены опечатки в NSNotificationCenterзаявлении


Обновления от 12 сентября 2013 года:

исправлено UIViewControllerBasedStatusBarAppearanceдоNO

добавлено решение для приложений с поворотом экрана

добавлен подход для изменения цвета фона строки состояния.


По-видимому, нет способа вернуть строку состояния iOS7 обратно к тому, как она работает в iOS6.

Тем не менее, мы всегда можем написать некоторые коды и превратить строку состояния в iOS6-подобный, и это самый короткий способ, который я могу придумать:

  1. Набор UIViewControllerBasedStatusBarAppearanceдля NOв info.plist(Чтобы отказаться от того, просматривать контроллеры настроить стиль строки состояния , так что мы можем задать стиль строки состояния с помощью метода UIApplicationstatusBarStyle.)

  2. В AppDelegate application:didFinishLaunchingWithOptions, позвоните

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        [application setStatusBarStyle:UIStatusBarStyleLightContent];
        self.window.clipsToBounds =YES;
        self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
    
        //Added on 19th Sep 2013
        self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
    }
    return YES;
    


чтобы:

  1. Проверьте, если это iOS 7.

  2. Установите содержимое строки состояния белым, в отличие от UIStatusBarStyleDefault.

  3. Избегайте подпредставлений, чьи рамки выходят за пределы видимых границ (для видов, анимируемых в основной вид сверху).

  4. Создайте иллюзию, что строка состояния занимает место, как в iOS 6, сместив и изменив размер окна приложения.


Для приложений с поворотом экрана

используйте NSNotificationCenter для обнаружения изменений ориентации путем добавления

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidChangeStatusBarOrientation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];

в if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)и создать новый метод в AppDelegate:

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
    int a = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
    int w = [[UIScreen mainScreen] bounds].size.width;
    int h = [[UIScreen mainScreen] bounds].size.height;
    switch(a){
        case 4:
            self.window.frame =  CGRectMake(0,20,w,h);
            break;
        case 3:
            self.window.frame =  CGRectMake(-20,0,w-20,h+20);
            break;
        case 2:
            self.window.frame =  CGRectMake(0,-20,w,h);
            break;
        case 1:
           self.window.frame =  CGRectMake(20,0,w-20,h+20);
    }
}

Чтобы при изменении ориентации он вызывал оператор switch для определения ориентации экрана приложения («Портрет», «Перевернутый вниз», «Пейзаж влево» или «Пейзаж вправо») и соответственно изменял рамку окна приложения, создавая иллюзию строки состояния iOS 6.


Чтобы изменить цвет фона строки состояния:

Добавить

 @property (retain, nonatomic) UIWindow *background;

в , AppDelegate.hчтобы сделать backgroundсвойство в классе и предотвратить ARC от deallocating его. (Вам не нужно делать это, если вы не используете ARC.)

После этого вам просто нужно создать UIWindow в if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1):

background = [[UIWindow alloc] initWithFrame: CGRectMake(0, 0, self.window.frame.size.width, 20)];
background.backgroundColor =[UIColor redColor];
[background setHidden:NO];

Не забудьте @synthesize background;после @implementation AppDelegate!


3
Это нарушает вращение. просто один на один
Джесси Наухер

2
@JesseNaugher Я рекомендую изменить ограничение по вертикали от 0 до 20 программно. Это будет работать на ротацию.
эксперт

2
Любая идея о том, как мы можем избежать расширения панели навигации на 20 пикселей? Это решение хорошо для меня, но моя навигационная панель слишком высока на 20 пикселей.
Симонбс

4
@ArchyHolt: Ваше простое решение работает для меня, за исключением случаев, когда я представляю контроллер модального представления. После того, как модальный контроллер вида отклонен, оставшийся вид теперь находится под строкой состояния. Я воспроизвел это в новом примере проекта, чтобы убедиться, что больше ничего интересного не происходит. Я думаю, может быть, ваше более продвинутое решение могло бы быть здесь полезным, но я не уверен, какое уведомление придет в игру Любые идеи?
Маркдорисон

4
Представление сбрасывается после закрытия модального контроллера представления. :(
КаренАнн

41

ОБНОВЛЕНИЕ (НОВОЕ РЕШЕНИЕ)

Это обновление является лучшим решением проблемы панели навигации iOS 7. Вы можете установить пример цвета панели навигации: FakeNavBar.backgroundColor = [UIColor redColor];

Примечание: если вы используете контроллер навигации по умолчанию, пожалуйста, используйте старое решение.

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if(NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0)
    {
        UIView *FakeNavBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
        FakeNavBar.backgroundColor = [UIColor whiteColor];

        float navBarHeight = 20.0;
        for (UIView *subView in self.window.subviews) {

            if ([subView isKindOfClass:[UIScrollView class]]) {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height - navBarHeight);
            } else {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height);
            }
        }
        [self.window addSubview:FakeNavBar];
    }

    return YES;

}

СТАРЫЕ РЕШЕНИЯ - Если вы используете предыдущий код, пожалуйста, игнорируйте следующий код и изображение

Это старая версия решения для панели навигации iOS 7.

Я решил проблему с помощью следующего кода. Это для добавления строки состояния. didFinishLaunchingWithOptions

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    UIView *addStatusBar = [[UIView alloc] init];
    addStatusBar.frame = CGRectMake(0, 0, 320, 20);
    addStatusBar.backgroundColor = [UIColor colorWithRed:0.973 green:0.973 blue:0.973 alpha:1]; //change this to match your navigation bar
    [self.window.rootViewController.view addSubview:addStatusBar];
}

И для Интерфейсного Разработчика это для, когда вы открываете с iOS 6; это начинается с 0 пикселей.

Примечание. Дельты iOS 6/7 появляются только в том случае, если вы сняли флажок «Использовать автоматическое расположение» для контроллера вида в «Инспекторе файлов» (крайний левый значок) в области сведений.

Введите описание изображения здесь


6
Ты сделал мой день. Возьми +1 за помощь!
Ниру Мукунд Шах

5
Пожалуйста, обратите внимание: iOS 6/7 Дельты появляются только в том случае, если вы сняли флажок «Использовать автоматическое расположение» для Контроллера представления в «Инспекторе файлов» (крайний левый значок) в области сведений.
Мэтт

1
Большое спасибо! Вы спасли меня от многих неприятностей!
Neowinston

2
Кто сказал, что расположение строки состояния стиля iOS 6 не может быть сохранено, Вы можете сделать это способом @ TacettinÖzbölük ... спасибо товарищу за это решение awsum.
Vizllx

1
хороший! также, чтобы отметить, что яблоко предпочитает это сейчас: if (NSFoundationVersionNumber> = NSFoundationVersionNumber_iOS_6_1) {}
Джоэл Балмер

26

РЕШЕНИЕ :

Установите его в вашем viewcontroller или в rootviewcontroller, переопределив метод:

-(BOOL) prefersStatusBarHidden
    {
        return YES;
    }

Неплохое решение. Полностью удалить планку. Может не быть идеальным для UX все время, но выполнимо.
Фархан Хафиз

Просто потрясающе. Работал на меня без нареканий.
MadLokesh

Сценарий: как только я снова переключаюсь на свой UIVIew после воспроизведения видео в полноэкранном режиме, внизу появляется черная полоса, которая соответствует размеру строки состояния, хотя я уже использовала строку состояния. Я полностью удалил строку состояния, и теперь проблема устранена.
MadLokesh

Я только успешно использовал этот метод
user2277872

17

Вот еще один подход для проектов, которые широко используют раскадровку:

ЦЕЛЬ:

Цель этого подхода - воссоздать тот же стиль строки состояния в iOS7, который был в iOS6 (см. Заголовок вопроса «Строка состояния iOS 7 Вернуться к стилю iOS 6»).

РЕЗЮМЕ:

Чтобы добиться этого, мы максимально используем раскадровку, смещая элементы пользовательского интерфейса, которые перекрываются строкой состояния (под iOS 7), вниз, в то время как с помощью дельт-страниц можно отменить изменение макета вниз для iOS 6.1 или более ранней версии. Получающееся дополнительное пространство в iOS 7 затем занято UIView с backgroundColor, установленным в цвет по нашему выбору. Последний может быть создан в коде или с помощью раскадровки (см. АЛЬТЕРНАТИВЫ ниже)

Предположения:

Чтобы получить желаемый результат при выполнении следующих действий, предполагается, что для View controller-based status bar appearanceнего задано значение NO, а Status bar styleдля параметра «Прозрачный черный стиль (альфа из 0,5)» или «Непрозрачный черный стиль». Обе настройки можно найти / или добавить в разделе «Информация» в настройках вашего проекта.

ШАГИ:

  • Добавьте в UIWindow подпредставление, которое будет использоваться в качестве фона строки состояния. Чтобы добиться этого, добавьте следующее в свой AppDelegate application: didFinishLaunchingWithOptions:послеmakeKeyAndVisible

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        UIView *statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourAppsUIWindow.frame.size.width, 20)];
        statusBarBackgroundView.backgroundColor = [UIColor blackColor];
        [yourAppsUIWindow addSubview:statusBarBackgroundView];
    }
    
  • Поскольку вы программно добавили фон ТОЛЬКО для iOS 7, вам придется соответствующим образом настроить макет элементов пользовательского интерфейса, которые перекрываются строкой состояния, при этом сохраняя их макет для iOS6. Для этого сделайте следующее:

    • Убедитесь, что Use Autolayoutдля вашей раскадровки не выбрано (это потому, что в противном случае «iOS 6/7 Deltas» не отображается в Инспекторе размеров). Сделать это:
      • выберите файл раскадровки
      • показать коммунальные услуги
      • выберите «Показать инспектор файлов»
      • В разделе «Документ Интерфейсного Разработчика» снимите флажок «Использовать Autolayout»
    • При желании, чтобы помочь вам отслеживать изменения макета для iOS 7 и 6 по мере их применения, выберите «Помощник редактора», выберите «Предварительный просмотр» и «iOS 6.1 или более ранняя версия»: введите описание изображения здесь введите описание изображения здесь
    • Теперь выберите элемент пользовательского интерфейса, который вы хотите настроить, чтобы он больше не перекрывался строкой состояния.
    • Выберите «Показать инспектор размера» в столбце «Утилиты».
    • Переместите ваш элемент пользовательского интерфейса вдоль оси Y на ту же величину, что и высота строки состояния bg: введите описание изображения здесь
    • И измените значение iOS6 / 7 Deltas для Y на ту же ОТРИЦАТЕЛЬНУЮ величину, что и высота bg строки состояния (обратите внимание на изменение в предварительном просмотре iOS 6, если вы его используете): введите описание изображения здесь

АЛЬТЕРНАТИВЫ:

Чтобы добавить еще меньше кода в проекты, насыщенные раскадровкой, и иметь автоматический фоновый режим строки состояния, вместо программного добавления фона для строки состояния, вы можете добавить цветное представление к каждому контроллеру представления, который находится в самом верху основного вида указанного viewcontroller. Затем вы изменили бы дельту высоты этого нового вида на ту же отрицательную величину, что и высота вашего вида (чтобы она исчезла в iOS 6).

Недостатком этой альтернативы (хотя, возможно, она и незначительна, учитывая совместимость с автоматическим поворотом) является тот факт, что это дополнительное представление не сразу видно, если вы просматриваете раскадровку для iOS 6. Вы бы знали, что оно есть, если вы посмотрите на " Схема документа "Раскадровка.


12

Если вы не хотите, чтобы ваши контроллеры представления перекрывались строкой состояния (и панелями навигации), снимите флажок «Расширить края под верхними панелями» в Интерфейсном Разработчике в Xcode 5.

Снимите флажок Расширить края под верхней панели


7
Это возможно, только если вы используете раскадровку
Cœur

3
Он работает только с контейнерами vcs, такими как контроллер навигации или контроллер вкладок
Andrea

2
dgeForExtendedLayout используется только контроллерами представления контейнера (такими как UINavigationController), чтобы определить, должны ли его дочерние представления перекрываться хромом родителя. Установка этого свойства в корневом контроллере представления для UIWindow ничего не делает. См. Мой ответ выше: stackoverflow.com/questions/18294872/…
jaredsinclair

Как вы делаете это для UITabBarController @Andrea? Спасибо.
Карен Энн

@KarenAnne Зависит, если вы делаете программно или с раскадровками. Программно вам просто нужно установить свойствоdgeForExtent на то, что вам нравится в контроллере представления, который вы показываете внутри UITabBarViewController, но чтобы не было проблемы со строкой состояния, вы должны загрузить контроллер uinavigation внутри th UITabbarController. Проверьте здесь. developer.apple.com/library/ios/documentation/UserExperience/…
Андреа

11

Apple выпустила Технический Q & A QA1797: не позволяя строке состояния скрывать ваши взгляды . Он отлично работает для версий iOS 6 и iOS 7.


5
Apple предполагает, что все используют авто-макет. Авторазметка была ужасна в Xcode 4, а Xcode 5 был только что выпущен, так что это сомнительное предположение.
Гленн Мейнард

1
Но в перспективе это лучшее решение, чем изменение размера рамки корневого окна или строки состояния.
Игорь

Насколько я могу судить, решение Apple не работает, если ваш rootViewController является splitViewController.
Верн Дженсен

8

Я просмотрел много-много-много-много уроков, чтобы решить эту чертову проблему. Но ни один из них не работает! Вот мое решение, и оно работает для меня:

if( [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f ) {
    float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
    for( UIView *v in [self.view subviews] ) {
        CGRect rect = v.frame;
        rect.origin.y += statusBarHeight;
        v.frame = rect;
    }
}

Логика проста. Я перевожу все дочерние представления на self.view с 20 пикселями. Вот и все. Затем скриншот будет отображаться так же, как и iOS 6. Я ненавижу строку состояния iOS7! ~ "~


2
где я должен добавить это? в приложении делегат запустил с настройками?
mhmdshawqi

Когда я это делаю, моя строка состояния становится белой
ropo

6

Небольшая альтернатива ответу Арчи Холта, немного более простая:

а. Набор UIViewControllerBasedStatusBarAppearanceдля NOв info.plist

б. В AppDelegateх application:didFinishLaunchingWithOptions:, звоните:

if ([[UIDevice currentDevice].systemVersion floatValue] < 7)
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
else
{
    // handling statusBar (iOS7)
    application.statusBarStyle = UIStatusBarStyleLightContent;
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    self.window.clipsToBounds = YES;

    // handling screen rotations for statusBar (iOS7)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

И добавьте метод:

- (void)applicationDidChangeStatusBarOrientationNotification:(NSNotification *)notification
{
    // handling statusBar (iOS7)
    self.window.frame = [UIScreen mainScreen].applicationFrame;
}

Вы можете также рассмотреть подклассы UIWindowдля обработки UIApplicationDidChangeStatusBarOrientationNotificationсебя.


у вас есть проблемы с presentViewController: анимированные: завершение:?
Tùng

@ TùngĐỗ правда, поэтому я сделал альтернативу, которая работает лучше: stackoverflow.com/questions/18294872/…
Cœur

5

Я использовал это во всех моих контроллерах представления, это просто. Добавьте эти строки во все ваши методы viewDidLoad:

- (void)viewDidLoad{
    //add this 2 lines:
    if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

    [super viewDidLoad];
}

1
Работал как шарм, и до смерти легко. В режиме ruby, перед вызовом super, используйте: self.edgesForExtendedLayout = UIRectEdgeNone, если откликается ToSelector ("dgeForExtendedLayout ")
профессор

4

Попробуйте этот простой метод ....

Шаг 1 : Чтобы изменить в одиночномviewController

[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];

Шаг 2 : изменить во всем приложении

info.plist
      ----> Status Bar Style
                  --->UIStatusBarStyle to UIStatusBarStyleBlackOpaque

Шаг 3 : также добавьте это в каждый, viewWillAppearчтобы отрегулировать statusbarвысоту дляiOS7

    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 7) {
        CGRect frame = [UIScreen mainScreen].bounds;
        frame.origin.y+=20.0;
        frame.size.height-= 20.0;
        self.view.frame = frame;
        [self.view layoutIfNeeded];
    }


3

Я достиг строки состояния, как iOS 6 в iOS 7.

Установите для UIViewControllerBasedStatusBarAppearance значение NO в info.plist

Вставить этот код в - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptionsметод

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);

    //Added on 19th Sep 2013
    NSLog(@"%f",self.window.frame.size.height);
    self.window.bounds = CGRectMake(0,0, self.window.frame.size.width, self.window.frame.size.height);
}

Это может оттолкнуть все ваши просмотры на 20 пикселей. Чтобы прийти, используйте следующий -(void)viewDidAppear:(BOOL)animatedметод в методе

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    CGRect frame=self.view.frame;
    if (frame.size.height==[[NSUserDefaults standardUserDefaults] floatForKey:@"windowHeight"])
    {
        frame.size.height-=20;
    }
    self.view.frame=frame;
}

Вы должны установить значение WindowHeight Userdefaults после выделения окна в методе didFinishLauncing, например:

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[[NSUserDefaults standardUserDefaults] setFloat:self.window.frame.size.height forKey:@"windowHeight"];

Лучше сделать так, чтобы ваш UINavigationBar heightравнялся 64 вместо 44. Тогда ваша полоса будет расширяться до вершины, как в приложениях Apple.
Аарон Брагер

@AaronBrager Но мое требование было показать строку состояния стиля iOS 6.
Роза пустыни

Можете ли вы добавить решение для альбомной ориентации iOS 7 ?. Я делаю то же самое. но это не работает в iOS 7 Landscape.
sathiamoorthy

@DesertRose THX! Это работает для меня, но это отсекает uitabbar внизу. У меня есть приложение на основе контроллера панели вкладок с 3 представлениями, 2 из которых являются tableviewcontrollers.
Марсиококо

1
До тех пор, пока я не поверну устройство (мое устройство iOS 7 - iPad), это исправляет это прекрасно. Но как только я поворачиваюсь, черная полоса остается точно там, где она есть, и «представление» (извините, если это неправильный технический термин, я PhoneGap / веб-парень) сохраняет свою уменьшенную высоту - за исключением того, что это больше не высота, это ширина. Это решение не поддерживает ротацию, но это лучшее исправление, которое я когда-либо видел, - как его можно улучшить, чтобы отслеживать ротацию устройств? Спасибо!
Tylerl

2

Если вы используете конструктор интерфейса, попробуйте это:

В вашем XIB-файле:

1) Выберите основной вид, установите цвет фона на черный (или любой другой цвет, который вы хотите, чтобы строка состояния была

2) Убедитесь, что фон является автономным подпредставлением, расположенным как дочерний элемент верхнего уровня представления контроллера.
Переместите фон, чтобы стать прямым потомком зрения контроллера. Проверьте панель автоматического изменения размера, чтобы убедиться, что вы заблокировали все края рамки, активировали обе оси гибкости, и, если это UIImageView, установите для режима содержимого значение Масштаб, чтобы заполнить. Программно это преобразуется в contentMode, установленный в UIViewContentModeScaleToFill, и имеет его маску автоматического изменения размера (UIViewAutoresizingFurableWidth | UIViewAutoresizingF FlexibleHeight).

3) Теперь переместите все, что заблокировано, сверху вниз - на 20 пунктов и установите для iOS 6/7 delta Y значение -20.
Все дочерние элементы верхнего уровня, которые привязаны к верхнему фрейму на панели автоматического изменения размера, должны быть сдвинуты вниз на 20 пунктов, и для их iOS 6/7 delta Y должно быть установлено значение -20. (Cmd выберите все из них и нажмите стрелку вниз 20 раз - есть ли лучший способ для кого-либо?)

4) Отрегулируйте iOS 6/7 высоту дельты всех вышеупомянутых элементов, которые имели гибкую высоту. Для любого из элементов, которые были заблокированы в верхней и нижней части рамки и на панели автоматического изменения размера включена гибкая высота, также должна быть установлена ​​высота треугольника iOS 6/7, равная 20. Это включает фоновое представление, упомянутое выше. Это может показаться антиинтуитивным, но из-за порядка, в котором они применяются, это необходимо. Сначала задается высота кадра (в зависимости от устройства), затем применяются дельты, и, наконец, маски авторазмера применяются на основе позиций смещения всех дочерних кадров - подумайте немного, это будет иметь смысл.

5) Наконец, элементы, которые были привязаны к нижней рамке, но не к верхней рамке, вообще не нуждаются в дельтах.

Это даст вам одинаковую строку состояния в iOS7 и iOS6.

С другой стороны, если вы хотите стилизацию под iOS7 при сохранении совместимости с iOS6, тогда установите значения delta Y / delta height равными 0 для фона.

Чтобы увидеть больше информации о переходе на iOS7, прочитайте полный пост: http://uncompiled.blogspot.com/2013/09/legacy-compatible-offsets-in-ios7.html


Никаких различий при использовании автоматического макета
lostintranslation

2

Моим решением было добавить UIViewвысоту 20 точек в верхней части окна в iOS 7. Затем я создал метод в своем классе AppDelegate, чтобы показать / скрыть «сплошной» фон строки состояния. В application:didFinishLaunchingWithOptions::

// ...

// Add a status bar background
self.statusBarBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width, 20.0f)];
self.statusBarBackground.backgroundColor = [UIColor blackColor];
self.statusBarBackground.alpha = 0.0;
self.statusBarBackground.userInteractionEnabled = NO;
self.statusBarBackground.layer.zPosition = 999; // Position its layer over all other views
[self.window addSubview:self.statusBarBackground];

// ...
return YES;

Затем я создал метод постепенного увеличения / уменьшения черного фона строки состояния:

- (void) showSolidStatusBar:(BOOL) solidStatusBar
{
    [UIView animateWithDuration:0.3f animations:^{
        if(solidStatusBar)
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
            self.statusBarBackground.alpha = 1.0f;
        }
        else
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
            self.statusBarBackground.alpha = 0.0f;
        }
    }];
}

Все, что мне нужно сделать сейчас, это позвонить, [appDelegate showSolidStatusBar:YES]когда это необходимо.


2

Это может быть огромной проблемой, если вы используете Auto layout, потому что вы больше не можете напрямую манипулировать кадрами. Есть простое решение без лишней работы.

В итоге я написал вспомогательный метод в Utility Class и вызвал его из всех viewDidLayoutSubviewsметодов контроллеров представления .

+ (void)addStatusBarIfiOS7:(UIViewController *)vc
    {
        if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
            CGRect viewFrame = vc.view.frame;
            if(viewFrame.origin.y == 20) {
                //If the view's y origin is already 20 then don't move it down.
                return;
            }
            viewFrame.origin.y+=20.0;
            viewFrame.size.height-= 20.0;
            vc.view.frame = viewFrame;
            [vc.view layoutIfNeeded];
        }
    }

Переопределите свой viewDidLayoutSubviewsметод в контроллере представления, где вы хотите строку состояния. Это поможет вам пережить бремя автопоставки.

- (void)viewDidLayoutSubviews
{
    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    [super viewDidLayoutSubviews];
    [MyUtilityClass addStatusBarIfiOS7:self];
}

1

Самый простой способ сделать это - установить старый SDK на свой новейший Xcode.

Как установить более старый SDK на новейший Xcode?

  1. Вы можете получить iOS 6.1 SDK с http://www.4shared.com/zip/NlPgsxz6/iPhoneOS61sdk.html или загрузить старый Xcode и получить SDK из его содержимого.

  2. Разархивируйте и вставьте эту папку в /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs

  3. Перезапустите xcode.

  4. Теперь вы можете выбрать более старый SDK в настройках вашего проекта.

Надеюсь, это поможет вам. У меня это сработало =)


работал на меня. спасибо @marcelosalloum, но все еще ищу обходной путь для моего приложения phonegap (uiwebview) для поддержки прозрачной строки состояния iOS7 для будущего обновления моего приложения. Спасибо еще раз. ;)
Ханизм

@marcellosaloum, вы уверены, что приложение будет принято Apple? Они сказали, что приложения, скомпилированные с XCode 4, больше не будут приниматься ... это фактически означает iOS 6 SDK.
Валерио

Мое приложение действительно было принято, потому что Xcode5 может компилировать старые iOS SDK. Я не уверен, что AppStore отклонит встроенные приложения Xcode4, но (Xcode4! = IOS 6 SDK), как вы сказали.
marcelosalloum

Это было после 1 февраля? В тот день Apple сделала это обязательным.
Валерио

Нет, последний раз этот код касался в прошлом году, народ. Не знал, что Apple сделала это обязательным (хотя я не рад, что узнал). Не могли бы вы опубликовать здесь ссылку, которая говорит это? Приветствия
marcelosalloum

1

Что касается использования presentViewController:animated:completion:беспорядка window.rootViewController.view, мне пришлось найти другой подход к этой проблеме. Наконец-то я получил его для работы с модальностями и вращениями, создав подкласс UIView моего rootViewController.

.час

@interface RootView : UIView

@end

.m

@implementation RootView

-(void)setFrame:(CGRect)frame
{
    if (self.superview && self.superview != self.window)
    {
        frame = self.superview.bounds;
        frame.origin.y += 20.f;
        frame.size.height -= 20.f;
    }
    else
    {
        frame = [UIScreen mainScreen].applicationFrame;
    }

    [super setFrame:frame];
}

- (void)layoutSubviews
{
    self.frame = self.frame;

    [super layoutSubviews];
}

@end

Теперь у вас есть сильный обходной путь для анимации iOS7.


1

Я опаздываю на этот ответ, но я просто хочу поделиться тем, что я сделал, что в принципе является самым простым решением

Прежде всего -> Перейдите в свой info.plistФайл и добавьте Стиль строки состояния-> Прозрачный черный стиль (Альфа 0.5)

Теперь вот оно:

Добавьте этот код в свой AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
     //Whatever your code goes here
  if(kDeviceiPad){

     //adding status bar for IOS7 ipad
         if (IS_IOS7) {
              UIView *addStatusBar = [[UIView alloc] init];
              addStatusBar.frame = CGRectMake(0, 0, 1024, 20);
              addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //change this to match your navigation bar
              [self.window.rootViewController.view addSubview:addStatusBar];
                    }
                }
    else{

         //adding status bar for IOS7 iphone
        if (IS_IOS7) {
            UIView *addStatusBar = [[UIView alloc] init];
            addStatusBar.frame = CGRectMake(0, 0, 320, 20);
            addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //You can give your own color pattern
            [self.window.rootViewController.view addSubview:addStatusBar];
        }

    return YES;
   }

0

Мое очень простое решение (при условии, что поддерживается только вертикальная ориентация) состоит в том, чтобы переопределить границы окна приложения для версий iOS ниже 7 в методе делегата приложения didFinishLaunchingWithOptions:

CGRect screenBounds = [[UIScreen mainScreen] bounds];
if ([HMService getIOSVersion] < 7) {
    // handling statusBar (iOS6) by leaving top 20px for statusbar.
    screenBounds.origin.y = 20;
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
else {
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}

Ваш код просто сдвигает 'y' с 0 до 20, но не регулирует высоту соответственно, поэтому вы должны добавить screenBounds.size.height - = 20; сразу после screenBounds.origin.y = 20;
Амит С.

0

Вы можете скрыть строку состояния все вместе. Так что ваше приложение будет полноэкранным. Я думаю, что это лучшее, что вы получите.

UIStatusBarStyleNone или установите в настройках цели.


2
где указать UIStatusbarstylenone
user4951

0

Шаги для скрытия строки состояния в iOS 7:

1. Перейдите в файл info.plist вашего приложения.

2.И установить, просмотреть внешний вид строки состояния контроллера: Boolean NO

Надеюсь, я решил проблему в строке состояния .....


0

Чтобы продолжить работу с setStatusBarHidden: я использую эту категорию:

@interface UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden;

@end

@implementation UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden{
    if (!IOS7) {
        [self setStatusBarHidden:statusBarHidden];
        return;
     }

    if ([self isStatusBarHidden] == statusBarHidden) {
        return;
    }

    [self setStatusBarHidden:statusBarHidden];
    [self keyWindow].clipsToBounds = YES;
    CGFloat offset = statusBarHidden ? 0 : 20;
    [self keyWindow].frame =  CGRectMake(0,offset,[self keyWindow].frame.size.width,[self keyWindow].frame.size.height-offset);
    [self keyWindow].bounds = CGRectMake(0, offset, [self keyWindow].frame.size.width,[self keyWindow].frame.size.height);
}

@end


0

Это может быть слишком поздно, чтобы поделиться, но у меня есть кое-что, что могло бы помочь кому-то, я пытался подразделить UINavigationBar и хотел сделать его похожим на ios 6 с черной строкой состояния и текстом строки состояния в белом.

Вот что я нашел для этого

        self.navigationController?.navigationBar.clipsToBounds = true
        self.navigationController?.navigationBar.translucent = false
        self.navigationController?.navigationBar.barStyle = .Black
        self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()

Это сделало мой фон строки состояния черным, текст строки состояния белым, а цвет панели навигации - белым.

iOS 9.3, XCode 7.3.1

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.