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
Walidacja danych z widoków 6
Walidacja danych z widoków podczas wprowadzania Wyrażenie regularne: Dowolna ilość małych i dużych liter Gdzieś w MainActivity
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) https://design.google.com/#resources
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ą
Fragment pojedyncza zakładka TabFragment1.java fragment_tab_fragment1.xml
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 ADAPTER ViewPager TabLayout Osobna metoda, by nie robić bałaganu w oncreate Podłączenie stworzonego adaptera (kontrolera zakładek) z widokiem viewpage Podłączenie viewpagera z tablayoutem
Efekt
ontabselectedlistener Po przejściu na nową zakładkę 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
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 Styl bazowy Odnośnik do colors.xml Źródło: http://www.viralandroid.com/2015/08/android-custom-material-design-theme-color.html
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<ViewHolder> w naszym przypadku po: RecyclerView.Adapter<ToDoViewHolder> 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: Usuwa element z list Uaktualnia stan adaptera. WAŻNE! ToDoViewHolder:
Dodanie nowej funkcjonalności Swipe w prawo i lewo Metoda obsługująca zmianę położenia w pionie Zmienia tło Aktualizuje listę! WAŻNE! Zwraca pozycje na liście Kolor z zasobów 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 MODE_PRIVATE MODE_WORLD_READABLE MODE_WORLD_WRITEABLE putint, putlong, putboolean, putstringset, putfloat 36
Zapis i odczyt z pliku Gdzie możemy zapisać plik: Wewnętrzny magazyn (Internal storage) pamięć wbudowana Zawsze dostępna Pliki zapisane przez naszą aplikację mogą być czytane domyślnie tylko przez nas Zewnętrzny magazyn (External storage) Karta SD Nie zawsze dostępna 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()
ODCZYT Zapis i odczyt z pliku w wewnętrznym magazynie getfilesdir() zwraca folder zapisu plików w magazynie Np. /data/user/0/[package]/files 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);
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 Metoda sprawdzająca czy użytkownik zezwolił na zapis /storage/emulated/0
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 Wzorzec Request/Response, w którym identyfikujemy żądania kodem (int) Sprawdzamy uprawniania aplikacji Jeśli ich nie mamy (jeszcze) to prosimy o pozwolenie Metoda w Activity która otrzymuje odpowiedź (Response) 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