Czy ktoś może mi powiedzieć, jak mogę naśladować dolny arkusz w nowej aplikacji Mapy w iOS 10?
W Androidzie możesz użyć narzędzia, BottomSheet
które naśladuje to zachowanie, ale nie mogłem znaleźć czegoś takiego na iOS.
Czy to prosty widok przewijania ze wstawką zawartości, aby pasek wyszukiwania znajdował się na dole?
Jestem całkiem nowy w programowaniu na iOS, więc jeśli ktoś mógłby mi pomóc w tworzeniu tego układu, byłoby to bardzo mile widziane.
Mam na myśli „dolny arkusz”:
Odpowiedzi:
Nie wiem, jak dokładnie dolny arkusz nowej aplikacji Mapy reaguje na interakcje użytkowników. Ale możesz utworzyć niestandardowy widok, który wygląda jak na zrzutach ekranu i dodać go do widoku głównego.
Zakładam, że wiesz, jak:
1- twórz kontrolery widoku za pomocą scenorysów lub plików Xib.
2 - użyj googleMaps lub Apple's MapKit.
Przykład
1- Utwórz 2 kontrolery widoku, np. MapViewController i BottomSheetViewController . Pierwszy kontroler będzie obsługiwał mapę, a drugi to sam dolny arkusz.
Skonfiguruj MapViewController
Utwórz metodę dodawania widoku dolnego arkusza.
I nazwij to metodą viewDidAppear:
Skonfiguruj BottomSheetViewController
1) Przygotuj tło
Utwórz metodę dodawania efektów rozmycia i jaskrawości
wywołaj tę metodę w swoim widokuWillAppear
Upewnij się, że kolor tła widoku kontrolera jest przezroczysty.
2) Animuj wygląd dołu arkusza
3) Zmodyfikuj xib, jak chcesz.
4) Dodaj Pan Gesture Recognizer do swojego widoku.
W metodzie viewDidLoad dodaj UIPanGestureRecognizer.
I zaimplementuj zachowanie gestów:
Przewijany arkusz dolny:
Jeśli Twój widok niestandardowy jest widokiem przewijania lub innym widokiem, który dziedziczy, masz dwie opcje:
Pierwszy:
Zaprojektuj widok z widokiem nagłówka i dodaj panGesture do nagłówka. (złe wrażenia użytkownika) .
Druga:
1 - Dodaj panoramę do widoku dolnego arkusza.
2 - Zaimplementuj UIGestureRecognizerDelegate i ustaw delegata panGesture na kontroler.
3- Wdrożenie shouldRecognizeSimultaneouslyWith funkcji zarządcę oraz wyłączyć z Scrollview isScrollEnabled obiektu dwóch przypadków:
W przeciwnym razie włącz przewijanie.
UWAGA
Jeśli ustawisz .allowUserInteraction jako opcję animacji, tak jak w przykładowym projekcie, musisz włączyć przewijanie po zakończeniu animacji, jeśli użytkownik przewija w górę.
Przykładowy projekt
I stworzyliśmy przykładowy projekt z większą ilością opcji na ten repozytorium, które mogą dać ci lepszy wgląd w sposób dostosowywania przepływu.
W wersji demo funkcja addBottomSheetView () kontroluje, który widok powinien zostać użyty jako dolny arkusz.
Przykładowe zrzuty ekranu z projektu
- Częściowy widok
- Pełny widok
- Przewijalny widok
źródło
Wydałem bibliotekę na podstawie mojej odpowiedzi poniżej.
Naśladuje nakładkę aplikacji Skróty. Zobacz ten artykuł .
Głównym składnikiem biblioteki jest
OverlayContainerViewController
. Definiuje obszar, w którym kontroler widoku można przeciągać w górę iw dół, ukrywając lub ujawniając zawartość pod nim.Zaimplementuj,
OverlayContainerViewControllerDelegate
aby określić liczbę żądanych wycięć:Poprzednia odpowiedź
Myślę, że w sugerowanych rozwiązaniach istnieje znacząca kwestia: przejście między zwojem a tłumaczeniem.
W Mapach, jak być może zauważyłeś, kiedy tableView sięga
contentOffset.y == 0
, dolny arkusz przesuwa się w górę lub spada.Chodzi o to, ponieważ nie możemy po prostu włączyć / wyłączyć przewijania, gdy nasz gest przesuwania rozpoczyna tłumaczenie. Zatrzymuje przewijanie do momentu rozpoczęcia nowego dotknięcia. Tak jest w przypadku większości proponowanych tutaj rozwiązań.
Oto moja próba realizacji tego ruchu.
Punkt początkowy: aplikacja Maps
Aby rozpocząć dochodzenie, niech wizualizacji hierarchii wyświetl Maps (Mapy rozpocząć na symulatorze, a następnie wybierz
Debug
>Attach to process by PID or Name
>Maps
w Xcode 9).Nie mówi, jak działa ruch, ale pomogło mi zrozumieć jego logikę. Możesz grać z lldb i debugerem hierarchii widoków.
Nasz stos kontrolerów widoków
Stwórzmy podstawową wersję architektury Maps ViewController.
Zaczynamy od
BackgroundViewController
(naszego widoku mapy):Umieszczamy tableView w dedykowanym
UIViewController
:Teraz potrzebujemy VC do osadzenia nakładki i zarządzania jej tłumaczeniem. Aby uprościć problem, uważamy, że może on przełożyć nakładkę z jednego punktu statycznego
OverlayPosition.maximum
na innyOverlayPosition.minimum
.Na razie ma tylko jedną publiczną metodę animacji zmiany pozycji i ma przejrzysty widok:
Wreszcie potrzebujemy ViewController do osadzenia wszystkich:
W naszej AppDelegate nasza sekwencja uruchamiania wygląda następująco:
Trudność związana z tłumaczeniem nakładki
Jak przetłumaczyć naszą nakładkę?
Większość proponowanych rozwiązań wykorzystuje dedykowany moduł rozpoznawania gestów panoramy, ale tak naprawdę już go mamy: gest panoramy widoku tabeli. Ponadto musimy synchronizować zwój i tłumaczenie oraz
UIScrollViewDelegate
mieć wszystkie potrzebne zdarzenia!Naiwna implementacja użyłaby drugiego gestu panoramy i spróbowała zresetować
contentOffset
widok tabeli, gdy nastąpi tłumaczenie:Ale to nie działa. TableView aktualizuje go,
contentOffset
gdy wyzwala własne działanie rozpoznawania gestów panoramy lub gdy wywoływane jest wywołanie zwrotne displayLink. Nie ma szans, że nasz program rozpoznający uruchomi się zaraz po udanym zastąpieniucontentOffset
. Naszą jedyną szansą jest albo wzięcie udziału w fazie układu (poprzez przesłonięcielayoutSubviews
wywołań widoku przewijania w każdej ramce widoku przewijania) lub odpowiedź nadidScroll
metodę uczestnika wywoływaną przy każdejcontentOffset
modyfikacji. Spróbujmy tego.Implementacja tłumaczenia
Dodajemy do naszego delegata, aby
OverlayVC
wysłać zdarzenia scrollview do naszego modułu obsługi tłumaczeńOverlayContainerViewController
:W naszym kontenerze śledzimy tłumaczenie za pomocą wyliczenia:
Obecne obliczenie pozycji wygląda następująco:
Potrzebujemy 3 metod do obsługi tłumaczenia:
Pierwszy mówi nam, czy musimy rozpocząć tłumaczenie.
Drugi wykonuje tłumaczenie. Wykorzystuje
translation(in:)
metodę gestu przewijania scrollView.Trzeci animuje koniec tłumaczenia, gdy użytkownik puści palec. Pozycję obliczamy na podstawie prędkości i aktualnej pozycji widoku.
Implementacja naszej delegacji po prostu wygląda następująco:
Ostatni problem: wywołanie zmian w kontakcie nakładki
Tłumaczenie jest teraz całkiem wydajne. Ale wciąż jest ostatni problem: poprawki nie są dostarczane do naszego widoku tła. Wszystkie są przechwytywane przez widok pojemnika nakładki. Nie możemy ustawić
isUserInteractionEnabled
sięfalse
bo to również wyłączyć interakcje w naszym widoku tabeli. Rozwiązanie to jest szeroko stosowane w aplikacji MapyPassThroughView
:Usuwa się z łańcucha odpowiadającego.
W
OverlayContainerViewController
:Wynik
Oto wynik:
Możesz znaleźć kod tutaj .
Jeśli zauważysz jakieś błędy, daj mi znać! Pamiętaj, że twoja implementacja może oczywiście użyć drugiego gestu przesuwania, szczególnie jeśli dodasz nagłówek w nakładce.
Zaktualizuj 23/08/18
Możemy wymienić
scrollViewDidEndDragging
zewillEndScrollingWithVelocity
zamiastenabling
/disabling
zwoju kiedy użytkownik przeciągając końce:Możemy użyć animacji wiosennej i umożliwić interakcję użytkownika podczas animacji, aby usprawnić przepływ ruchu:
źródło
UIViewPropertyAnimator
(który ma możliwość wstrzymania), a następnie użyćfractionComplete
właściwości do wykonania szorowania.translateView(following:)
metodzie obliczasz wysokość na podstawie translacji, ale może ona zaczynać się od innej wartości niż 0,0 (np. Widok tabeli jest nieco przewijany, a nakładka jest zmaksymalizowana po rozpoczęciu przeciągania) . Spowodowałoby to początkowy skok. Możesz to rozwiązać za pomocąscrollViewWillBeginDragging
wywołania zwrotnego, w którym zapamiętasz początkowycontentOffset
widok tabeli i użyjesz go wtranslateView(following:)
obliczeniach.csrutil disable && reboot
. Będziesz wtedy mieć wszystkie uprawnienia, które root powinien normalnie dać ci, w tym możliwość przyłączenia się do procesu Apple.Wypróbuj koło pasowe :
https://github.com/52inc/Pulley
źródło
Możesz spróbować mojej odpowiedzi https://github.com/SCENEE/FloatingPanel . Zapewnia kontroler widoku kontenera do wyświetlania interfejsu „dolnego arkusza”.
Jest łatwy w użyciu i nie przeszkadza Ci żadna obsługa rozpoznawania gestów! W razie potrzeby możesz również śledzić widok przewijania (lub widok rodzeństwa) w dolnym arkuszu.
To jest prosty przykład. Pamiętaj, że musisz przygotować kontroler widoku, aby wyświetlać zawartość w dolnym arkuszu.
Oto kolejny przykładowy kod wyświetlający dolny arkusz do wyszukiwania lokalizacji takiej jak Apple Maps.
źródło
Napisałem własną bibliotekę, aby osiągnąć zamierzone zachowanie w aplikacji ios Maps. Jest to rozwiązanie zorientowane na protokół. Więc nie musisz dziedziczyć żadnej klasy bazowej, zamiast tego utwórz kontroler arkuszy i skonfiguruj, jak chcesz. Obsługuje również wewnętrzną nawigację / prezentację z lub bez UINavigationController.
Zobacz poniższy link, aby uzyskać więcej informacji.
https://github.com/OfTheWolf/UBottomSheet
źródło
Niedawno stworzyłem komponent o nazwie
SwipeableView
podklasaUIView
napisany w Swift 5.1. Obsługuje wszystkie 4 kierunki, ma kilka opcji dostosowywania i może animować i interpolować różne atrybuty i elementy (takie jak ograniczenia układu, kolor tła / odcienia, transformacja afiniczna, kanał alfa i centrum widoku, wszystkie z nich pokazane z odpowiednią gablotą). Obsługuje również koordynację przesuwania z wewnętrznym widokiem przewijania, jeśli jest ustawiony lub automatycznie wykryty. Powinien być dość łatwy w użyciu (mam nadzieję 🙂)Link na https://github.com/LucaIaco/SwipeableView
dowód koncepcji:
Mam nadzieję, że to pomoże
źródło
Może spróbujesz mojej odpowiedzi https://github.com/AnYuan/AYPannel , zainspirowanej Pulleyem. Płynne przejście z przesuwania szuflady do przewijania listy. Dodałem gest panoramowania w widoku przewijania kontenera i ustawiłem returnRecognizeSimultentlyWithGestureRecognizer, aby zwrócił TAK. Więcej szczegółów w moim linku github powyżej. Chciałbym pomóc.
źródło