2016-05-13 2 views
7

Мы столкнулись с этой проблемой при внедрении интерактивного увольнения контроллера модального представления (перетаскивание модального вниз должно отклонить его) через UIPercentDrivenInteractiveTransition.Сбой при интерактивном отклонении модального

Установка:

  1. установки UIViewController встроенный в UINavigationController по меньшей мере одной кнопки в UINavigationBar
  2. модально представить другой UIViewController встроенный в UINavigationController, по крайней мере, одна кнопка в UINavigationBar
  3. установки UIPanGestureRecognizer на modaly представлены UINavigationController наводнение UIPercentDrivenInteractiveTransition
  4. перетащить модальный do шп «держит» его точкой на UINavigationBar

Издания:

  • , медленно тянет вниз, анимацию глюков вызывая модальный вид прыгать вверх и вниз

  • глюк появляется только тогда, когда:

    1. оба UINavigationBar s имеют по крайней мере одну кнопку на них
    2. вы "держать" модальный точкой на UINavigationBar

Minimal, например, может быть загружен с github repo.

Неужели кто-нибудь сталкивается с такой проблемой? Есть ли обходные пути? Есть ли недостатки в нашей установке?

Update

Проблема была смоделирована на управлении проектом выше на iPhone 5 тренажере с iOS 9.3, OSX 10.11.4, скомпилированные с Xcode 7.3.1.

Update 2

Дальнейшие исследования показали, что этот вопрос, вероятно, не в анимации: По какой-то причине в данной установке pan.translationInView(view) возвращает неожиданные значения, которые вызывают анимацию прыгать.

Частичное Обойти

Основываясь на идее Владимира мы частично исправили проблему путем переопределения hitTest метод UINavigationBar:

class DraggableNavigationBar: UINavigationBar { 

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { 
     guard let view = super.hitTest(point, withEvent: event) else { return nil } 

     if view is UIControl || pointIsInsideNavigationButton(point) { 
      return view 
     } else { 
      return nil 
     } 
    } 

    private func pointIsInsideNavigationButton(point: CGPoint) -> Bool { 
     return subviews 
      .filter { $0.frame.contains(point) } 
      .filter { String($0.dynamicType) == "UINavigationItemButtonView" } 
      .isEmpty == false 
    } 
} 
+0

Работы для меня. Невозможно увидеть какие-либо сбои на моем iPhone 6 или в iOS Simulator для iPhone 6. –

+0

НЕТ проблемы в выше code.work, например, чары – iMHitesh

+0

могут поделиться точной проблемой со мной. Какой тип ОС и версия xCode и цель развертывания и т. Д. – iMHitesh

ответ

1

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

Если переопределить hitTest метод UINavigationBar вы можете избавиться от этой проблемы, когда вы перетаскивание модальности, держась UINavigationBar:

extension UINavigationBar { 

    override public func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { 

     guard let view = super.hitTest(point, withEvent: event) else { return nil } 

     if view.isKindOfClass(UIControl) { 
      return super.hitTest(point, withEvent: event) 
     } else { 
      return nil 
     } 
    } 
} 

К сожалению, если вы перетащите модальным, держась UIBarButtonItem на UINavigationBar, глюк еще присутствовать ,

Вы также можете попробовать другой подход.

Как вы заметили, pan.translationInView(view) возвращает неправильные значения, которые заставляют анимацию прыгать. Вам нужно сравнить это значение с y координатой модального просмотра при перетаскивании. Вы можете получить это значение, проверяя уровень представления модального контроллера представления:

... 

let translation = pan.translationInView(view) 

if let layer = view.layer.presentationLayer() { 
      print(layer.frame.origin.y) 
} 

... 

Вы можете видеть, что, когда pan.translationInView(view) начинает показывать неправильное значение, layer.frame.origin.y все равно будут правильными в данный момент. Вы можете сравнить эти два значения и найти шаблон, когда значение неверно, и изменить его, чтобы исправить, добавив несколько точек в значение translation.y.

+0

Спасибо за идею! Я закончил переопределять 'hitTest', но также разрешил нажатия на кнопки назад (на удивление это не' UIControl'). Реагирование на разницу «перевод» и «презентационный слой» было бы довольно сложным, так как нужно было бы учитывать разные скорости перетаскивания и изменения направления. –

0

я не имею полное решение, но я был в состоянии уменьшить сбой на определенную сумму.Я мог бы воспроизвести этот вопрос на iPhone 5s с iOS 9.3.2 [перетаскивая экран вниз держа панель навигации]

Проблема, кажется, в UIView.animateWithDuration блоке DismissalAnimator. Комментируя задержку и параметры, сохраняя при этом значения по умолчанию, вы можете уменьшить прыжок в представлении. Вы также можете попробовать и проверить различный UIViewAnimationOptions, для которого вы получите минимальный прыжок.

UIView.animateWithDuration(0.3, 
     animations: { 
      dismissedView.frame = finalFrame 
     }, 
     completion: { _ in 
      let didComplete = !transitionContext.transitionWasCancelled() 
      transitionContext.completeTransition(didComplete) 
     } 
    ) 

Существует a question, который, кажется, иметь дело с таким же вопросом вы столкнулись. И ответы варьируются от отключения автоматического макета, помещая layoutIfNeeded в блок анимации [пытались, оба не работали].

+0

Спасибо за предложение. Тем не менее, изменение '.CurveLinear' заставляет анимацию десинхронизировать из движения пальца. Кроме того, учитывая, насколько конкретна эта проблема (кнопки в 'UINavigationBar', перетаскиваются по точкам в' UINavigationBar'), я не думаю, что связанный вопрос связан, но проверит его. –

Смежные вопросы