Не совсем var_dump
, но полезно: http://dbug.ospinto.com/
Решено следующее: 1- Объявить флаг, указывающий, что анимация завершена или нет:
BOOL pageAnimationFinished;
2- Установите для этого флага значение true в viewDidLoad:
pageAnimationFinished = YES;
3- Отключить tapGesture для pageViewController и назначить 'self' делегату panGestureRecognizer:
for (UIGestureRecognizer * gesRecog in self.pageViewController.gestureRecognizers)
{
if ([gesRecog isKindOfClass:[UITapGestureRecognizer class]])
gesRecog.enabled = NO;
else if ([gesRecog isKindOfClass:[UIPanGestureRecognizer class]])
gesRecog.delegate = self;
}
4- Разрешить / Запретить panGestureRecognizer через следующий метод делегирования распознавателя жестов:
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ([gestureRecognizer.view isEqual:self.view] || [gestureRecognizer.view isEqual:self.pageViewController.view]))
{
UIPanGestureRecognizer * panGes = (UIPanGestureRecognizer *)gestureRecognizer;
if(!pageAnimationFinished || (currentPage < minimumPage && [panGes velocityInView:self.view].x < 0) || (currentPage > maximumPage && [panGes velocityInView:self.view].x > 0))
return NO;
pageAnimationFinished = NO;
}
return YES;
}
5- Добавьте следующий метод делегатаViewController:
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
pageAnimationFinished = YES;
}
Вышеуказанные ответы были правильными, но я считаю более сложными, чем это необходимо, и кулинарная книга полезна. Итак, вот что, кажется, работает для меня:
В контроллере представления, который устанавливает и вызывает pageViewController, объявляет:
@property (assign) BOOL pageIsAnimating;
и в viewDidLoad:
pageIsAnimating = NO;
добавьте это:
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
pageIsAnimating = YES;
}
и добавьте пару строк:
- (void)pageViewController:(UIPageViewController *)pageViewController
didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers
transitionCompleted:(BOOL)completed {
if (completed || finished) // Turn is either finished or aborted
pageIsAnimating = NO;
...
}
Жесты подавляются путем отказа от предоставления информации о контроллере просмотра:
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController {
if (pageIsAnimating)
return nil;
...
return after;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController {
if (pageIsAnimating)
return nil;
...
return before;
}
Ох, а изменения ориентации сбросят флаг:
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation {
pageIsAnimating = NO;
...
}
Я попытаюсь проигнорировать жест в UIPageViewControllers во время перехода.
Мое решение в быстром, простом и рабочем:
extension MyPageVC: UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
self.view.isUserInteractionEnabled = false
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
self.view.isUserInteractionEnabled = true
}
}
Хороший ответ из Basem Saadawy, но он имеет некоторый дефект.
На самом деле, вызов делегатаRecognizerShouldBegin: может быть вызван без дальнейшей анимации. Это возможно, если вы начинаете свой жест движением вертикального пальца, а его горизонтальное смещение недостаточно для запуска анимации (но этого достаточно, чтобы запустить gestureRecognizerShouldBegin: ). Таким образом, наша переменная pageAnimationFinished будет установлена в NO без реальной анимации. Поэтому pageViewController: didFinishAnimating: никогда не будет вызываться, и вы можете заблокировать текущую страницу без возможности ее изменения.
Вот почему лучше назначить NO этой переменной - это метод действия распознавателя жестов с экзаменом (нас интересует только горизонтальное направление).
Итак, последние шаги:
1) Объявить переменную экземпляра (флаг):
BOOL pageAnimationFinished;
2) Задайте свое начальное значение
- (void)viewDidLoad
{
[super viewDidLoad];
...
pageAnimationFinished = YES;
}
3) Назначьте делегат и пользовательское действие распознающим жестам
for (UIGestureRecognizer * gesRecog in self.pageViewController.gestureRecognizers)
{
if ([gesRecog isKindOfClass:[UIPanGestureRecognizer class]])
{
gesRecog.delegate = self;
[gr addTarget:self action:@selector(handlePan:)];
}
}
3 ') Анимация действительно начинается, когда перевод жестов больше в горизонтальном направлении, и палец движется горизонтально в одно мгновение. Я предполагаю, что одна и та же логика используется во внутреннем распознавателе, назначаемом UIPageViewController .
- (void) handlePan:(UIPanGestureRecognizer *)gestureRecognizer
{
if (pageAnimationFinished && gestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint vel = [gestureRecognizer velocityInView:self.view];
CGPoint tr = [gestureRecognizer translationInView:self.view];
if (ABS(vel.x) > ABS(vel.y) && ABS(tr.x) > ABS(tr.y))
pageAnimationFinished = NO; // correct place
}
}
4) Запрет жестов, если анимация еще не закончена.
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ([gestureRecognizer.view isEqual:self.view] || [gestureRecognizer.view isEqual:self.pageViewController.view]))
{
UIPanGestureRecognizer * panGes = (UIPanGestureRecognizer *)gestureRecognizer;
if(!pageAnimationFinished || (currentPage < minimumPage && [panGes velocityInView:self.view].x < 0) || (currentPage > maximumPage && [panGes velocityInView:self.view].x > 0))
return NO;
}
return YES;
}
5) Анимация закончена
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
pageAnimationFinished = YES;
}
Я слишком много играл с ней и, похоже, это хорошее решение, которое хорошо работает.
Как насчет этого:
- (void)pageViewController:(UIPageViewController*)pgVC willTransitionToViewControllers:(NSArray*)pendingVCs
{
pgVC.dataSource = nil; // ... to disallow user to change pages until animation completes
}
- (void)pageViewController:(UIPageViewController*)pgVC
didFinishAnimating:(BOOL)finished
previousViewControllers:(NSArray*)prevVCs
transitionCompleted:(BOOL)completed
{
if(completed || finished) {
pgVC.dataSource = _pgViewDataSource; // ... to allow user to change pages again
}
}
Вот версия Swift версии Билла Чесвика (в настоящее время главный ответ):
Добавьте переменную, чтобы удерживать текущее состояние:
var pageIsAnimating = false
Установите анимационное состояние:
func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) {
self.pageIsAnimating = true
}
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if finished || completed {
self.pageIsAnimating = false
}
}
Заблокировать переходы, если он в настоящее время оживляет:
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
if self.pageIsAnimating {
return nil
}
// Your code here
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
if self.pageIsAnimating {
return nil
}
// Your code here
}
Спасибо, Билл Чесвик!
добавьте этот код (убедитесь, что вы включили UIPageViewControllerDelegate в свой заголовок или расширение класса и назначили self.pageViewController.delegate = self;
):
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
self.pageAnimationFinished = NO;
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
self.pageAnimationFinished = YES;
}
, затем проверьте self.pageAnimationFinished
и верните нуль, если это == NO
.
Дольше Объяснение:
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
Мы можем использовать этот метод делегата из UIPageViewControllerDelegate
знать, когда анимация перелистывает или проскакивает через страницы. Используя это, мы можем реализовать это следующим образом:
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
pageAnimationFinished = YES;
}
, тогда просто верните nil
в свои
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(PageViewController *)viewController
и
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(PageViewController *)viewController
когда
pageAnimationFinished == NO
. Обязательно установите pageAnimationFinished
на NO
, когда вы живете. Лучший способ узнать, когда вы живете, - это использовать противоположность
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
, а именно:
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
С тех пор я не видел этого предупреждения, и это можно сделать в 1/3 линии, как и другие решения. И намного проще следовать.
Используйте методы UIPageViewControllerDelegate и настройте защиту, чтобы предотвратить создание новых просмотров страниц при обнаружении чрезмерных поворотов страниц.
Мне пришлось добавить его в viewDidAppear: чтобы он работал
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.pageAnimationFinished = YES;
}