it-roy-ru.com

Контент помещается в UIPageViewController с помощью UINavigationController

ОБНОВЛЕНИЕ 2

Я запускаю и тестирую свое приложение в iOS Simulator на 4-дюймовом устройстве. Если я использую 3,5-дюймовое устройство, ярлык не прыгает. В моем .xib, в разделе «Имитированные метрики», он установлен как Retina 4-дюймовый полноэкранный режим. Есть идеи, почему я вижу эту проблему только на 4-дюймовом устройстве?

ОБНОВЛЕНИЕ 1

В IB, если я выберу «Панель навигации» в Simulated Metrics, мой ярлык все равно подскочит. Единственный способ заставить мой ярлык правильно отображаться на первом экране - это не устанавливать контроллер навигации в качестве корневого контроллера моего окна.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Для rootViewController моего окна задается UINavigationController, в rootViewController которого встроен UIPageViewController.

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

uipageviewcontroller with navigationcontroller

В моем приложении Delegate:

self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[ContainerViewController new]];

В ContainerViewController:

- (void)viewDidLoad {

    [super viewDidLoad];

    self.pvc = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
                                               navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                                                             options:nil];
    self.pvc.dataSource = self;
    self.pvc.delegate = self;
    DetailViewController *detail = [DetailViewController new];
    [self.pvc setViewControllers:@[detail]
                       direction:UIPageViewControllerNavigationDirectionForward
                        animated:false
                      completion:nil];

    [self addChildViewController:self.pvc];
    [self.view addSubview:self.pvc.view];
    [self.pvc didMoveToParentViewController:self];
}
59
djibouti33

Поэтому я добавляю еще один ответ после дальнейшего развития и, наконец, думаю, что выяснил, что происходит. Похоже, что в iOS7, UIPageViewController имеет свой собственный UIScrollView. Из-за этого вы должны установить для automaticallyAdjustsScrollViewInsets значение false. Вот мой viewDidLoad сейчас:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.automaticallyAdjustsScrollViewInsets = false;

    DetailViewController *detail = [[DetailViewController alloc] init];
    [self setViewControllers:@[detail]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:false
                  completion:nil];
}

Нет необходимости помещать что-либо в viewWillLayoutSubviews (как предложил один из моих предыдущих ответов).

83
djibouti33

Это определенно вызвано automaticallyAdjustsScrollViewInsets, как и другие авторы (включая @ djibouti33). Однако это свойство странно в двух отношениях:

  1. Он должен быть установлен на UINavigationController. Если вы установите его на дочерний контроллер, управляемый UINavigationController, это не будет иметь никакого эффекта. 1
  2. Это применимо, только когда представление прокрутки находится в нулевом индексе в подпредставлениях контроллера. 2

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

TLDR: Обходной путь, с которым я пошел, - это добавление фиктивного представления к UIPageViewController с нулевым индексом, чтобы избежать применения параметра к scrollView в контроллере страницы, например так:

pageViewController.view.insertSubview(UIView(), atIndex: 0) // Swift

[pageViewController.view insertSubview: [UIView new] atIndex: 0]; // obj-c

Лучше было бы установить contentInset в представлении прокрутки самостоятельно, но, к сожалению, UIPageViewController не предоставляет представление прокрутки.

22
John Gibb

Просто снимите флажок Under Top Bars для обоих: UIPageViewController и вашего пользовательского PageContentViewController:

 enter image description here

11
Bartłomiej Semańczyk

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

Используя следующую иерархию viewController:

-- UINavigationController
  -- MyPageViewController
    -- MyDetailViewController

Вот что я сделал, чтобы решить это:

В MyPageViewController.m

@interface MyPageViewController () <delegates>
  @property (strong) MyDetailViewController *initialViewController;
@end

- (void)viewDidLoad
{
    ...

    // set this once, because we're going to use it in viewWillLayoutSubviews,
    // which gets called multiple times
    self.initialViewController = [MyDetailViewController new];
}

// the problem seemed to stem from the fact that a pageViewController couldn't
// properly lay out it's child view controller initially if it contained a 
// scroll view. by the time we're in layoutSubviews, pageViewController seems to
// have gotten it's bearings and everything is laid out just fine.
- (void)viewWillLayoutSubviews
{
    [self setViewControllers:@[self.initialViewController]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:false
                  completion:nil];
}
4
djibouti33

Попробуйте снять эти 2 опции на вашей раскадровке

 enter image description here

3
apinho

У меня та же проблема. Я решаю это, помещая setViewControllers для первой страницы в viewDidLoad UIPageViewController вместо того, чтобы устанавливать его при создании экземпляра UIPageViewController. Кроме того, мне нужно автоматически установить ADJUSTSScrollViewInsets в NO.

3
howa

У меня была похожая проблема, но ни одно из решений здесь не помогло. Моя проблема заключалась в том, что всякий раз, когда я переходил на следующую страницу, контент прыгал вниз, заканчиваясь в правильном положении, но начиная с 20 пикселей слишком высоко (явно что-то связанное со строкой состояния). Мой контейнер VC не был навигационным VC. После того, как я на время выдернул волосы, решение, которое оказалось для меня полезным, состояло в том, чтобы просто убедиться, что ни одно из ограничений в моем контенте VC не было связано с верхним руководством по макету. Это может или не может быть осуществимо в вашем случае, но по моему это было, и это было единственное, что решило скачок контента. Также очень любопытно, что эта проблема проявлялась только тогда, когда стиль перехода был установлен на прокрутку. Просто изменив его на скручивание страницы, проблема исчезла. Но мне нужен был свиток. Надеюсь, это поможет кому-то еще.

3
Danny

Попробуйте выбрать UIPageViewController в раскадровке и снимите флажки «Под нижними полосами» и «Под непрозрачными полосами» в Инспекторе атрибутов.

1
acid beast

Ничто из вышеперечисленного не помогло мне 

Здесь я нашел решение

var pageMenu : CAPSPageMenu?

Вместо добавления, как это

self.view.addSubview(pageMenu!.view)

Добавьте ваш CAPSPageMenu, как показано ниже

addChildViewController(pageMenu!) 
self.view.addSubview(pageMenu!.view) 
pageMenu!.didMove(toParentViewController: self)

Ссылка: iOS Swift: SlidingMenuView Неправильная позиция после представления imagePicker

Удачного кодирования!

0
Sanju

Как сказано в «Bo:»: Положить self.edgesForExtendedLayout = UIRectEdgeNone; в viewDidLoad MyPageViewController решил проблему. Бо

0
osxdirk

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

  • Для каждой страницы содержимого, которая должна отображаться в UIPageViewController, найдите самое верхнее ограничение, которое находится между верхней частью вида и нижней частью верхнего руководства по макету, и добавьте выход для него в контроллер представления.
  • В каждом контроллере представления с такой розеткой добавьте другое свойство для предпочтительного верхнего расстояния. Эти два выхода выглядят так (на Swift):

    @IBOutlet weak var topGuideConstraint: NSLayoutConstraint!
    var topDistance: CGFloat!
    
  • В viewDidLoad() установите для topDistance значение, назначенное ограничению в раскадровке:

    override func viewDidLoad() {
        super.viewDidLoad()
        topDistance = topGuideConstraint.constant
    }
    
  • В viewWillLayoutSubviews() убедитесь, что ограничение имеет правильное значение, корректируя высоту строки состояния, когда topLayoutGuide.length равен нулю, что похоже на случай во время перехода , но не после его завершения: 

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        topGuideConstraint.constant = topDistance + (
            topLayoutGuide.length == 0
                ? UIApplication.sharedApplication().statusBarFrame.size.height
                : 0
        )
    }
    

Повторите эти действия для каждого контроллера представления содержимого, отображаемого в UIPageViewController. Отрегулируйте смещение соответствующим образом, если вы также отображаете UINavigation bar.

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

0
theory

Версия ответа Джибути33 Свифта (за исключением строки, которая не является частью решения проблемы)

Swift 3.0

override func viewDidLoad() {
    super.viewDidLoad()
    self.automaticallyAdjustsScrollViewInsets = false
}
0
Kqtr

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

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

Я не уверен, как вы инициализируете свой фрейм для своего контроллера детального просмотра, но я предполагаю, что вы могли бы использовать: self.view.frame.size.height;

попробуйте использовать: self.view.frame.size.height - = self.navigationController.navigationBar.bounds.size.height;

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

0
CalebDavis

Как @ djibouti33 уже опубликовано: 

pageViewController не может правильно выложите его дочерний контроллер вида изначально, если он содержал просмотр прокрутки. к тому времени, когда мы находимся в layoutSubviews, pageViewController, кажется, уже получил свои ориентиры, и все выложено просто отлично

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

override func viewDidLoad() {
    super.viewDidLoad()
    self.pageViewController = self.storyboard?.instantiateViewController(withIdentifier: "yourPageViewController") as? UIPageViewController       
    self.pageViewController?.dataSource = self

    pageViewController?.automaticallyAdjustsScrollViewInsets = false    
    self.pageViewController?.view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.height)       
    self.addChildViewController(self.pageViewController!)        
    self.view.addSubview((self.pageViewController?.view)!)       
    self.pageViewController?.didMove(toParentViewController: self)
}


override func viewDidLayoutSubviews() {
    let startVC = self.viewControllerAtIndex(index: 0) as infoDataViewController     
    let viewControllers = NSArray(object: startVC)    
    self.pageViewController?.setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: true, completion: nil)
}
0
QitVision

Первоначально моя иерархия контроллера вида выглядела так:

-- UINavigationController
  -- MyContainerViewController
    -- UIPageViewController
      -- MyDetailViewController

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

-- UINavigationController
  -- MyPageViewController
    -- MyDetailViewController

MyPageViewController управляет его toolbar, и все работает как положено, как на 4-дюймовом, так и на 3,5-дюймовом устройстве.

0
djibouti33