Android WYKŁAD 3
Agenda Odtwarzanie stanu Activity Walidacja danych z widoków Przycisk "wstecz" Material Design Fragmenty Implementacja GUI opartego o zakładki Stylowanie aplikacji Implementacja listy Operacje IO: SharedPreferences Zapis odczyt z Internal i External Storage
Odtwarzanie stanu Activity Cel: Odtworzenie stanu Activity w przypadku jego wyłączenia przez system lub zmiany ekranu wywołanej np. zmianą orientacji telefonu Domyślnie stan każdego widoku jest zapisywany, dzięki czemu "layout przetrwa". Automatyczny zapis działa tylko dla widoków z własnym unikalnym ID! Dodatkowe dane mogą zostać zapisane dzięki implementacji metod: protected void onSaveInstanceState(Bundle outState); protected void onRestoreInstanceState(Bundle savedInstanceState);
Odtwarzanie Activity
Walidacja danych z widoków 5
6
Walidacja danych z widoków podczas wprowadzania Gdzieś w MainActivity Wyrażenie regularne: Dowolna ilość małych i dużych liter
Walidacja danych z widoku – typ wyświetlanej klawiatury android:inputType="phone"android:inputType="textPassword" android:inputType="number" android:inputType="time"
Podpięcie się pod przycisk "wróć"
Material design Nazwa filozofii tworzenia GUI, która przyświecać ma przy projektowaniu środowisk komputerowych i mobilnych Zalecenia co do tworzenia GUI, zachowania widoków, kolorystyki, ikon, typografii itd. Wspierana od Android 5.0 (API 21) poprzez nowe typy widoków Obecny w wielu na wielu innych platformach: Angular Material (angular), bootstrap-material-design (Bootstrap), Material Design In XAML Toolkit (C#), Jfoenix (Java)
Material Design - przygotowanie By wykorzystać widoki zgodne z Material Design w aplikacji należy w app/build.gradle dodać bibliotekę design suport do sekcji "zależności" Upewnić się, że aplikacja tworzona jest dla Androida >= 5.0 (API 23)
Fragmenty Fragment reprezentuje porcję (moduł, część) Activity. Fragmenty posiadają własny cykl życia, własne eventy. Można je dodawać i usuwać z aktywności w trakcie działania Powstały by tworzyć dynamiczne GUI w zależności od parametrów ekranu urządzeń bez konieczności martwienia się o jego dostosowywanie Fragmenty powinny być tworzone tak by możliwe było ich powtórne użycie
Tworzenie fragmentu Trzy identyczne fragmenty z różną zawartością
TabFragment1.java fragment_tab_fragment1.xml Fragment – pojedyncza zakładka
FragmentPageAdapter Klasa odpowiedzialna za zarządzanie fragmentami na zakładkach W zależności od Numeru strony zwraca dany fragment Ilość zakładek == ilości fragmentów do wyświetlenia Etykiety zakładek
Obsługa zakładek – widok Activity Umiejscowienie po osi Z Trick: Poprzez ustalenie takiego samego elevation możliwe jest zakrycie cienia poszczególnych komponentów
Obsługa zakładek – MainActivity.java Podłączenie stworzonego adaptera (kontrolera zakładek) z widokiem viewPage Podłączenie viewPagera z tablayoutem ADAPTERViewPager TabLayout Osobna metoda, by nie robić bałaganu w onCreate
Efekt…
onTabSelectedListener Zwraca numer zaznaczonej zakładki Po dodaniu własnego Listenera należy wykonać akcję podmiany strony samemu! Podczas opuszczania strony Po zaznaczeniu zakładki na której już jesteśmy Po przejściu na nową zakładkę
Stylowanie globalne aplikacji \app\src\main\res\values\styles.xml przechowuje style wizualne widoków \app\src\main\res\values\colors.xml definiuje kolory użyte w stylach Źródło: Odnośnik do colors.xml Styl bazowy
ThemeEditor – edytor styli
Lista w Material Design RecyclerView – bardziej rozbudowana wersja ListView, elastyczna klasa przeznaczona do wyświetlania nawet ogromnych porcji danych Zależności: app\build.gradle
ToDoItem - model Reprezentacja pojedynczego wpisu na liście (tzw. model)
CardView – layout/item.xml CardView – wygląd i zachowanie pojedynczego wpisu na liście
RecyclerView Reprezentacja listy. Umieszczamy na layoucie w miejscu gdzie ma się wyświetlić lista – najczęściej wypełnia całe activity LayoutManager – odpowiedzialny za pozycjonowanie elementów na liście. Można definiować swoje, lub wykorzystać wbudowane: LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager Linear Grid Staggered
ViewHolder Wzorzec reprezentujący widok. Powtał by ograniczyć ilość wywołań findViewById
Adapter (Wrapper, Opakowanie) - ogólnie - wzorzec projektowy, którego celem jest umożliwienie współpracy dwóm klasom o niekompatybilnych interfejsach. W omawianym przypadku klasa Adapter jest pomostem między listą obiektów (List<>) a RecyclerView Klasa dziedzicząca po RecyclerView.Adapter w naszym przypadku po: RecyclerView.Adapter Należy zaimplementować: ToDoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) Miejsce na inicjalizację naszego ViewHolder’a void onBindViewHolder(ToDoViewHolder holder, int position) Łączy widok (kontrolkę) z polem klasy int getItemCount() Zwraca ilość elementów na liście
Adapter
MainActivity – połączenie wszystkiego w całość Obrazki z folderu drawable
Efekt
Animacja za pomocą ItemTouchHelper Cel: swipe w lewo – oznacz jako zrobione (pokoloruj na zielono) Swipe w prawo – usuń Poprawki: ToDoAdapter: ToDoViewHolder: Usuwa element z list Uaktualnia stan adaptera. WAŻNE!
Dodanie nowej funkcjonalności Swipe w prawo i lewo Metoda obsługująca zmianę położenia w pionie Zwraca pozycje na liście Kolor z zasobów Zmienia tło Aktualizuje listę! WAŻNE! Dołącza callbacki do RecycleView
Efekt
SharedPreferences Zapis prostych typów (int, float, double, string) do pliku Brak konieczności ręcznego odczytu danych (parsowania) Metoda zapisu: Klucz-Wartość Zalecane do zapisu małej ilości danych 34
SharedPreferences 35
SharedPreferences 36 MODE_PRIVATE MODE_WORLD_READABLE MODE_WORLD_WRITEABLE putInt, putLong, putBoolean, putStringSet, putFloat
Zapis i odczyt z pliku Gdzie możemy zapisać plik: Wewnętrzny magazyn (Internal storage) – pamięć wbudowana Zewnętrzny magazyn (External storage) – Karta SD Zawsze dostępnaNie zawsze dostępna Pliki zapisane przez naszą aplikację mogą być czytane domyślnie tylko przez nas Zapisane pliki są dostępne publicznie Podczas usuwania aplikacji usuwają się zawsze wszystkie zapisane pliki Pliki usuną się tylko jeśli zostały zapisane w ścieżce zwróconej przez getExternalFilesDir()
Zapis i odczyt z pliku w wewnętrznym magazynie ODCZYT ZAPIS MODE_PRIVATE – tryb domyślny MODE_APPEND – dopisanie MODE_WORLD_READABLE – mogą czytać inne aplikacje MODE_WORLD_WRITEABLE – mogą zapisywać inne aplikacje openFileOutput("mytextfile.txt", MODE_PRIVATE|MODE_APPEND); getFilesDir() – zwraca folder zapisu plików w magazynie Np. /data/user/0/[package]/files
Zapis i odczyt z pliku w zewnętrznym magazynie Uprawnienia do zapisu/odczytu w zewnętrznym magazynie \app\src\main\AndroidManifest.xml Czy w ogóle magazyn zewnętrzny istnieje?
Zapis i odczyt z pliku w zewnętrznym magazynie Nowy tryb bezpieczeństwa w Android 6 (API 23) wymaga manualnego poproszenia o przyznanie praw zapisu do zewnętrznego magazynu
Zapis i odczyt z pliku w zewnętrznym magazynie Zapis /storage/emulated/0 Metoda sprawdzająca czy użytkownik zezwolił na zapis
Zapis i odczyt z pliku w zewnętrznym magazynie Odczyt Metoda sprawdzająca czy użytkownik zezwolił na odczyt
Poprawne zarządzanie uprawnianiami w Androidzie 6 Metoda w Activity która otrzymuje odpowiedź (Response) Wzorzec Request/Response, w którym identyfikujemy żądania kodem (int) Sprawdzamy uprawniania aplikacji… Jeśli ich nie mamy (jeszcze) to prosimy o pozwolenie… Powinniśmy zawsze zareagować na odpowiedź użytkownika i wyłączyć część funkcjonalności, jeśli nie mamy prawa ich używać. W przeciwnym wypadku aplikacja wywoła wyjątek: permission denied