Как скрыть строку состояния, не скрывая ее
Разработчики iOS наверняка знают о проблеме со строкой состояния и знаменитым "слайдом / гамбургером / ящиком". Проблема хорошо объяснена здесь: http://uxmag.com/articles/adapting-ui-to-ios-7-the-side-menu
Я использую библиотеку MMDrawerController, и у нее есть приятный хак, который позволяет нам создать фиктивную строку состояния прямо над контроллером представления контейнера. К сожалению, это не очень хорошо работает. Какие новости? Новость заключается в том, что я наткнулся на приложение ( Tinder), которое идеально решает эту проблему. Я создал GIF, который отлично показывает, что делает Tinder.
Вам нужно подождать несколько секунд, чтобы увидеть гифку, потому что в ней есть ошибка, и я не знаю, как от нее избавиться. Просто подождите одну / две секунды, и вы сможете правильно увидеть GIF.
Во всяком случае, что делает Tinder? Когда пользователь нажимает на верхнюю левую кнопку меню и начинает смахивать вправо, строка состояния аккуратно исчезает. И когда представление вернется в исходное положение, строка состояния появится снова.
Я и счастлив, и немного расстроен из-за этого, потому что это означает, что должен быть способ сделать это, но я действительно не знаю, как реализовать это (возможно, взлом MMDrawerController
). Любая помощь будет высоко ценится.
ВАЖНЫЙ
Пожалуйста, обратите внимание на то, что метод setStatusBarHidden:
будет полностью скрывать строку состояния, это означает, что весь вид имеет высоту -20px. Это, очевидно, не решение, потому что, как видно из рисунка, изображение не растягивается.
5 ответов
Ваша главная проблема с MMDrawerController
, Если вы покопаетесь в нем, вы найдете множество методов, связанных со статусной строкой, таких как setShowsStatusBarBackgroundView
setStatusBarViewBackgroundColor
и больше. Что-то в их коде увеличивает представление, когда строка состояния скрыта.
В качестве альтернативы вы можете использовать другой контроллер ящика или использовать пользовательский код.
Вот простой способ сделать это:
ViewControllerA:
-(BOOL)prefersStatusBarHidden
{
return _hidden;
}
- (void)statusHide
{
[UIView animateWithDuration:0.4 animations:^() {[self setNeedsStatusBarAppearanceUpdate];
}completion:^(BOOL finished){}];
}
ViewControllerB: (Контейнер в ViewControllerA)
- (IBAction)move:(UIButton *)sender
{
parent = (ViewController*)self.parentViewController;
parent.hidden = !parent.hidden;
CGRect frame = parent.blueContainer.frame;
if(parent.hidden)
{
frame.origin.x = 150;
}
else
{
frame.origin.x = 0;
}
[UIView animateWithDuration:1 animations:^() {parent.blueContainer.frame = frame;}completion:^(BOOL finished){}];
[parent statusHide];
}
Для совместимости с iOS 6 используйте:
[[UIApplication sharedApplication] setStatusBarHidden:_hidden withAnimation:UIStatusBarAnimationFade];
Представление таблицы и другие подпредставления останутся на своих местах и не будут перемещены вверх.
Редактировать:
Добавление панели навигации:
UINavigationController изменит высоту своего UINavigationBar до 44 или 64 точек, в зависимости от довольно странного и недокументированного набора ограничений. Если UINavigationController обнаруживает, что вершина фрейма его вида визуально соприкасается с вершиной его UIWindow, то он рисует свою панель навигации с высотой 64 точки. Если его вершина не соприкасается с вершиной окна UIWindow (даже если она отклонена только на одну точку), то она рисует свою навигационную панель "традиционным" способом с высотой 44 точки. Эта логика выполняется UINavigationController, даже если в иерархии контроллера представления вашего приложения есть несколько дочерних элементов. Нет способа предотвратить такое поведение.
Взято отсюда
Вы могли бы очень просто подкласс UINavigationController
и создайте свой собственный navbar, чтобы избежать этой досады.
Я не знаю, решит ли это вашу проблему, но я получил почти такой же эффект, используя проект SWRevealViewController. В appDelegate я установил метод делегата из этого класса, чтобы сделать это:
- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position {
#ifdef DEBUG
NSArray *teste = @[@"FrontViewPositionLeftSideMostRemoved",@"FrontViewPositionLeftSideMost",@"FrontViewPositionLeftSide",@"FrontViewPositionLeft",@"FrontViewPositionRight",@"FrontViewPositionRightMost",@"FrontViewPositionRightMostRemoved"];
NSLog(@"%@ %d", teste[position], position);
#endif
if (position == FrontViewPositionRight)
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
UINavigationController *frontViewController = (id)revealController.frontViewController;
frontViewController.navigationBar.centerY += (position == FrontViewPositionRight) ? 20 : 0; // 20 == statusbar heihgt
}
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position {
if (position == FrontViewPositionLeft)
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
}
centerY - это категория в UIView, которая устанавливает center.y, не занимаясь скучной частью установки переменных кадра.
Вот как вы должны сделать это в iOS 7:
@implementation ViewController
{
BOOL _hideStatusBar;
}
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleDefault;
}
-(UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
return UIStatusBarAnimationFade;
}
-(BOOL)prefersStatusBarHidden
{
return _hideStatusBar;
}
-(void)setStatusBarHidden:(BOOL)hidden
{
[UIView animateWithDuration:1.0 animations:^{
_hideStatusBar = hidden;
[self setNeedsStatusBarAppearanceUpdate];
}];
}
@end
Вы можете использовать -setStatusBarHidden:withAnimation:
если вы отрегулируете свои рамки просмотра в -viewDidAppear:
, то вы не увидите никакого натяжения. Обратите внимание, что автоматическое расположение отключено.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect frame = self.view.frame;
// adjust root view frame
frame.origin.y -= 20;
frame.size.height += 20;
[self.view setFrame:frame];
// adjust subviews y position
for (UIView *subview in [self.view subviews])
{
CGRect frame = subview.frame;
frame.origin.y += 20;
[subview setFrame:frame];
}
}
- (IBAction)sliderChanged:(id)sender
{
UISlider *s = (UISlider *)sender;
if (s.value > .5)
{
UIApplication *app = [UIApplication sharedApplication];
if (![app isStatusBarHidden])
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
}
else
{
UIApplication *app = [UIApplication sharedApplication];
if ([app isStatusBarHidden])
[app setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
}
}
Проверьте метод setStatusBarHidden:withAnimation:
на UIApplication
, Это позволит вам показать или скрыть строку состояния, и анимация может быть ни одна, исчезать или слайд. Вам просто нужно добавить вызов, чтобы скрыть панель, и один, чтобы показать панель в правильное время, и решить, нравится ли вам затухание, как показано на рисунке, или слайд работает лучше для вас.