UIView не меняет размер на весь экран при скрытии панели навигации и панели вкладок - PullRequest
37 голосов
/ 10 июля 2009

У меня есть приложение с панелью вкладок и панелью навигации для нормального взаимодействия. Один из моих экранов - это большая часть текста, поэтому я позволяю пользователю нажимать, чтобы перейти в полноэкранный режим (вроде как Photos.app).

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

удалена мертвая ссылка ImageShack

Я не уверен, что вызвало это. Пробел определенно не является видом позади текстового представления, поскольку я устанавливаю его цвет фона на красный, чтобы быть уверенным. Что может быть причиной этого?

** ОБНОВЛЕНИЕ **

Я провел некоторое тестирование на попадание в подклассе UIWindow и обнаружил, что пробел на самом деле является недокументированным / неопубликованным UILayoutContainerView. Это родительский вид tabBar. Я не думаю, что рекомендуется напрямую манипулировать этим видом, так как я могу скрыть панель вкладок?

** ОБНОВЛЕНИЕ № 2 **

Я проверил кадр self.view до и после анимации, и похоже, что родительский вид недостаточно изменяет размеры.

после перехода в полноэкранный режим рамка просмотра имеет высоту всего 411 пикселей. Я попытался поэкспериментировать с фреймом вручную, а также установил autoResizeMask без удачи.

**** ОБНОВЛЕНИЕ: вот конечный результат ****

- (void)toggleFullscreen {
    isFullScreen = !isFullScreen;  //ivar

    //hide status bar & navigation bar
    [[UIApplication sharedApplication] setStatusBarHidden:isFullScreen animated:YES];
    [self.navigationController setNavigationBarHidden:isFullScreen animated:YES];

    [UIView beginAnimations:@"fullscreen" context:nil];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:.3];

    //move tab bar up/down
    CGRect tabBarFrame = self.tabBarController.tabBar.frame;
    int tabBarHeight = tabBarFrame.size.height;
    int offset = isFullScreen ? tabBarHeight : -1 * tabBarHeight;
    int tabBarY = tabBarFrame.origin.y + offset;
    tabBarFrame.origin.y = tabBarY;
    self.tabBarController.tabBar.frame = tabBarFrame;

    //fade it in/out
    self.tabBarController.tabBar.alpha = isFullScreen ? 0 : 1;

    //resize webview to be full screen / normal
    [webView removeFromSuperview];
    if(isFullScreen) {
                //previousTabBarView is an ivar to hang on to the original view...
        previousTabBarView = self.tabBarController.view;
        [self.tabBarController.view addSubview:webView];

        webView.frame = [self getOrientationRect];  //checks orientation to provide the correct rect

    } else {
        [self.view addSubview:webView];
        self.tabBarController.view = previousTabBarView;
    }

    [UIView commitAnimations];
}

(обратите внимание, что я переключил просмотр текста в веб-просмотр, но то же самое работает для исходного просмотра текста)

Ответы [ 15 ]

29 голосов
/ 22 июля 2009

У меня была именно эта проблема, когда я анимировал панель вкладок и панель навигации в нижней и верхней части экрана соответственно, оставляя белое пространство размером 49px там, где была панель вкладок.

Оказывается, причина, по которой мой новый «полноэкранный» вид на самом деле не заполнял пространство, заключалась в том, что я добавлял полноэкранный вид как подпредставление представления контроллера навигации, которое само было дочерним по отношению к контроллеру панели вкладок.

Чтобы исправить это, я просто добавил новое полноэкранное представление (в вашем случае это представление со всем текстом) как подпредставление представления UITabBarController.

[[[self tabBarController] view] addSubview:yourTextView];

Тогда все, что вам нужно сделать, это убедиться, что кадр вашего подпредставления имеет 480 x 320 пикселей, и он должен заполнить экран (включая область, которая ранее была таинственным пробелом)

5 голосов
/ 22 июля 2009

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

- (void)viewDidLoad {
  [super viewDidLoad];
  currentlyHidden = NO;
}

- (void) hideStuff {
  SO2AppDelegate *appDelegate = (id)[[UIApplication sharedApplication] delegate];
  self.navigationController.navigationBarHidden = YES;

  CGRect newFrame = appDelegate.tabBarController.view.frame;
  newFrame.size.height += appDelegate.tabBarController.tabBar.frame.size.height;
  appDelegate.tabBarController.view.frame = newFrame;
}

- (void) showStuff {
  SO2AppDelegate *appDelegate = (id)[[UIApplication sharedApplication] delegate];

  CGRect newFrame = appDelegate.tabBarController.view.frame;
  newFrame.size.height -= appDelegate.tabBarController.tabBar.frame.size.height;
  appDelegate.tabBarController.view.frame = newFrame;

  self.navigationController.navigationBarHidden = NO;
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
  if (currentlyHidden) {
    [self showStuff];
    currentlyHidden = NO;
  } else {
    [self hideStuff];
    currentlyHidden = YES;
  }
}

Кроме того, поскольку это определенно зависит от того, как настроены ваши перья и т. Д., Я публикую проект в Интернете, чтобы вы могли его скачать и посмотреть. Это довольно минимальная демонстрация, просто проект, основанный на навигации, где делегат устанавливает контроллер вкладок и встраивает контроллер представления из основного пера. Остальное находится в кончике и классе RootViewController. Полосы переключаются при каждом касании, поэтому просто коснитесь экрана. Очевидно, что в реальном приложении вам может понадобиться настроить вид прокрутки, чтобы содержимое не перескочило.

3 голосов
/ 20 июля 2009

Вы установили свойство hidesBottomBarWhenPushed контроллера просмотра на YES? Вы должны установить это в вашем initWithNibName:bundle: или initWithCoder: методе. Когда его толкают на контроллер Nav, это должно скрыть панель вкладок и заставить представление контента расширяться вниз.

2 голосов
/ 03 октября 2010

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

2 голосов
/ 19 июля 2009

Может быть, есть другой вид, который является встроенной частью области панели вкладок? То есть что-то дополнительное, чтобы скрыть. Это поможет вам увидеть, какие взгляды вокруг.

for (UIView *viewy in [self.navigationController.view subviews])
{
    NSLog([viewy description]);
}
1 голос
/ 12 ноября 2014

У меня была похожая проблема. Как упоминал Гарри, это причина того, что Navigation Controller является внутренним контроллером Tab Bar Controller. Нашел другой способ, как перерисовать ваше представление и иметь правильный кадр. В вашем контроллере добавьте следующее:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // Here you can make your tabBarControlelr.view.hidde = true or use any animation that hides UITabBar. I made
    [TabBarController setTabBarHidden:YES];

    self.navigationController.view.frame = CGRectMake(self.navigationController.view.frame.origin.x, self.navigationController.view.frame.origin.y, self.navigationController.view.frame.size.width, self.navigationController.view.frame.size.height + 50);
    [self.navigationController.view setNeedsLayout];

 }

А вот как я это скрываю. Я могу сделать это напрямую, вызывая метод TabBarControlelr или обертку метода класса:

+ (void)setTabBarHidden:(BOOL)hidden
{
    AppDelegate *delegate = [UIApplication sharedApplication].delegate;
    TabBarController *tabBarController = (TabBarController *) delegate.window.rootViewController;

    if ([tabBarController isKindOfClass:[TabBarController class]]) {
        [tabBarController setTabBarHidden:hidden];
    }
}


- (void)setTabBarHidden:(BOOL)hidden
{
    if (self.tabBar.hidden == hidden) {
        return;
    }

    if (hidden == NO) {
        self.tabBar.hidden = hidden;
    }

    [UIView animateWithDuration:0.15 animations:^{
        self.tabBar.frame = CGRectOffset(self.tabBar.frame, 0, ( hidden ? 50 : -50 ));
    } completion:^(BOOL finished) {
        self.tabBar.hidden = hidden;
    }];
}
1 голос
/ 20 июля 2009

Я бы переместил вид в окно, когда вы решите перейти в полноэкранный режим. например,

myView = [self.view retain];
self.view = nil;
[window addSubview:myView];

и вернуться:

[myView removeFromSuperView];
self.view = myView;
[myView release];
myView = nil;

Добавив представление в качестве дочернего элемента окна, оно может быть полностью полноэкранным и будет располагаться поверх панели вкладок.

Затем вы можете объединить это с

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:@"UIDeviceOrientationDidChangeNotification" object:nil];

для обнаружения вращения. (Я думаю, что вы комбинируете это с view.transform = CGAffineTransformMakeRotation, чтобы заставить его вращаться ...?)

1 голос
/ 20 июля 2009

Попробуйте сделать так, чтобы представление TabBarControllers было больше экрана, чтобы панель вкладок была скрыта за пределами экрана, если вы сделаете это до нового ViewController, то его вид изменится, чтобы заполнить новый кадр!

В моем тесте я использовал метод tabBarController: shouldSelectViewController: делегат, чтобы проверить, какой контроллер представления должен стать текущим, и соответственно установить TabBarController.view.frame. Например:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    if( viewController == second)
        tabBarController.view.frame = CGRectMake( 0, 20, 320, 500);
    else
        tabBarController.view.frame = CGRectMake( 0, 20, 320, 460);
}

Если это все еще не совсем то, что вам нужно, попробуйте заглянуть в свойство hidesBottomBarWhenPressed объекта UIViewController. Если установлено значение yes, нижняя панель будет скрыта, если контроллер помещен в стек навигации.

1 голос
/ 20 июля 2009

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

0 голосов
/ 15 декабря 2011

Поместите код для подготовки к следующему переходу, у меня отлично работает:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"ViewPhoto"]) {

    ImageView *vc = [segue destinationViewController];

    NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];

        NSString *Title = [photoNames objectAtIndex:selectedIndex];
        [vc setSelectedTitle:[NSString stringWithFormat:@"%@", Title]];

        vc.hidesBottomBarWhenPushed = YES;

        }
    }
...