Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt.
Znalazłeś błąd? Zgłoś problem →
Cześć wszystkim!
Przed nadchodzącymi jesiennymi premierami nowych wersji systemów mobilnych zalecamy wcześniejsze przygotowanie aplikacji React Native, aby uniknąć problemów po ich oficjalnym udostępnieniu.
Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt.
Znalazłeś błąd? Zgłoś problem →
Od dłuższego czasu Apple odradza używanie UIWebView na rzecz WKWebView. W iOS 12, który zostanie wydany w nadchodzących miesiącach, UIWebView zostanie oficjalnie oznaczony jako przestarzały. Implementacja WebView dla iOS w React Native w dużej mierze opiera się na klasie UIWebView. Dlatego w świetle tych zmian stworzyliśmy nowy natywny backend dla iOS dla komponentu WebView w React Native, który wykorzystuje WKWebView.
Końcowe zmiany zostały wprowadzone w tym commicie i będą dostępne w wersji 0.57.
Aby skorzystać z tej nowej implementacji, użyj właściwości useWebKit:
UIWebView nie posiadał prawidłowego sposobu na ułatwienie komunikacji między JavaScript działającym w WebView a React Native. Gdy wiadomości były wysyłane z WebView, polegaliśmy na obejściu, aby dostarczyć je do React Native. W skrócie, kodowaliśmy dane wiadomości w adresie URL ze specjalnym schematem i przekierowywaliśmy WebView pod ten adres. Po stronie natywnej przechwytywaliśmy i anulowaliśmy to przekierowanie, przetwarzaliśmy dane z adresu URL i w końcu wywoływaliśmy React Native. Ta implementacja była podatna na błędy i niebezpieczna. Z przyjemnością ogłaszam, że wykorzystaliśmy funkcje WKWebView, aby całkowicie ją zastąpić.
Inne zalety WKWebView w porównaniu z UIWebView to szybsze wykonywanie kodu JavaScript oraz architektura wieloprocesowa. Więcej szczegółów znajdziesz w WWDC 2014.
Jeśli twoje komponenty używają poniższych właściwości, możesz napotkać problemy podczas przełączania się na WKWebView. Na razie sugerujemy unikanie używania tych właściwości:
Niespójne zachowanie:
automaticallyAdjustContentInsets i contentInsets (commit)
Gdy dodasz contentInsets do WKWebView, nie zmienia to viewportu WKWebView. Viewport pozostaje tej samej wielkości co ramka. W przypadku UIWebView rozmiar viewportu faktycznie się zmienia (zmniejsza się, jeśli contentInsets są dodatnie).
W nowej implementacji WebView dla iOS istnieje możliwość, że kolor tła będzie migać, jeśli użyjesz tej właściwości. Ponadto WKWebView renderuje przezroczyste tła inaczej niż UIWebview. Więcej szczegółów znajdziesz w opisie commita.
Wraz z postępem technologicznym i rosnącym znaczeniem aplikacji mobilnych w codziennym życiu, rośnie także potrzeba tworzenia dostępnych aplikacji.
Ograniczone API Dostępności React Native zawsze było dużym problemem dla developerów, dlatego wprowadziliśmy kilka aktualizacji, aby ułatwić tworzenie inkluzywnych aplikacji mobilnych.
Problem pierwszy: Dwie zupełnie różne, a jednak podobne właściwości - accessibilityComponentType (Android) i accessibilityTraits (iOS)
accessibilityComponentType i accessibilityTraits to dwie właściwości służące do informowania TalkBack na Androidzie i VoiceOver na iOS, z jakim elementem interfejsu użytkownik ma do czynienia. Największe problemy z tymi właściwościami to:
To dwie różne właściwości o różnych metodach użycia, ale tym samym celu. W poprzednim API były to osobne właściwości (po jednej na platformę), co było nie tylko niewygodne, ale też mylące dla wielu developerów. accessibilityTraits na iOS pozwala na 17 różnych wartości, podczas gdy accessibilityComponentType na Androidzie tylko na 4. Co więcej, wartości w większości się nie pokrywały. Nawet typy danych wejściowych różnią się: accessibilityTraits akceptuje tablicę cech lub pojedynczą cechę, podczas gdy accessibilityComponentType tylko pojedynczą wartość.
Bardzo ograniczona funkcjonalność na Androidzie. Przy starej właściwości TalkBack rozpoznawał tylko elementy: "button", "radiobutton_checked" i "radiobutton_unchecked".
Podpowiedzi dostępności pomagają użytkownikom TalkBack i VoiceOver zrozumieć, co się stanie po wykonaniu akcji na elemencie dostępności, gdy nie jest to oczywiste na podstawie samej etykiety. Te podpowiedzi można włączać i wyłączać w panelu ustawień. Poprzednio API React Native w ogóle nie obsługiwało podpowiedzi dostępności.
Niektórzy użytkownicy z wadami wzroku używają odwróconych kolorów w telefonach, aby uzyskać większy kontrast ekranu. Apple udostępniło API dla iOS, które pozwala developerom ignorować określone widoki. Dzięki temu obrazy i filmy nie są zniekształcane, gdy użytkownik ma włączone odwrócone kolory. To API nie jest obecnie obsługiwane przez React Native.
Rozwiązanie pierwsze: Połączenie accessibilityComponentType (Android) i accessibilityTraits (iOS)
Aby rozwiązać problem rozbieżności między accessibilityComponentType a accessibilityTraits, postanowiliśmy połączyć je w jedną właściwość. To rozwiązanie miało sens, ponieważ technicznie pełnią tę samą funkcję, a ich połączenie zwalnia developerów z konieczności martwienia się o specyfikę platformy przy budowaniu funkcji dostępności.
Tło
W iOS UIAccessibilityTraits to właściwość, którą można ustawić na dowolnym obiekcie NSObject. Każda z 17 cech przekazanych przez właściwość JavaScript do natywnych jest mapowana na element UIAccessibilityTraits w Objective-C. Cechy są reprezentowane przez wartości typu long int, a każda ustawiona cecha jest łączona operatorem OR.
W Androidzie jednak AccessibilityComponentType to koncept wymyślony przez React Native, który nie ma bezpośredniego odpowiednika we właściwościach Androida. Dostępność jest obsługiwana przez delegata dostępności. Każdy widok ma domyślnego delegata. Aby dostosować dowolne akcje dostępności, należy utworzyć nowego delegata, nadpisać konkretne metody, które chcemy dostosować, a następnie ustawić delegata dostępności dla obsługiwanego widoku. Gdy developer ustawiał AccessibilityComponentType, natywny kod tworzył nowego delegata na podstawie przekazanego komponentu i przypisywał go do widoku.
Wprowadzone zmiany
Dla naszej nowej właściwości chcieliśmy stworzyć superset obu istniejących właściwości. Zdecydowaliśmy się wzorować nową właściwość głównie na istniejącej accessibilityTraits, ponieważ accessibilityTraits ma znacznie więcej wartości. Funkcjonalność dla Androida zostanie zapewniona poprzez modyfikację Delegata Dostępności.
Istnieje 17 wartości UIAccessibilityTraits, które można ustawić dla accessibilityTraits w iOS. Jednak nie uwzględniliśmy wszystkich jako możliwych wartości dla nowej właściwości. Dzieje się tak, ponieważ efekt ustawienia niektórych z tych cech jest mało znany, a wiele wartości praktycznie nigdy nie jest używanych.
Wartości UIAccessibilityTraits generalnie pełniły jedną z dwóch funkcji: opisywały rolę elementu interfejsu lub jego stan. W większości obserwowanych przypadków używano jednej wartości reprezentującej rolę w połączeniu z "state selected", "state disabled" lub obydwoma. Dlatego zdecydowaliśmy się stworzyć dwie nowe właściwości dostępności: accessibilityRole i accessibilityState.
accessibilityRole
Nowa właściwość accessibilityRole służy do informowania TalkBacka lub Voiceovera o roli elementu interfejsu. Może przyjmować jedną z następujących wartości:
none
button
link
search
image
keyboardkey
text
adjustable
header
summary
imagebutton
Ta właściwość pozwala na przekazanie tylko jednej wartości, ponieważ elementy interfejsu generalnie nie pełnią logicznie więcej niż jednej z tych ról. Wyjątkiem jest połączenie obrazu i przycisku, dlatego dodaliśmy rolę imagebutton będącą kombinacją obu.
accessibilityStates
Nowa właściwość accessibilityStates służy do informowania TalkBacka lub Voiceovera o stanie elementu interfejsu. Przyjmuje tablicę zawierającą jedną lub obie z następujących wartości:
W tym celu dodaliśmy nową właściwość accessibilityHint. Jej ustawienie umożliwi TalkBackowi lub Voiceoverowi odczytanie podpowiedzi użytkownikom.
accessibilityHint
Ta właściwość przyjmuje podpowiedź dostępności w formie ciągu znaków (String) do odczytania.
W iOS ustawienie tej właściwości konfiguruje natywną właściwość AccessibilityHint widoku. Podpowiedź będzie odczytywana przez Voiceover, jeśli podpowiedzi dostępności są włączone w ustawieniach iPhone'a.
W Androidzie ustawienie tej właściwości dołącza wartość podpowiedzi na końcu etykiety dostępności. Zaleta tego rozwiązania polega na naśladowaniu zachowania podpowiedzi w iOS, ale wadą jest to, że w Androidzie nie można wyłączyć tych podpowiedzi w ustawieniach tak jak w iOS.
Podjęliśmy tę decyzję dla Androida, ponieważ podpowiedzi dostępności zwykle odpowiadają konkretnej akcji (np. kliknięciu) i chcieliśmy zachować spójne zachowanie między platformami.
Udostępniliśmy w JavaScript interfejs API Apple AccessibilityIgnoresInvertColors. Teraz gdy masz widok, którego kolory nie powinny być inwertowane (np. obraz), możesz ustawić tę właściwość na true, a kolory nie zostaną odwrócone.
Ten skrypt usuwa również wystąpienia AccessibilityComponentType (zakładając, że wszędzie tam, gdzie ustawiono AccessibilityComponentType, ustawiono również AccessibilityTraits).
W przypadkach, w których używano AccessibilityTraits bez odpowiedniej wartości dla AccessibilityRole, oraz w przypadkach, gdy do AccessibilityTraits przekazywano wiele cech, konieczne było wykonanie ręcznego codemodu.
Te właściwości są już używane w bazie kodu Facebooka. Codemod dla Facebooka był zaskakująco prosty. Skrypt jscodeshift naprawił około połowy naszych przypadków, a druga połowa została naprawiona ręcznie. Cały proces trwał mniej niż kilka godzin.
Mamy nadzieję, że zaktualizowane API okaże się przydatne! I prosimy, kontynuujcie tworzenie dostępnych aplikacji! #inclusion
Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt.
Znalazłeś błąd? Zgłoś problem →
Minęło trochę czasu od naszego ostatniego raportu o stanie React Native.
W Facebooku używamy React Native bardziej niż kiedykolwiek w wielu ważnych projektach. Jednym z naszych najpopularniejszych produktów jest Marketplace – jedna z głównych zakładek w naszej aplikacji, z której korzysta 800 milionów osób miesięcznie. Od momentu powstania w 2015 roku cały Marketplace został zbudowany w React Native, obejmując ponad sto pełnoekranowych widoków w różnych częściach aplikacji.
React Native wykorzystujemy także w wielu nowych sekcjach aplikacji. Jeśli oglądaliście zeszłomiesięczny keynote F8, rozpoznacie funkcje takie jak Krwiodawstwo, Reagowanie na kryzysy, Skróty prywatności i Kontrole zdrowia – wszystkie niedawno wprowadzone i zbudowane w React Native. Projekty poza główną aplikacją Facebooka również korzystają z React Native. Nowe gogle VR Oculus Go zawierają aplikację mobilną towarzyszącą w całości zbudowaną w React Native, nie wspominając już o React VR napędzającym wiele funkcji w samych goglach.
Naturalnie korzystamy też z wielu innych technologii do budowania naszych aplikacji. Litho i ComponentKit to dwie biblioteki, których szeroko używamy; obie zapewniają API komponentów podobne do Reacta do budowania natywnych ekranów. React Native nigdy nie miał zastąpić wszystkich innych technologii – skupiamy się na ulepszaniu samego React Native, ale cieszymy się, gdy inne zespoły zapożyczają nasze pomysły, jak wprowadzenie natychmiastowego przeładowania do kodu niebędącego JavaScriptem.
Gdy w 2013 roku rozpoczynaliśmy projekt React Native, zaprojektowaliśmy go z pojedynczym "mostem" między JavaScriptem a kodem natywnym, który jest asynchroniczny, możliwy do serializacji i przetwarzany wsadowo. Tak jak React DOM przekształca aktualizacje stanu w imperatywne wywołania API DOM typu document.createElement(attrs) i .appendChild(), tak React Native został zaprojektowany do zwracania pojedynczej wiadomości JSON listującej mutacje do wykonania, jak [["createView", attrs], ["manageChildren", ...]]. Zaprojektowaliśmy cały system tak, by nigdy nie polegał na synchronicznej odpowiedzi i by zapewnić pełną serializowalność całej listy do JSONa i z powrotem. Zrobiliśmy to dla elastyczności: na tej architekturze zbudowaliśmy narzędzia takie jak debugowanie w Chrome, które asynchronicznie wykonuje cały kod JavaScript przez połączenie WebSocket.
Przez ostatnie 5 lat odkryliśmy, że te początkowe założenia utrudniają implementację niektórych funkcji. Asynchroniczny most uniemożliwia bezpośrednią integrację logiki JavaScript z wieloma natywnymi API oczekującymi synchronicznych odpowiedzi. Wsadowe przetwarzanie wywołań natywnych utrudnia wywoływanie z aplikacji React Native funkcji zaimplementowanych natywnie. A serializowalny most oznacza niepotrzebne kopiowanie zamiast bezpośredniego współdzielenia pamięci między obu światami. Dla aplikacji całkowicie zbudowanych w React Native te ograniczenia są zwykle akceptowalne. Ale dla aplikacji z złożoną integracją między React Native a istniejącym kodem są frustrujące.
Pracujemy nad dużą przebudową architektury React Native, aby framework był bardziej elastyczny i lepiej integrował się z natywną infrastrukturą w hybrydowych aplikacjach JavaScript/natywnych. W tym projekcie zastosujemy wiedzę zdobytą przez ostatnie 5 lat i stopniowo przejdziemy do nowocześniejszej architektury. Przepisujemy wiele wewnętrznych elementów React Native, ale większość zmian odbywa się pod maską: istniejące aplikacje React Native będą działać z niewielkimi modyfikacjami lub bez nich.
Aby React Native był lżejszy i lepiej integrował się z istniejącymi natywnymi aplikacjami, ta rearchitektura wprowadza trzy główne wewnętrzne zmiany. Po pierwsze, zmieniamy model wątkowości. Zamiast wymagać od każdej aktualizacji UI pracy na trzech różnych wątkach, będzie możliwe synchroniczne wywoływanie JavaScriptu z dowolnego wątku dla wysokopriorytetowych aktualizacji, przy jednoczesnym utrzymaniu niskopriorytetowych zadań poza wątkiem głównym dla zachowania responsywności. Po drugie, włączamy możliwości async rendering do React Native, co umożliwi wielopoziomowe priorytety renderowania i uprości obsługę asynchronicznych danych. Wreszcie, upraszczamy nasz mostek, aby był szybszy i lżejszy; bezpośrednie wywołania między natywnym kodem a JavaScriptem są bardziej wydajne i ułatwią budowę narzędzi debugujących takich jak ślady stosu międzyjęzykowego.
Po wprowadzeniu tych zmian możliwe będą ściślejsze integracje. Obecnie włączenie natywnej nawigacji, obsługi gestów czy komponentów takich jak UICollectionView i RecyclerView bez skomplikowanych obejść jest niemożliwe. Po zmianach w modelu wątkowości tworzenie takich funkcji stanie się proste.
Udostępnimy więcej szczegółów na temat tej pracy później w tym roku, gdy będzie bliżej ukończenia.
Oprócz wewnętrznej społeczności w Facebooku, cieszymy się, że na zewnątrz istnieje prężna społeczność użytkowników i współtwórców React Native. Chcemy lepiej wspierać społeczność React Native, zarówno lepiej służąc użytkownikom, jak i ułatwiając współtworzenie projektu.
Tak jak nasze zmiany architektoniczne pomogą React Native czyściej współdziałać z inną natywną infrastrukturą, React Native powinien być szczuplejszy po stronie JavaScriptu, aby lepiej pasować do ekosystemu JavaScript – w tym umożliwiając wymianę maszyny wirtualnej i bundlera. Wiemy, że tempo zmian łamiących kompatybilność może być trudne do nadążenia, więc chcemy znaleźć sposoby na rzadsze wydawanie wersji głównych. Wreszcie, wiemy że niektóre zespoły poszukują bardziej dogłębnej dokumentacji w tematach takich jak optymalizacja uruchamiania, gdzie nasza ekspertyza nie została jeszcze spisana. Spodziewajcie się takich zmian w nadchodzącym roku.
Jeśli używasz React Native, jesteś częścią naszej społeczności – dziel się z nami swoimi przemyśleniami, jak możemy ulepszyć React Native dla Ciebie.
React Native to tylko jedno z narzędzi w zestawie developera mobilnego, ale wierzymy w nie mocno – i ulepszamy je każdego dnia, z ponad 2500 commitami w ostatnim roku od 500+ współtwórców.
Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt.
Znalazłeś błąd? Zgłoś problem →
JavaScript! Wszyscy go kochamy. Ale niektórzy z nas uwielbiają także typy. Na szczęście istnieją rozwiązania pozwalające dodać silniejsze typowanie do JavaScript. Moim ulubionym jest TypeScript, ale React Native natywnie wspiera Flow. Wybór między nimi zależy od preferencji – każde podejście inaczej dodaje magię typów do JavaScript. Dzisiaj przyjrzymy się, jak używać TypeScript w aplikacjach React Native.
Aktualizacja: Od czasu powstania tego wpisu proces stał się jeszcze prostszy. Możesz zastąpić całą konfigurację opisaną w tym artykule, wykonując jedno polecenie:
Istnieją jednak pewne ograniczenia w obsłudze TypeScript przez Babel, które szczegółowo omówiono w powyższym artykule. Kroki opisane w tym wpisie nadal działają, a Artsy nadal używa react-native-typescript-transformer w produkcji, ale najszybszym sposobem na rozpoczęcie pracy z React Native i TypeScript jest użycie powyższego polecenia. Zawsze możesz przełączyć się później, jeśli zajdzie taka potrzeba.
W każdym razie – dobrej zabawy! Oryginalny wpis blogowy kontynuujemy poniżej.
Ponieważ możesz rozwijać aplikacje na różnych platformach dla różnych typów urządzeń, podstawowa konfiguracja może być złożona. Najpierw upewnij się, że potrafisz uruchomić zwykłą aplikację React Native bez TypeScript. Postępuj zgodnie z instrukcjami na stronie React Native, aby rozpocząć. Gdy uda ci się wdrożyć aplikację na urządzeniu lub emulatorze, będziesz gotowy do stworzenia aplikacji React Native z TypeScript.
Plik tsconfig.json zawiera wszystkie ustawienia kompilatora TypeScript. Domyślne wartości utworzone przez powyższe polecenie są w większości poprawne, ale otwórz plik i odkomentuj następującą linię:
{ /* Search the config file for the following line and uncomment it. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ }
Plik rn-cli.config.js zawiera ustawienia dla React Native TypeScript Transformer. Otwórz go i dodaj następujący kod:
Zmień nazwy wygenerowanych plików App.js i __tests_/App.js na App.tsx. Plik index.js musi zachować rozszerzenie .js. Wszystkie nowe pliki powinny używać rozszerzenia .tsx (lub .ts, jeśli plik nie zawiera JSX).
Gdybyś spróbował teraz uruchomić aplikację, otrzymałbyś błąd podobny do object prototype may only be an object or null. Jest to spowodowane niepowodzeniem w zaimportowaniu domyślnego eksportu z React oraz nazwanego eksportu w tej samej linii. Otwórz plik App.tsx i zmodyfikuj import na początku pliku:
-import React, { Component } from 'react'; +import React from 'react' +import { Component } from 'react';
Część tego problemu wynika z różnic w sposobie współdziałania Babela i TypeScripta z modułami CommonJS. W przyszłości oba narzędzia ustabilizują się pod kątem tego samego zachowania.
W tym momencie powinieneś być w stanie uruchomić aplikację React Native.
Aby uzyskać najlepsze doświadczenia w TypeScript, potrzebujemy, aby sprawdzanie typów rozumiało strukturę i API naszych zależności. Niektóre biblioteki publikują swoje pakiety z plikami .d.ts (deklaracje typów/definicje typów), które opisują strukturę podstawowego JavaScriptu. Dla innych bibliotek musimy jawnie zainstalować odpowiedni pakiet z zakresu npm @types/.
Na przykład będziemy potrzebować typów dla Jesta, Reacta, React Native oraz React Test Renderer.
Zapisaliśmy te pakiety deklaracji jako zależności dev, ponieważ jest to aplikacja React Native używająca tych zależności wyłącznie podczas rozwoju, a nie w czasie działania. Gdybyśmy publikowali bibliotekę na NPM, musielibyśmy dodać niektóre z tych zależności typów jako zwykłe zależności.
Dodajmy komponent do naszej aplikacji. Stwórzmy komponent Hello.tsx. Jest to komponent dydaktyczny - nie coś, co napisałbyś w rzeczywistej aplikacji, ale przykład pokazujący nietrywialne użycie TypeScript w React Native.
Utwórz katalog components i dodaj następujący przykład:
Zamiast renderować elementy HTML jak div, span, h1 itd., renderujemy komponenty takie jak View i Button. Są to natywne komponenty działające na różnych platformach.
Stylowanie określamy za pomocą funkcji StyleSheet.create dostarczonej przez React Native. Arkusze stylów React pozwalają kontrolować układ przy użyciu Flexboxa i stylizować przy użyciu konstrukcji podobnych do CSS.
Mamy już zainstalowanego Jesta jako runner testów. Będziemy pisać testy snapshotów dla naszych komponentów, więc dodajmy wymagane rozszerzenie do testów snapshotów:
yarnadd--dev react-addons-test-utils
Teraz utwórz folder __tests__ w katalogu components i dodaj test dla Hello.tsx:
Podczas pierwszego uruchomienia testu zostanie utworzony migawkowy zapis wyrenderowanego komponentu, który zostanie zapisany w pliku components/__tests__/__snapshots__/Hello.tsx.snap. Po wprowadzeniu zmian w komponencie konieczne będzie zaktualizowanie migawek i przejrzenie ich pod kątem nieoczekiwanych zmian. Więcej o testowaniu komponentów React Native można przeczytać tutaj.
Zapoznaj się z oficjalnym samouczkiem React oraz biblioteką do zarządzania stanem Redux. Te zasoby mogą okazać się pomocne podczas tworzenia aplikacji React Native. Dodatkowo warto przyjrzeć się bibliotece komponentów ReactXP, napisanej w całości w TypeScript i obsługującej zarówno React na webie, jak i React Native.
Powodzenia w bardziej bezpiecznym typowo środowisku programistycznym React Native!
Trzy lata temu zgłoszono problem na GitHubie dotyczący dodania obsługi widżetu pomocniczego klawiatury w React Native.
Przez kolejne lata pojawiały się liczne "+1", różne obejścia i zero konkretnych zmian w RN w tej sprawie - aż do dziś. Zaczynając od iOS, udostępniamy API do obsługi natywnego widżetu pomocniczego klawiatury i z przyjemnością dzielimy się szczegółami implementacji.
Czym dokładnie jest widżet pomocniczy klawiatury? Z dokumentacji Apple dowiadujemy się, że to niestandardowy widok kotwiczony u góry systemowej klawiatury, gdy obiekt staje się first responder. Każdy obiekt dziedziczący po UIResponder może przedefiniować właściwość .inputAccessoryView jako read-write i zarządzać niestandardowym widokiem. Infrastruktura responderów montuje widok i synchronizuje go z klawiaturą systemową. Gesty zamykające klawiaturę (przeciągnięcie lub dotknięcie) są automatycznie stosowane do widżetu pomocniczego. Pozwala to budować interfejsy z interaktywnym zamykaniem klawiatury - kluczową funkcją w aplikacjach takich jak iMessage czy WhatsApp.
Istnieją dwa główne zastosowania dla kotwiczenia widoku nad klawiaturą. Pierwsze to tworzenie paska narzędzi klawiatury, jak selektor tła w kreatorze Facebooka.
W tym scenariuszu klawiatura jest skupiona na polu tekstowym, a widżet pomocniczy dostarcza dodatkowej funkcjonalności kontekstowej. W aplikacji mapowej mogą to być sugestie adresów, a w edytorze tekstu - narzędzia formatowania.
Obiektem Objective-C UIResponder posiadającym <InputAccessoryView> w tym przypadku jest wyraźnie <TextInput> stający się first responderem, który pod maską staje się instancją UITextView lub UITextField.
Drugi typowy scenariusz to przyklejone pola tekstowe:
Tutaj pole tekstowe jest częścią samego widżetu pomocniczego. Rozwiązanie powszechnie stosowane w aplikacjach messengeringowych, gdzie wiadomość można komponować podczas przewijania historii.
Kto posiada <InputAccessoryView> w tym przykładzie? Czy może to być znowu UITextView/UITextField? Pole tekstowe jest WEWNĄTRZ widżetu pomocniczego - tworzy to zależność cykliczną. Rozwiązanie tego problemu to temat na osobny artykuł. Spoiler: właścicielem jest generyczna podklasa UIView, której ręcznie każemy zostać first responderem.
Znając już zastosowania <InputAccessoryView>, kolejnym krokiem było zaprojektowanie API uwzględniającego oba scenariusze i współpracującego z istniejącymi komponentami RN jak <TextInput>.
Dla pasków narzędzi klawiatury istotne były:
Możliwość umieszczenia dowolnej hierarchii widoków RN w <InputAccessoryView>
Zdolność tej odłączonej hierarchii do odbierania dotknięć i modyfikowania stanu aplikacji
Powiązanie <InputAccessoryView> z konkretnym <TextInput>
Możliwość współdzielenia jednego <InputAccessoryView> między wieloma polami tekstowymi
Punkt 1 osiągnęliśmy za pomocą koncepcji zbliżonej do portali React. W tym podejściu "przenosimy" widoki RN do hierarchii UIView zarządzanej przez infrastrukturę responderów. Ponieważ widoki RN renderują się jako UIView, jest to proste - wystarczy nadpisać:
i przekierować wszystkie subview do nowej hierarchii UIView. Dla punktu 2 skonfigurowaliśmy nowy RCTTouchHandler dla <InputAccessoryView>. Aktualizacje stanu realizowane są standardowymi callbackami. Dla punktów 3-4 użyliśmy pola nativeID do lokalizacji widżetu w kodzie natywnym podczas tworzenia komponentu <TextInput>. Funkcja ta wykorzystuje właściwość .inputAccessoryView natywnego pola tekstowego, skutecznie łącząc <InputAccessoryView> z <TextInput> w ich implementacjach ObjC.
Obsługa przyklejonych pól tekstowych (scenariusz 2) dodaje dodatkowe ograniczenia. Ponieważ pole tekstowe jest dzieckiem widżetu pomocniczego, powiązanie przez nativeID nie wchodzi w grę. Zamiast tego ustawiamy .inputAccessoryView generycznej UIView (poza ekranem) na naszą natywną hierarchię <InputAccessoryView>. Ręczne uczynienie tej UIView first responderem powoduje zamontowanie widżetu przez infrastrukturę responderów - koncepcja dokładnie wyjaśniona we wspomnianym artykule.
Proces tworzenia tego API nie był pozbawiony wyzwań. Oto napotkane problemy i ich rozwiązania.
Początkowy pomysł zakładał nasłuchiwanie zdarzeń UIKeyboardWill(Show/Hide/ChangeFrame) w NSNotificationCenter. Ten wzorzec stosowany jest w bibliotekach open-source'owych i wewnętrznie w aplikacji Facebooka. Niestety, zdarzenia UIKeyboardDidChangeFrame nie były wywoływane na czas, aby zaktualizować ramkę <InputAccessoryView> podczas przeciągania, a zmiany wysokości klawiatury nie były wychwytywane. Powodowało to błędy typu:
Na iPhone X klawiatura tekstowa i emoji mają różne wysokości. Większość aplikacji używających zdarzeń klawiatury musiała łatać ten błąd. Naszym rozwiązaniem było pełne wykorzystanie .inputAccessoryView, gdzie infrastruktura responderów automatycznie obsługuje takie aktualizacje.
Kolejny podchwytliwy błąd dotyczył omijania przycisku Home na iPhone X. Można pomyśleć: "Apple stworzył safeAreaLayoutGuide właśnie po to!". Byliśmy równie naiwni. Problem? Natywna implementacja <InputAccessoryView> nie ma okna do zakotwiczenia aż do momentu pojawienia się. Rozwiązaliśmy to nadpisując -(BOOL)becomeFirstResponder i wymuszając constraintsy w tym momencie. Ale pojawił się kolejny problem:
Widżet omija przycisk Home, ale treść z obszaru unsafe staje się widoczna. Rozwiązanie znaleźliśmy w tym radarze. Owinęliśmy natywną hierarchię <InputAccessoryView> kontenerem ignorującym safeAreaLayoutGuide. Kontener zakrywa treść w unsafe area, podczas gdy <InputAccessoryView> pozostaje w bezpiecznej strefie.
Pełna implementacja tej funkcjonalności jest dostępna w tym commicie. Komponent <InputAccessoryView> będzie dostępny w nadchodzącym wydaniu wersji v0.55.0.
Starszy Kierownik Produktu Technicznego w AWS Mobile
Nieoficjalne Tłumaczenie Beta
Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt.
Znalazłeś błąd? Zgłoś problem →
AWS jest powszechnie znanym w branży technologicznej dostawcą usług chmurowych. Obejmują one technologie obliczeniowe, magazynowe i bazodanowe, a także w pełni zarządzane rozwiązania serwerless. Zespół AWS Mobile ściśle współpracuje z klientami i członkami ekosystemu JavaScript, aby aplikacje mobilne i webowe połączone z chmurą były bezpieczniejsze, skalowalne oraz łatwiejsze w tworzeniu i wdrażaniu. Rozpoczęliśmy od kompletu startowego, ale mamy też nowsze rozwiązania.
W tym wpisie omówimy kilka ciekawych rozwiązań dla developerów React i React Native:
AWS Amplify, deklaratywna biblioteka dla aplikacji JavaScript korzystających z usług chmurowych
AWS AppSync, w pełni zarządzana usługa GraphQL z funkcjami offline i czasu rzeczywistego
Aplikacje React Native są bardzo łatwe do uruchomienia przy użyciu narzędzi takich jak Create React Native App czy Expo. Jednak połączenie ich z chmurą może stanowić wyzwanie, gdy próbujesz dopasować przypadki użycia do usług infrastrukturalnych. Na przykład Twoja aplikacja React Native może wymagać przesyłania zdjęć. Czy powinny być one chronione per użytkownik? To prawdopodobnie oznacza potrzebę rejestracji lub logowania. Chcesz mieć własny katalog użytkowników czy korzystasz z dostawcy mediów społecznościowych? Być może aplikacja potrzebuje też wywoływać API z własną logiką biznesową po zalogowaniu użytkowników.
Aby pomóc developerom JavaScript w tych problemach, wydaliśmy bibliotekę o nazwie AWS Amplify. Jej projekt podzielono na "kategorie" zadań, zamiast implementacji specyficznych dla AWS. Na przykład, jeśli chcesz, aby użytkownicy rejestrowali się, logowali, a następnie przesyłali prywatne zdjęcia, wystarczy dodać do aplikacji kategorie Auth i Storage:
W powyższym kodzie widać przykłady typowych zadań, w których Amplify może pomóc, jak używanie kodów uwierzytelniania wieloskładnikowego (MFA) przez e-mail lub SMS. Obecnie obsługiwane kategorie to:
Auth: Zapewnia automatyzację poświadczeń. Gotowa implementacja wykorzystuje dane uwierzytelniające AWS do podpisywania oraz tokeny JWT OIDC z Amazon Cognito. Obsługiwane są typowe funkcje, takie jak MFA.
Analytics: Jedną linijką kodu uzyskaj śledzenie uwierzytelnionych i nieuwierzytelnionych użytkowników w Amazon Pinpoint. Możesz rozszerzyć to o własne metryki lub atrybuty.
API: Zapewnia bezpieczną interakcję z interfejsami RESTful API, wykorzystując AWS Signature Version 4. Moduł API doskonale sprawdza się w infrastrukturach serwerless z Amazon API Gateway.
Storage: Uproszczone polecenia do przesyłania, pobierania i listowania treści w Amazon S3. Możesz też łatwo grupować dane jako publiczne lub prywatne per użytkownik.
Caching: Interfejs pamięci podręcznej LRU działający zarówno w aplikacjach webowych, jak i React Native, wykorzystujący specyficzną dla implementacji trwałość.
i18n and Logging: Zapewnia możliwości internacjonalizacji i lokalizacji oraz debugowania i logowania.
Jedną z zalet Amplify jest wbudowanie "najlepszych praktyk" w projekt dostosowany do Twojego środowiska programistycznego. Przykładowo, zauważyliśmy współpracując z klientami i developerami React Native, że skróty stosowane podczas rozwoju aplikacji dla szybkiego efektu często trafiały do środowisk produkcyjnych. To może naruszać skalowalność lub bezpieczeństwo, wymuszając przebudowę infrastruktury i refaktoryzację kodu.
Jednym z przykładów, jak pomagamy programistom uniknąć tego problemu, są Referencyjne architektury bezserwerowe z AWS Lambda. Pokazują one najlepsze praktyki współpracy Amazon API Gateway i AWS Lambda przy budowaniu zaplecza. Ten wzorzec został wbudowany w kategorię API Amplify. Możesz użyć tego wzorca do interakcji z wieloma różnymi punktami końcowymi REST i przekazywania nagłówków bezpośrednio do funkcji Lambda dla niestandardowej logiki biznesowej. Udostępniliśmy również AWS Mobile CLI do inicjowania nowych lub istniejących projektów React Native z tymi funkcjami. Aby rozpocząć, zainstaluj poprzez npm i postępuj zgodnie z monitami konfiguracyjnymi:
Kolejnym przykładem wbudowanych najlepszych praktyk specyficznych dla ekosystemu mobilnego jest bezpieczeństwo haseł. Domyślna implementacja kategorii Auth wykorzystuje pule użytkowników Amazon Cognito do rejestracji i logowania. Ta usługa implementuje protokół Secure Remote Password jako sposób ochrony użytkowników podczas prób uwierzytelniania. Jeśli chcesz zgłębić matematyczne podstawy protokołu, zauważysz, że musisz użyć dużej liczby pierwszej przy obliczaniu weryfikatora hasła nad pierwiastkiem pierwotnym do generowania grupy. W środowiskach React Native JIT jest wyłączony. To sprawia, że obliczenia BigInteger dla operacji bezpieczeństwa takich jak ta są mniej wydajne. Aby to zrekompensować, udostępniliśmy natywne mosty w Androidzie i iOS, które możesz podlinkować w swoim projekcie:
npm install --save aws-amplify-react-native react-native link amazon-cognito-identity-js
Cieszymy się również, widząc że zespół Expo uwzględnił to w swoim najnowszym SDK, dzięki czemu możesz używać Amplify bez konieczności ejectowania.
Wreszcie, specjalnie dla rozwoju React Native (i React), Amplify zawiera komponenty wyższego rzędu (HOCs) do łatwego opakowywania funkcjonalności, takich jak rejestracja i logowanie w twojej aplikacji:
Podstawowy komponent jest również dostarczany jako <Authenticator />, co daje pełną kontrolę nad dostosowywaniem interfejsu użytkownika. Dostarcza także właściwości do zarządzania stanem użytkownika, np. czy zalogował się czy czeka na potwierdzenie MFA, oraz callbacki, które możesz wywołać przy zmianie stanu.
Podobnie znajdziesz ogólne komponenty React do różnych przypadków użycia. Możesz je dostosować do swoich potrzeb, np. aby pokazać wszystkie prywatne obrazy z Amazon S3 w module Storage:
Możesz kontrolować wiele funkcji komponentów poprzez props, jak pokazano wcześniej, z opcjami publicznego lub prywatnego przechowywania. Istnieją nawet możliwości automatycznego zbierania analiz, gdy użytkownicy wchodzą w interakcję z określonymi komponentami UI:
return<S3Albumtrack/>
AWS Amplify preferuje konwencję nad konfiguracją w stylu rozwoju, z globalną procedurą inicjalizacji lub inicjalizacją na poziomie kategorii. Najszybszym sposobem na rozpoczęcie jest użycie pliku aws-exports. Jednak programiści mogą również używać biblioteki niezależnie z istniejącymi zasobami.
Aby zgłębić filozofię i zobaczyć pełne demo, obejrzyj film z AWS re:Invent.
Krótko po premierze AWS Amplify, udostępniliśmy również AWS AppSync. To w pełni zarządzana usługa GraphQL z funkcjami offline i działania w czasie rzeczywistym. Chociaż możesz używać GraphQL w różnych językach programowania klienckiego (w tym natywnych Android i iOS), jest ona szczególnie popularna wśród programistów React Native. Dzieje się tak, ponieważ model danych doskonale wpasowuje się w jednokierunkowy przepływ danych i hierarchię komponentów.
AWS AppSync umożliwia łączenie się z zasobami w twoim własnym koncie AWS, co oznacza, że posiadasz i kontrolujesz swoje dane. Odbywa się to poprzez użycie źródeł danych, a usługa obsługuje Amazon DynamoDB, Amazon Elasticsearch oraz AWS Lambda. Dzięki temu możesz łączyć funkcjonalności (takie jak NoSQL i wyszukiwanie pełnotekstowe) w pojedynczym interfejsie API GraphQL jako schemat. Pozwala to na mieszanie i dopasowywanie źródeł danych. Usługa AppSync może również tworzyć zasoby na podstawie schematu, więc jeśli nie znasz usług AWS, możesz napisać schemat GraphQL w SDL, kliknąć przycisk i automatycznie rozpocząć pracę.
Funkcjonalność czasu rzeczywistego w AWS AppSync jest kontrolowana poprzez subskrypcje GraphQL z dobrze znanym wzorcem opartym na zdarzeniach. Ponieważ subskrypcje w AWS AppSync są kontrolowane na poziomie schematu za pomocą dyrektywy GraphQL, a schemat może używać dowolnego źródła danych, oznacza to, że możesz wyzwalać powiadomienia z operacji bazodanowych przy użyciu Amazon DynamoDB i Amazon Elasticsearch Service, lub z innych części twojej infrastruktury za pomocą AWS Lambda.
Podobnie jak w AWS Amplify, możesz używać funkcji bezpieczeństwa klasy enterprise w swoim interfejsie API GraphQL z AWS AppSync. Usługa pozwala szybko rozpocząć pracę z kluczami API. Jednak gdy przechodzisz do produkcji, możesz przejść na użycie AWS Identity and Access Management (IAM) lub tokenów OIDC z pul użytkowników Amazon Cognito. Możesz kontrolować dostęp na poziomie resolvera za pomocą polityk na typach. Możesz nawet używać sprawdzeń logicznych dla szczegółowej kontroli dostępu w czasie wykonywania, takich jak wykrywanie, czy użytkownik jest właścicielem określonego zasobu bazy danych. Istnieją również możliwości sprawdzania przynależności do grup w celu wykonywania resolverów lub dostępu do poszczególnych rekordów bazy danych.
Aby pomóc programistom React Native w poznaniu tych technologii, dostępny jest wbudowany przykładowy schemat GraphQL, który możesz uruchomić na stronie głównej konsoli AWS AppSync. Ten przykład wdraża schemat GraphQL, tworzy tabele bazy danych i automatycznie łączy zapytania, mutacje oraz subskrypcje. Dostępny jest również działający przykład dla React Native dla AWS AppSync, który wykorzystuje ten wbudowany schemat (oraz przykład dla React), co pozwala uruchomić zarówno komponenty klienckie, jak i chmurowe w ciągu kilku minut.
Rozpoczęcie pracy jest proste, gdy używasz AWSAppSyncClient, który podłącza się do Apollo Client. AWSAppSyncClient obsługuje bezpieczeństwo i podpisywanie dla twojego interfejsu API GraphQL, funkcjonalność offline oraz proces uzgadniania i negocjacji subskrypcji:
Konsola AppSync udostępnia plik konfiguracyjny do pobrania, który zawiera twój punkt końcowy GraphQL, region AWS i klucz API. Następnie możesz użyć klienta z React Apollo:
W tym momencie możesz używać standardowych zapytań GraphQL:
query ListEvents{ listEvents{ items{ __typename id name where when description comments{ __typename items{ __typename eventId commentId content createdAt } nextToken } } } }
Powyższy przykład pokazuje zapytanie z przykładowym schematem aplikacji utworzonym przez AppSync. Prezentuje on nie tylko interakcję z DynamoDB, ale także zawiera paginację danych (w tym zaszyfrowanych tokenów) oraz relacje typów między Events i Comments. Ponieważ aplikacja jest skonfigurowana z AWSAppSyncClient, dane są automatycznie utrwalane offline i będą synchronizowane, gdy urządzenia ponownie połączą się z siecią.
Zespół stojący za tymi bibliotekami jest bardzo ciekaw, jak działają one dla Ciebie. Chcemy również usłyszeć, co jeszcze możemy zrobić, aby ułatwić Ci tworzenie aplikacji w React i React Native z wykorzystaniem usług w chmurze. Skontaktuj się z zespołem AWS Mobile na GitHubie w sprawie AWS Amplify lub AWS AppSync.
Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt.
Znalazłeś błąd? Zgłoś problem →
Animacja ładowania w aplikacji Twittera na iOS bardzo mi się podoba.
Gdy aplikacja jest gotowa, logo Twittera rozwija się w przyjemny sposób, odsłaniając aplikację.
Postanowiłem odtworzyć tę animację ładowania za pomocą React Native.
Aby zrozumieć, jak to zbudować, musiałem najpierw rozłożyć animację na części. Najłatwiej dostrzec subtelności, spowalniając ją.
Musimy rozwiązać kilka kluczowych elementów tej animacji.
Skalowanie ptaka (logo).
Podczas powiększania ptaka – odsłanianie aplikacji znajdującej się pod spodem
Lekkie pomniejszenie aplikacji na końcu animacji
Odtworzenie tej animacji zajęło mi sporo czasu.
Początkowo przyjąłem błędne założenie, że niebieskie tło i ptak Twittera stanowią warstwę na wierzchu aplikacji, a podczas powiększania logo stawało się przeźroczyste, odsłaniając aplikację. To podejście nie działa, bo przeźroczyste logo pokazałoby niebieską warstwę, a nie aplikację pod spodem!
Na szczęście dla was, drodzy czytelnicy, oszczędzę wam tych frustracji. W tym poradniku od razu przejdziemy do konkretów!
Zanim przejdziemy do kodu, warto zrozumieć rozkład warstw. Aby zobrazować ten efekt, odtworzyłem go w CodePen (osadzony poniżej), gdzie możecie interaktywnie zobaczyć poszczególne warstwy.
Efekty tworzą trzy główne warstwy. Pierwsza to niebieska warstwa tła. Choć wydaje się być na wierzchu aplikacji, tak naprawdę znajduje się z tyłu.
Następnie mamy jednolitą białą warstwę. Na samym przodzie znajduje się nasza aplikacja.
Kluczowa sztuczka to użycie logo Twittera jako mask, która zakrywa zarówno aplikację, jak i białą warstwę. Nie będę szczegółowo omawiał maskowania — w sieci znajdziecie mnóstwozasobówna ten temat.
Podstawowa zasada maskowania: nieprzeźroczyste piksele maski odsłaniają zawartość, którą zakrywają, a przeźroczyste piksele maski ją ukrywają.
Logo Twittera służy jako maska dla dwóch warstw: jednolitej białej warstwy i warstwy aplikacji.
Aby odsłonić aplikację, powiększamy maskę, aż przekroczy rozmiar całego ekranu.
Podczas powiększania maski zwiększamy przezroczystość warstwy aplikacji, odsłaniając ją i ukrywając białą warstwę pod spodem. Na koniec efektu: warstwę aplikacji początkowo skalujemy do rozmiaru >1, a następnie zmniejszamy do 1 pod koniec animacji. Potem ukrywamy warstwy nie-aplikacyjne, bo nie będą już widoczne.
Mówi się, że obraz wart jest 1000 słów. A ile słów warta jest interaktywna wizualizacja? Klikajcie przycisk "Next Step", by przejść przez animację. Widok warstw pokazuje perspektywę boczną. Siatka pomaga wizualizować przeźroczyste warstwy.
MaskedViewIOS przyjmuje właściwości maskElement i children. Elementy children są maskowane przez maskElement. Warto zauważyć, że maska nie musi być obrazem – może to być dowolny widok. W powyższym przykładzie efektem będzie wyrenderowanie niebieskiego widoku, który będzie widoczny tylko tam, gdzie znajdują się słowa "Basic Mask" z maskElement. Właśnie stworzyliśmy skomplikowany niebieski tekst.
Chcemy wyrenderować naszą niebieską warstwę, a na wierzchu umieścić naszą maskowaną warstwę aplikacji i białą warstwę z logo Twittera.
Mamy już wszystkie elementy potrzebne do działania, następnym krokiem jest ich animowanie. Aby animacja była płynna, użyjemy Animated API React Native.
Animated pozwala nam deklaratywnie definiować animacje w JavaScript. Domyślnie te animacje działają w JavaScripcie i mówią warstwie natywnej, jakie zmiany wprowadzać w każdej klatce. Mimo że JavaScript będzie próbował aktualizować animację w każdej klatce, prawdopodobnie nie będzie w stanie robić tego wystarczająco szybko, co spowoduje utratę klatek (jank). Tego właśnie nie chcemy!
Animated ma specjalne zachowanie, które pozwala uniknąć tego problemu. Flaga useNativeDriver wysyła definicję animacji z JavaScriptu do warstwy natywnej na początku animacji, pozwalając stronie natywnej przetwarzać aktualizacje bez konieczności komunikacji z JavaScriptem w każdej klatce. Ograniczeniem useNativeDriver jest to, że można animować tylko określony zestaw właściwości, głównie transform i opacity. Nie można animować np. koloru tła za pomocą useNativeDriver – przynajmniej na razie. Z czasem dodamy więcej możliwości, a tymczasem zawsze możesz złożyć PR z brakującymi właściwościami dla swojego projektu, co przysłuży się całej społeczności 😀.
Ponieważ zależy nam na płynności animacji, będziemy działać w ramach tych ograniczeń. Więcej o działaniu useNativeDriver możesz przeczytać w naszym poście na blogu.
Powiększenie ptaka, odsłaniając aplikację i jednolitą białą warstwę
Wygaszenie aplikacji (fade in)
Pomniejszenie aplikacji
Ukrycie białej i niebieskiej warstwy po zakończeniu
W Animated mamy dwa główne sposoby definiowania animacji. Pierwszy to Animated.timing, który pozwala określić dokładny czas trwania animacji wraz z krzywą wygładzania ruchu. Drugi to fizyczne API jak Animated.spring. Z Animated.spring podajesz parametry jak tarcie i napięcie sprężyny, pozwalając fizyce sterować animacją.
Mamy wiele animacji, które mają działać równocześnie i są ze sobą ściśle powiązane. Na przykład chcemy, aby aplikacja zaczęła wygasać w trakcie odsłaniania maski. Ponieważ te animacje są tak powiązane, użyjemy Animated.timing z pojedynczą wartością Animated.Value.
Animated.Value to opakowanie wartości natywnej, której Animated używa do śledzenia stanu animacji. Zazwyczaj wystarczy jedna taka wartość dla całej animacji. Komponenty używające Animated przechowują tę wartość w stanie.
Ponieważ myślę o tej animacji jako o krokach występujących w różnych momentach jej trwania, zaczniemy od wartości Animated.Value równej 0 (0% ukończenia), a kończymy na 100 (100% ukończenia).
Początkowy stan naszego komponentu będzie następujący.
state ={ loadingProgress:newAnimated.Value(0), };
Gdy będziemy gotowi rozpocząć animację, każemy Animated animować tę wartość do 100.
Animated.timing(this.state.loadingProgress,{ toValue:100, duration:1000, useNativeDriver:true,// This is important! }).start();
Następnie próbuję określić przybliżone wartości dla różnych elementów animacji w poszczególnych etapach. Poniższa tabela przedstawia różne komponenty animacji oraz proponowane wartości w miarę postępu czasu.
Maska z logiem Twittera powinna zaczynać od skali 1, potem lekko się zmniejszyć, by następnie gwałtownie powiększyć. Zatem przy 10% animacji powinna mieć wartość skali około 0.8, by na końcu osiągnąć skalę 70. Wybór 70 był dość arbitralny - musiała być na tyle duża, by ptak całkowicie odsłonił ekran, a 60 okazało się za małe 😀. Co ciekawe, im wyższa wartość, tym szybciej będzie się wydawało, że maska rośnie, bo musi osiągnąć większy rozmiar w tym samym czasie. Ta wartość wymagała kilku prób, by dobrze współgrała z tym logo. Inne rozmiary logo lub urządzeń będą wymagały innej końcowej skali, by zapewnić pełne odsłonięcie ekranu.
Aplikacja powinna pozostać niewidoczna przez dłuższy czas, przynajmniej do momentu, gdy logo Twittera zacznie rosnąć. Bazując na oryginalnej animacji, chcę zacząć ją pokazywać, gdy ptak jest w połowie skali, i w pełni ujawnić dość szybko. Zatem przy 15% zaczynamy ją pokazywać, a przy 30% całej animacji jest już w pełni widoczna.
Skala aplikacji zaczyna się od 1.1 i zmniejsza do normalnej skali pod koniec animacji.
To, co zrobiliśmy powyżej, to mapowanie wartości z postępu animacji (w procentach) na wartości poszczególnych elementów. Robimy to w Animated za pomocą .interpolate. Tworzymy 3 różne obiekty stylów - jeden dla każdego elementu animacji - używając wartości interpolowanych na podstawie this.state.loadingProgress.
const loadingProgress =this.state.loadingProgress; const opacityClearToVisible ={ opacity: loadingProgress.interpolate({ inputRange:[0,15,30], outputRange:[0,0,1], extrapolate:'clamp', // clamp means when the input is 30-100, output should stay at 1 }), }; const imageScale ={ transform:[ { scale: loadingProgress.interpolate({ inputRange:[0,10,100], outputRange:[1,0.8,70], }), }, ], }; const appScale ={ transform:[ { scale: loadingProgress.interpolate({ inputRange:[0,100], outputRange:[1.1,1], }), }, ], };
Mając te obiekty stylów, możemy ich użyć podczas renderowania fragmentu widoku z początku wpisu. Pamiętaj, że tylko Animated.View, Animated.Text i Animated.Image mogą używać obiektów stylów opartych na Animated.Value.
Jupi! Elementy animacji wyglądają teraz tak, jak chcemy. Pozostaje tylko posprzątać niebieską i białą warstwę, które nigdy więcej nie będą widoczne.
Aby wiedzieć, kiedy możemy je usunąć, potrzebujemy znać moment zakończenia animacji. Na szczęście Animated.timing w metodzie .start przyjmuje opcjonalne callbacki wykonywane po zakończeniu animacji.
Spokojnie, drogi czytelniku. Sam nie cierpię, gdy poradniki podają tylko fragmenty kodu bez pełnego źródła.
Ten komponent został opublikowany na npm i jest dostępny na GitHubie jako react-native-mask-loader. Aby przetestować na telefonie, wersja na Expo jest dostępna tutaj:
Ta książka to świetne źródło wiedzy o Animated po przeczytaniu dokumentacji React Native.
Oryginalna animacja Twittera przyspiesza odsłanianie maski pod koniec. Spróbuj zmodyfikować loader, używając innej funkcji easingu (lub springa!), by lepiej odwzorować to zachowanie.
Obecna końcowa skala maski jest zakodowana na sztywno i może nie odsłaniać całej aplikacji na tablecie. Obliczanie końcowej skali na podstawie rozmiaru ekranu i obrazu byłoby świetnym PR-em.
Gratulacje dla Devin Abbott i Houssein Djirdeh z okazji przedpremierowej publikacji książki "Full Stack React Native"! Poprowadzi ona czytelników przez naukę React Native poprzez budowanie kilku małych aplikacji.
Expo SDK 24 zostało wydane! Wykorzystuje React Native 0.51 i zawiera mnóstwo nowych funkcji i ulepszeń: dołączanie obrazów w aplikacjach standalone (brak konieczności cache'owania przy pierwszym ładowaniu!), API do manipulacji obrazami (przycinanie, zmiana rozmiaru, obracanie, odbicie), API do wykrywania twarzy, nowe funkcje kanałów wydań (ustawianie aktywnego wydania dla danego kanału i wycofywanie), panel internetowy do śledzenia budowania aplikacji standalone oraz naprawienie długo istniejącego błędu w implementacji OpenGL dla Androida i wielozadaniowości Androida, by wymienić tylko kilka.
Od stycznia przeznaczamy więcej zasobów na React Navigation. Silnie wierzymy, że jest możliwe i pożądane budowanie nawigacji React Native przy użyciu komponentów React i prymitywów takich jak Animated oraz react-native-gesture-handler, i jesteśmy naprawdę podekscytowani niektórymi zaplanowanymi ulepszeniami. Jeśli szukasz możliwości, by przyczynić się do społeczności, sprawdź react-native-maps i react-native-svg — oba projekty mogą skorzystać z pomocy!
Rozpoczęto pull request w celu migracji rdzenia mostka React Native Windows do .NET Standard, co uczyni go efektywnie niezależnym od systemu operacyjnego. Mamy nadzieję, że wiele innych platform .NET Core będzie mogło rozszerzyć mostek własnymi modelami wątkowości, środowiskami uruchomieniowymi JavaScript i UIManagerami (pomyśl o JavaScriptCore, Xamarin.Mac, Linux Gtk# i opcjach Samsung Tizen).
Praca nad przełomową funkcją DetoxInstruments okazuje się bardzo wymagającym zadaniem. Tworzenie śladu stosu JavaScript w dowolnym momencie wymaga niestandardowej implementacji JSCore obsługującej zawieszanie wątku JS. Testy profilera wewnętrznie w aplikacji Wix ujawniły ciekawe wnioski dotyczące wątku JS.
Projekt nadal nie jest wystarczająco stabilny do ogólnego użytku, ale trwają nad nim aktywne prace i mamy nadzieję wkrótce go ogłosić.
Tempo rozwoju wersji 2 znacząco przyspieszyło. Dotychczas tylko jeden programista pracował nad projektem przez 20% swojego czasu, obecnie trzech programistów pracuje nad nim na pełen etat!
Wydajność Androida
Zastąpienie starego JSCore dołączonego do RN jego najnowszą wersją (szczytową wersją projektu webkitGTK z niestandardową konfiguracją JIT) przyniosło 40% wzrost wydajności wątku JS. Kolejnym krokiem jest kompilacja wersji 64-bitowej. Prace te opierają się na skryptach budujących JSC dla Androida. Aktualny status można śledzić tutaj.
Trwała dyskusja na temat przekształcenia tych spotkań w dyskusje skupione na jednym konkretnym temacie (np. nawigacja, przenoszenie modułów React Native do oddzielnych repozytoriów, dokumentacja, ...). Wierzymy, że w ten sposób najlepiej przysłużymy się społeczności React Native. Zmiana może nastąpić już podczas kolejnego spotkania. Zachęcamy do podzielenia się na Twitterze tematami, które chcielibyście zobaczyć.
Pracowaliśmy nad ciągłą integracją (CI) React Native. Najważniejsze, że migrowaliśmy z Travisa na Circle, zapewniając React Native jednolity, spójny proces CI.
Kontynuujemy prace nad Haul. W zeszłym miesiącu wydaliśmy dwie nowe wersje, w tym wsparcie dla webpacka 3. Planujemy dodać obsługę CRNA i Expo oraz ulepszyć HMR. Nasz plan rozwoju jest publicznie dostępny w systemie śledzenia problemów. Jeśli chcesz zgłosić sugestie lub opinię, daj nam znać!
Wydano Expo SDK 22 (oparte na React Native 0.49) i zaktualizowano CRNA.
Zawiera ulepszone API ekranu startowego, podstawowe wsparcie ARKit, API "DeviceMotion", obsługę SFAuthenticationSession w iOS11 oraz więcej.
Twoje snacki mogą teraz zawierać wiele plików JavaScript, a obrazy i inne zasoby możesz przesyłać przeciągając je do edytora.
Wspieraliśmy rozwój react-navigation dodając obsługę iPhone'a X.
Skupiamy się na wygładzaniu niedoskonałości przy budowaniu dużych aplikacji w Expo. Przykładowo:
Wsparcie najwyższej klasy dla wdrażania w wielu środowiskach: staging, produkcja i dowolne kanały. Kanały będą obsługiwać wycofywanie wersji i ustawianie aktywnej wersji dla kanału. Daj znać jeśli chcesz być testerem wczesnej wersji: @expo_io.
Pracujemy też nad ulepszeniem infrastruktury budowania samodzielnych aplikacji oraz dodajemy możliwość dołączania obrazów i innych zasobów niebędących kodem, przy zachowaniu możliwości aktualizacji zasobów przez sieć.
Znaczenie "left" i "right" było zamienione w układach RTL dla stylów pozycji, marginesów, dopełnienia i obramowania. W ciągu kilku miesięcy usuniemy to zachowanie - "left" zawsze będzie oznaczać lewą stronę, a "right" prawą. Zmiany łamiące kompatybilność są ukryte pod flagą. Użyj I18nManager.swapLeftAndRightInRTL(false) w komponentach React Native, aby je włączyć.
Pracujemy nad typowaniem naszych wewnętrznych modułów natywnych w Flow i wykorzystujemy to do generowania interfejsów w Javie oraz protokołów w ObjC, które muszą implementować natywne implementacje. Mamy nadzieję, że ten system generowania kodu stanie się open source najwcześniej w przyszłym roku.
Usprawniamy proces rozwoju na platformie Shoutem. Chcemy uspójnić ścieżkę od tworzenia aplikacji do pierwszej niestandardowej ekranu, obniżając próg wejścia dla nowych developerów React Native. Przygotowaliśmy warsztaty testujące nowe funkcje. Ulepszyliśmy również Shoutem CLI pod kątem nowych przepływów.
Shoutem UI otrzymało ulepszenia komponentów i poprawki błędów. Sprawdziliśmy też kompatybilność z najnowszymi wersjami React Native.
Platforma Shoutem zyskała istotne aktualizacje, a nowe integracje są dostępne w ramach projektu rozszerzeń open source. Cieszymy się widząc aktywny rozwój rozszerzeń Shoutem przez innych developerów. Aktywnie kontaktujemy się z nimi, oferując porady i wsparcie.