представление таблицы скользит вверх под панелью навигации, когда пользователь нажимает строку

У меня есть UINavigationController (NC), содержащий UITableViewController (TVC0). Когда пользователь нажимает на строку, он загружает UIPageViewController (PVC), который перемещается вперед и назад между другими UITableViewController (TVC1).

TVC0 отображается внутри NC (это означает, что он не прячется за панелью навигации вверху или панелью вкладок внизу). Когда он нажимает PVC, первый TVC1 появляется внутри границ панели навигации и панели вкладок. Однако, когда я прокручиваю, TVC1 внутри скрыты за панелью навигации и панелью вкладок. Я могу потянуть, чтобы открыть содержимое, но когда отпускаю, оно снова оказывается за решеткой.

Как я могу заставить все появиться между двумя полосами? Я не могу использовать раскадровку (потому что это устаревшее приложение), а опция встраивания в... недоступна.

[Редактировать]

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

[/Редактировать]

[Больше правок]

Я тестировал другую область в симуляторе iOS 6 и обнаружил, что этот пейджинг работает безупречно в iOS 6. Таким образом, проблема, которую я вижу, специфична для iOS 7.

[/Еще править]

Вот мой TVC0 viewDidLoad, PVC pageViewController:viewControllerBeforeViewController: и помощник viewControllerAtIndex::

- (void) viewDidLoad
{
    [super viewDidLoad];
    NSDictionary* options = [NSDictionary dictionaryWithObject:
                             [NSNumber numberWithInteger: UIPageViewControllerSpineLocationMin]
                                                        forKey:
                             UIPageViewControllerOptionSpineLocationKey];
    self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:
                           UIPageViewControllerTransitionStyleScroll
                                                          navigationOrientation:
                           UIPageViewControllerNavigationOrientationHorizontal
                                                                        options: options];

    self.pageController.dataSource = self;
    self.pageController.view.frame = self.view.frame;
    NSArray* viewControllers =
            [NSArray arrayWithObject: [self viewControllerAtIndex: self.initialIndex]];

    [self.pageController setViewControllers: viewControllers
                                  direction: UIPageViewControllerNavigationDirectionForward
                                   animated: NO
                                 completion: nil];

    [self addChildViewController: self.pageController];
    [self.view addSubview: self.pageController.view];
    [self.pageController didMoveToParentViewController: self];

    for (UIGestureRecognizer* recognizer in self.pageController.gestureRecognizers)
    {
        if ([recognizer isKindOfClass: [UITapGestureRecognizer class]])
        {
            recognizer.enabled = NO;
        }
    }
}

// SearchResultsList is TVC1
- (SearchResultsList*) viewControllerAtIndex: (NSUInteger) index
{
    if (index >= self.items.count)
    {
        return nil;
    }

    SearchResultsList* retVal = [[SearchResultsList alloc]
                                    initWithNibName: @"SearchResultsList" bundle: nil];

    MyListItem* myItem = [self.items objectAtIndex: index];
    MyMatchesRequest* matches = [[MyMatchesRequest alloc] initWithItemId: myItem.itemId];
    [matches execute: ^(MySearchResults* results)
     {
         retVal.tableData = [NSMutableArray arrayWithArray: results.items];
         retVal.view.frame = self.view.frame;
         retVal.myItem = myItem;
         retVal.index = index;
         self.title = myItem.displayText;
         [[retVal tableView] reloadData];
     }];

    return retVal;
}

- (UIViewController*) pageViewController: (UIPageViewController*) pageViewController
      viewControllerBeforeViewController: (UIViewController*) viewController
{
    SearchResultsList* vc = (SearchResultsList*)viewController;
    if (vc.index == 0)
    {
        [self.navigationController popViewControllerAnimated: YES];
        return nil;
    }

    return [self viewControllerAtIndex: vc.index - 1];
}

person kwiqsilver    schedule 02.01.2014    source источник
comment
Autolayout ON или OFF для каждого из этих viewController?   -  person foundry    schedule 05.01.2014
comment
@foundry: выкл. Пробовал оба способа, ничего не помогает.   -  person kwiqsilver    schedule 07.01.2014
comment
У меня была точно такая же проблема, и это стоило мне +100 вознаграждений, но я заработал: stackoverflow.com/questions/20258933/. В основном то, что говорит Ник Глассо, работает. У вас также есть UINavigationBar на этом экране. Если вы видите, можете ли вы изменить Opaqueness. Если он не просвечивает, похоже, эта проблема также решается.   -  person logixologist    schedule 07.01.2014


Ответы (3)


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

self.pageViewController.definesPresentationContext = YES; 

 viewControllerWhichIsApageInPageController.modalPresentationStyle = UIModalPresentationCurrentContext
person Jef    schedule 11.01.2014

Ваш код кажется немного запутанным. Вы говорите, что это viewDidLoad вашего контроллера представления страницы, но он создает новый PVC и добавляет его в качестве дочернего контроллера представления себе в качестве родителя. Если вы действительно делаете это, вы создаете PVC внутри другого PVC. Я сомневаюсь, что это то, что вы хотите.

Этот код действительно принадлежит TVC0, который вызывает PVC, когда пользователь нажимает на строку. Этот вызов не будет корректным в viewDidLoad, но может хорошо подойти для метода didSelectRowAtIndexPath. Вместо того, чтобы вводить его в качестве дочернего контроллера, мы можем просто поместить его в стек нашего навигационного контроллера. (Я ожидаю, что вы все равно делаете это в своем внешнем PVC).

Но на всякий случай я бы убрал эти три строчки:

    [self addChildViewController: self.pageController];
    [self.view addSubview: self.pageController.view];
    [self.pageController didMoveToParentViewController:self];

и заменить их на

    [self.navigationController pushViewController:self.pageController 
                                         animated:YES];

(это вызывается из вашего TVC0 - весь код, который вы показали, может жить в TVC0)

Затем, чтобы предотвратить поведение, которое вы описываете, при создании UINavigationController должно быть достаточно установить для свойства translucent его navigationBar значение NO.

обновить

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

Причина «подпрыгивания» ясна. Если у вас есть полупрозрачный navBar, и его automaticallyAdjustsScrollViewInsets установлено в YES, в определенных ситуациях это может привести к тому, что приватное подпредставление pageViewController (_UIQueuingScrollView) установит его contentOffset.y на -64, когда pageViewController сначала загрузился. Однако, как только pageVC получает возможность обновить себя (например, смахиванием или другим жестом касания), он сбрасывает свое внутреннее состояние подпредставлений, теряя этот мошеннический контентOffset. Поэтому, когда вы касаетесь первой страницы, она подпрыгивает. Где он потом остается. Это может считаться ошибкой, хотя это может быть результатом неправильного использования pageViewController.

Просто установка automaticallyAdjustsScrollViewInsets на НЕТ не излечит ваши болезни, так как тогда все ваши страницы будут располагаться за навигационной панелью. Что вам нужно сделать, так это настроить рамку самого pageViewController.

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

  • если вы можете установить для свойства translucent панели навигации ваших навигационных контроллеров значение NO, проблема должна исчезнуть.

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

  • загрузка pageViewController в качестве дочернего элемента tableViewController и превращение его в подпредставление tableView — очень странный способ, который, несомненно, усугубляет ваши проблемы.

  • В viewControllerBeforeViewController дочерний элемент pageViewController, кажется, выталкивает его parentViewController (tableViewController) - так что вы никогда не увидите его содержимое таблицы? Либо в приложении есть более важные детали, либо вы неточно его описали.

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

person foundry    schedule 07.01.2014
comment
@kwiqsilver - если этот код уже находится в viewDidLoad TVCO, я не совсем понимаю, как TVCO «подталкивает PVC, as you are adding it as a child on viewDidLoad. In terms of your problem, either way should work - the essence is to set translucent» к NO на панели навигации вашего навигационного контроллера. Но я могу воспроизвести проблему точно так, как вы ее описываете, если я использую pushViewController вместо родитель/потомок. - person foundry; 07.01.2014
comment
Я попробовал это, и все, что он сделал, это сделать содержимое моего контроллера просмотра страницы пустым. - person kwiqsilver; 10.01.2014
comment
@kwiqsilver, вы пытались просто изменить свойство translucent панели навигации на НЕТ? (больше ничего не меняя) - person foundry; 11.01.2014

person    schedule
comment
Все, что нужно сделать, это скрыть верхний элемент табличного представления за панелью навигации. - person kwiqsilver; 10.01.2014
comment
Работает для меня, спасибо. Все еще необходимо в iOS9 и iOS10 с UIPageViewController и NavigationBar: первое изображение было смещено по вертикали, коснитесь его, и оно скользнуло на место. ContentOffset _UIQueueingScrollView был неверным, пока представление не было затронуто. - person ghr; 19.12.2016