2016-05-13 13 views
7

Wir haben dieses Problem bei der Implementierung interaktiver Entlassung eines Modal-View-Controllers (Ziehen von Modal-Down sollte es entlassen) über UIPercentDrivenInteractiveTransition.Glitch bei interaktivem Löschen von Modal

Setup:

  1. Setup UIViewController in UINavigationController eingebettet mit mindestens einer Taste in UINavigationBar
  2. modal weiteren zur Zeit UIViewController eingebettet in UINavigationController mit mindestens einer Taste in UINavigationBar
  3. Setup UIPanGestureRecognizer auf modaly präsentiert UINavigationController fahren UIPercentDrivenInteractiveTransition
  4. ziehen modal do wn "Betrieb" durch Punkt auf UINavigationBar

Ausgabe:

  • , während sie langsam nach unten ziehen, Animation Glitches modale Ansicht verursacht springen auf und ab

  • Glitch nur angezeigt, wenn:

    1. beide UINavigationBar s haben mindestens einen Knopf auf ihnen
    2. Sie "halten" durch den Punkt modal auf UINavigationBar

Minimal Beispiel aus github repo heruntergeladen werden.

Hat jemand über ein solches Problem kommen? Gibt es Workarounds? Gibt es einen Fehler in unserem Setup?

aktualisiert

Ausgabe hat mit iOS 9.3, auf laufende Projekt über auf iPhone 5-Simulator simuliert OSX 10.11.4, 7.3.1 mit Xcode zusammengestellt.

Update 2

Weitere Untersuchungen zeigten, dass Problem wahrscheinlich nicht in der Animation ist: Aus irgendeinem Grunde in bestimmten Setup pan.translationInView(view) unerwartete Werte zurückgibt, die Animation zu springen verursacht.

Teil Abhilfe

Basierend auf Wladimirs Idee, die wir teilweise das Problem behoben durch zwingende hitTest Methode der 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

Funktioniert für mich. Kann keine Störungen entweder auf meinem iPhone 6 oder in dem iOS-Simulator für iPhone 6 sehen. –

+0

KEIN Problem in oben code.work mag Charme – iMHitesh

+0

kann genaues Problem mit mir teilen. Welches OS-Typ und xCode-Version und Aufstellungsziel usw. – iMHitesh

Antwort

1

Sehr interessante Glitch. Ich habe vor einigen Tagen eine Teillösung für dieses Problem gefunden, und da niemand eine vollständige Lösung gefunden hat, werde ich das hier posten, vielleicht wird es hilfreich sein.

Wenn Sie hitTest Methode von UINavigationBar außer Kraft setzen können Sie loswerden dieses Problem, wenn Sie modal hinzieht UINavigationBar indem:

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 
     } 
    } 
} 

Leider wenn Sie, indem auf UIBarButtonItem auf UINavigationBar modal ziehen, Glitch noch vorhanden sein .

Sie können auch einen anderen Ansatz versuchen.

Wie Sie bemerkt haben, gibt pan.translationInView(view) falsche Werte zurück, wodurch die Animation springt. Sie müssen diesen Wert mit y Koordinate der modalen Ansicht beim Ziehen vergleichen. Sie können diesen Wert erhalten, indem Präsentationsschicht der Modal-View-Controller überprüft:

... 

let translation = pan.translationInView(view) 

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

... 

Sie können sehen, dass, wenn pan.translationInView(view) beginnt falschen Wert zu zeigen, layer.frame.origin.y wird noch in diesem Augenblick richtig sein. Sie können diese beiden Werte vergleichen und das Muster finden, wenn der Wert inkorrekt ist, und ihn durch Hinzufügen einiger Punkte zum translation.y Wert korrigieren.

+0

Danke für die Idee! Am Ende habe ich "hitTest" außer Kraft gesetzt, aber auch erlaubt, auf Back-Buttons zu tippen (überraschenderweise sind sie nicht "UIControl"). Auf den Unterschied zwischen Translation und PresentationLayer zu reagieren, wäre ziemlich schwierig, da man unterschiedliche Ziehgeschwindigkeiten und Richtungsänderungen berücksichtigen müsste. –

0

ich keine vollständige Lösung, aber ich konnte das reduzieren, Glitch um einen bestimmten Betrag.Ich kann dieses Problem auf dem iPhone 5s reproduzieren mit iOS 9.3.2 [durch den Bildschirm halte Navigationsleiste nach unten ziehen]

Das Problem scheint in dem UIView.animateWithDuration Block DismissalAnimator zu sein. Durch Auskommentieren der Verzögerung und der Optionen, d. H. Halten sie auf die Standardwerte, können Sie das Springen der Ansicht reduzieren. Sie könnten auch versuchen, nach verschiedenen UIViewAnimationOptions zu suchen, für die Sie minimalen Sprung bekommen.

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

Es gibt a question, die mit dem gleichen Problem zu tun haben scheint, dass Sie konfrontiert sind. Und die Antworten variierten von der Deaktivierung des automatischen Layouts, layoutIfNeeded in Animationsblock setzen [versuchte, beide nicht funktioniert].

+0

Danke für den Vorschlag. Wenn Sie jedoch ".CurveLinear" ändern, wird die Animation durch die Fingerbewegung desynchronisiert. Auch, wie spezifisch dieses Problem ist (Schaltflächen in 'UINavigationBar', Ziehen nach Punkt in' UINavigationBar') denke ich nicht, dass verknüpfte Frage verwandt ist, aber es auschecken wird. –

Verwandte Themen