Kann mir jemand sagen, wie ich das untere Blatt in der neuen Maps-App in iOS 10 nachahmen kann?
In Android können Sie ein verwenden BottomSheet
, das dieses Verhalten nachahmt, aber ich konnte so etwas für iOS nicht finden.
Ist das eine einfache Bildlaufansicht mit einem eingefügten Inhalt, sodass sich die Suchleiste unten befindet?
Ich bin ziemlich neu in der iOS-Programmierung. Wenn mir jemand beim Erstellen dieses Layouts helfen könnte, wäre das sehr dankbar.
Das meine ich mit "unteres Blatt":
Antworten:
Ich weiß nicht, wie genau das untere Blatt der neuen Maps-App auf Benutzerinteraktionen reagiert. Sie können jedoch eine benutzerdefinierte Ansicht erstellen, die der in den Screenshots entspricht, und sie der Hauptansicht hinzufügen.
Ich nehme an, Sie wissen wie:
1- Erstellen Sie View Controller entweder über Storyboards oder mithilfe von XIB-Dateien.
2- Verwenden Sie googleMaps oder Apples MapKit.
Beispiel
1- Erstellen Sie zwei Ansichts-Controller, z. B. MapViewController und BottomSheetViewController . Der erste Controller hostet die Karte und der zweite ist das unterste Blatt selbst.
Konfigurieren Sie MapViewController
Erstellen Sie eine Methode zum Hinzufügen der unteren Blattansicht.
Und rufen Sie es in der viewDidAppear-Methode auf:
Konfigurieren Sie BottomSheetViewController
1) Bereiten Sie den Hintergrund vor
Erstellen Sie eine Methode, um Unschärfe- und Lebendigkeitseffekte hinzuzufügen
Rufen Sie diese Methode in Ihrem viewWillAppear auf
Stellen Sie sicher, dass die Hintergrundfarbe der Ansicht Ihres Controllers clearColor ist.
2) Animieren Sie das Erscheinungsbild des unteren Blattes
3) Ändern Sie Ihre xib nach Ihren Wünschen.
4) Fügen Sie Ihrer Ansicht Pan Gesture Recognizer hinzu.
Fügen Sie in Ihrer viewDidLoad-Methode UIPanGestureRecognizer hinzu.
Und implementieren Sie Ihr Gestenverhalten:
Bildlauffähiges unteres Blatt:
Wenn Ihre benutzerdefinierte Ansicht eine Bildlaufansicht oder eine andere Ansicht ist, von der geerbt wird, haben Sie zwei Möglichkeiten:
Zuerst:
Entwerfen Sie die Ansicht mit einer Kopfzeilenansicht und fügen Sie die panGesture zur Kopfzeile hinzu. (schlechte Benutzererfahrung) .
Zweite:
1 - Fügen Sie die panGesture zur unteren Blattansicht hinzu.
2 - Implementieren Sie das UIGestureRecognizerDelegate und legen Sie den panGesture-Delegaten für den Controller fest.
3- Implementieren Sie shouldRecognizeSimultaneousWith delegate function und deaktivieren Sie die Eigenschaft scrollView isScrollEnabled in zwei Fällen:
Andernfalls aktivieren Sie das Scrollen.
HINWEIS
Wenn Sie .allowUserInteraction wie im Beispielprojekt als Animationsoption festlegen , müssen Sie das Scrollen beim Schließen der Animation aktivieren, wenn der Benutzer nach oben scrollt.
Beispielprojekt
Ich habe ein Beispielprojekt mit mehr Optionen für dieses Repo erstellt, das Ihnen möglicherweise bessere Einblicke in die Anpassung des Ablaufs gibt.
In der Demo steuert die Funktion addBottomSheetView (), welche Ansicht als unteres Blatt verwendet werden soll.
Beispielprojekt-Screenshots
- Teilansicht
- Vollansicht
- Bildlaufansicht
quelle
Ich habe eine Bibliothek basierend auf meiner Antwort unten veröffentlicht.
Es ahmt das Overlay der Shortcuts-Anwendung nach. Weitere Informationen finden Sie in diesem Artikel .
Die Hauptkomponente der Bibliothek ist die
OverlayContainerViewController
. Es definiert einen Bereich, in dem ein Ansichts-Controller nach oben und unten gezogen werden kann, um den darunter liegenden Inhalt auszublenden oder anzuzeigen.Implementieren Sie
OverlayContainerViewControllerDelegate
, um die Anzahl der gewünschten Kerben anzugeben:Vorherige Antwort
Ich denke, es gibt einen wichtigen Punkt, der in den vorgeschlagenen Lösungen nicht behandelt wird: den Übergang zwischen der Schriftrolle und der Übersetzung.
Wie Sie vielleicht bemerkt haben, gleitet
contentOffset.y == 0
das untere Blatt in Karten beim Erreichen der Tabellenansicht entweder nach oben oder nach unten.Der Punkt ist schwierig, da wir den Bildlauf nicht einfach aktivieren / deaktivieren können, wenn unsere Schwenkgeste mit der Übersetzung beginnt. Es würde die Schriftrolle stoppen, bis eine neue Berührung beginnt. Dies ist bei den meisten hier vorgeschlagenen Lösungen der Fall.
Hier ist mein Versuch, diesen Antrag umzusetzen.
Ausgangspunkt: Karten App
Um unsere Untersuchung zu beginnen, lassen Sie uns die Ansicht Hierarchie der Karten zu visualisieren (Start Maps auf einem Simulator und wählen Sie
Debug
>Attach to process by PID or Name
>Maps
in Xcode 9).Es sagt nicht, wie die Bewegung funktioniert, aber es hat mir geholfen, die Logik zu verstehen. Sie können mit dem lldb- und dem Ansichtshierarchie-Debugger spielen.
Unser View Controller stapelt sich
Erstellen wir eine Basisversion der Maps ViewController-Architektur.
Wir beginnen mit einem
BackgroundViewController
(unserer Kartenansicht):Wir haben die tableView in eine dedizierte
UIViewController
:Jetzt benötigen wir einen VC, um das Overlay einzubetten und seine Übersetzung zu verwalten. Um das Problem zu vereinfachen, können wir die Überlagerung von einem statischen Punkt
OverlayPosition.maximum
auf einen anderen verschiebenOverlayPosition.minimum
.Derzeit gibt es nur eine öffentliche Methode zum Animieren der Positionsänderung und eine transparente Ansicht:
Schließlich benötigen wir einen ViewController, um alles einzubetten:
In unserem AppDelegate sieht unsere Startsequenz folgendermaßen aus:
Die Schwierigkeit hinter der Overlay-Übersetzung
Wie übersetzen wir nun unser Overlay?
Die meisten der vorgeschlagenen Lösungen verwenden einen dedizierten Pan-Gesten-Erkenner, aber wir haben bereits einen: die Pan-Geste der Tabellenansicht. Außerdem müssen wir die Schriftrolle und die Übersetzung synchron halten und
UIScrollViewDelegate
alle Ereignisse haben, die wir brauchen!Eine naive Implementierung würde eine zweite Schwenkgeste verwenden und versuchen,
contentOffset
die Tabellenansicht zurückzusetzen, wenn die Übersetzung erfolgt:Aber es funktioniert nicht. Die tableView wird aktualisiert,
contentOffset
wenn eine eigene Pan-Gestenerkennungsaktion ausgelöst wird oder wenn der displayLink-Rückruf aufgerufen wird. Es besteht keine Chance, dass unser Erkenner direkt nach diesen ausgelöst wird, um das erfolgreich zu überschreibencontentOffset
. Unsere einzige Möglichkeit besteht darin, entweder an der Layoutphase teilzunehmen (indemlayoutSubviews
die Aufrufe der Bildlaufansicht in jedem Frame der Bildlaufansicht überschrieben werden ) oder auf diedidScroll
Methode des Delegaten zu reagieren, die bei jedercontentOffset
Änderung aufgerufen wird. Lass es uns versuchen.Die Übersetzung Implementierung
Wir fügen
OverlayVC
unserem einen Übersetzer hinzu, um die Ereignisse der Bildlaufansicht an unseren Übersetzer zu sendenOverlayContainerViewController
:In unserem Container verfolgen wir die Übersetzung anhand einer Aufzählung:
Die aktuelle Positionsberechnung sieht folgendermaßen aus:
Wir benötigen 3 Methoden, um die Übersetzung zu handhaben:
Der erste sagt uns, ob wir mit der Übersetzung beginnen müssen.
Der zweite führt die Übersetzung durch. Es verwendet die
translation(in:)
Methode der Schwenkgeste von scrollView.Der dritte animiert das Ende der Übersetzung, wenn der Benutzer seinen Finger loslässt. Wir berechnen die Position anhand der Geschwindigkeit und der aktuellen Position der Ansicht.
Die Delegiertenimplementierung unseres Overlays sieht einfach so aus:
Letztes Problem: Versenden der Berührungen des Overlay-Containers
Die Übersetzung ist jetzt ziemlich effizient. Es gibt jedoch noch ein letztes Problem: Die Berührungen werden nicht in unsere Hintergrundansicht übertragen. Sie werden alle von der Ansicht des Overlay-Containers abgefangen. Wir können nicht festlegen
isUserInteractionEnabled
,false
da dies auch die Interaktion in unserer Tabellenansicht deaktivieren würde. Die Lösung wird massiv in der Maps-App verwendetPassThroughView
:Es entfernt sich von der Responderkette.
In
OverlayContainerViewController
:Ergebnis
Hier ist das Ergebnis:
Den Code finden Sie hier .
Bitte, wenn Sie irgendwelche Fehler sehen, lassen Sie es mich wissen! Beachten Sie, dass Ihre Implementierung natürlich eine zweite Schwenkgeste verwenden kann, insbesondere wenn Sie Ihrem Overlay einen Header hinzufügen.
Update 23/08/18
Wir können ersetzen
scrollViewDidEndDragging
mitwillEndScrollingWithVelocity
anstattenabling
/disabling
Scroll , wenn der Benutzer Enden ziehen:Wir können eine Federanimation verwenden und Benutzerinteraktion während der Animation ermöglichen, um den Bewegungsfluss zu verbessern:
quelle
UIViewPropertyAnimator
(was die Fähigkeit hat anzuhalten) und dann diefractionComplete
Eigenschaft verwendet wird, um das Scrub durchzuführen.translateView(following:)
Methode berechnen Sie die Höhe basierend auf der Übersetzung, dies kann jedoch von einem anderen Wert als 0,0 ausgehen (z. B. wird die Tabellenansicht ein wenig gescrollt und die Überlagerung wird maximiert, wenn Sie mit dem Ziehen beginnen) . Das würde zum ersten Sprung führen. Sie können dies durch denscrollViewWillBeginDragging
Rückruf lösen, bei dem Sie sich an die InitialecontentOffset
der Tabellenansicht erinnern und diese für dietranslateView(following:)
Berechnung verwenden.csrutil disable && reboot
. Sie haben dann alle Befugnisse, die Ihnen root normalerweise geben sollte, einschließlich der Möglichkeit, sich an einen Apple-Prozess anzuschließen.Versuchen Sie Riemenscheibe :
https://github.com/52inc/Pulley
quelle
Sie können meine Antwort https://github.com/SCENEE/FloatingPanel versuchen . Es bietet einen Container View Controller zur Anzeige einer "Bottom Sheet" -Schnittstelle.
Es ist einfach zu bedienen und es macht Ihnen nichts aus, mit Gestenerkennern umzugehen! Bei Bedarf können Sie auch die Ansicht einer Bildlaufansicht (oder der Geschwisteransicht) in einem unteren Blatt verfolgen.
Dies ist ein einfaches Beispiel. Bitte beachten Sie, dass Sie einen View Controller vorbereiten müssen, um Ihren Inhalt in einem unteren Blatt anzuzeigen.
Hier ist ein weiterer Beispielcode zum Anzeigen eines unteren Blattes zum Suchen eines Speicherorts wie Apple Maps.
quelle
Ich habe meine eigene Bibliothek geschrieben, um das beabsichtigte Verhalten in der ios Maps-App zu erreichen. Es ist eine protokollorientierte Lösung. Sie müssen also keine Basisklasse erben, sondern einen Sheet Controller erstellen und nach Ihren Wünschen konfigurieren. Es unterstützt auch die innere Navigation / Präsentation mit oder ohne UINavigationController.
Siehe untenstehenden Link für weitere Details.
https://github.com/OfTheWolf/UBottomSheet
quelle
Ich habe kürzlich eine Komponente namens
SwipeableView
Unterklasse von erstelltUIView
, die in Swift 5.1 geschrieben wurde. Es unterstützt alle 4 Richtungen, verfügt über mehrere Anpassungsoptionen und kann verschiedene Attribute und Elemente animieren und interpolieren (z. B. Layouteinschränkungen, Hintergrund- / Farbtonfarbe, affine Transformation, Alphakanal und Ansichtszentrum, alle mit dem jeweiligen Vitrinen-Demo demonstriert). Es unterstützt auch die Wischkoordination mit der inneren Bildlaufansicht, wenn diese gesetzt oder automatisch erkannt wird. Sollte ziemlich einfach und unkompliziert zu bedienen sein (ich hoffe 🙂)Link unter https://github.com/LucaIaco/SwipeableView
konzeptioneller Beweiß:
Ich hoffe es hilft
quelle
Vielleicht können Sie meine Antwort https://github.com/AnYuan/AYPannel ausprobieren , inspiriert von Pulley. Reibungsloser Übergang vom Verschieben der Schublade zum Scrollen der Liste. Ich habe der Container-Bildlaufansicht eine Schwenkgeste hinzugefügt und shouldRecognizeSimultaneousWithGestureRecognizer so eingestellt, dass YES zurückgegeben wird. Mehr Details in meinem Github-Link oben. Möchte helfen.
quelle