Pokazywanie postów oznaczonych etykietą Android. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą Android. Pokaż wszystkie posty

czwartek, 20 sierpnia 2020

Android Basics - User Interface

Tego kursu wcześniej nie słuchałam i jak teraz usłyszałam, że to dla kogoś, kto nigdy nie napisał ani jednej linijki kodu, to zaczęłam wątpić...

Ale dobrze, pomyślałam, przekonaj się, że to umiesz, a przy okazji może usłyszysz jakąś informację, o której nie wiesz. I tak dowiedziałam się o:

  • atrybucie android:textAppearance="?android:textAppearanceSmallInverse"  , którego mogę użyć, gdy nie będę wiedzieć jaki rozmiar czcionki wybrać
  • atrybucie layout_weight, który może wystąpić w LinearLayout przy layout_width="0dp", a jego wartość określa jaką częścią całości jest dany element (sumuje się wartości tego atrybutu u wszystkich dzieci rodzica i proporcjonalnie rozdysponowuje się miejsce)
  • RelativeLayout - gdy robiłam kurs mniej podstawowy, ten layout był pominięty, zastąpiony ConstraintLayout, okazuje się, że są bardzo podobne a atrybutem typu android:layout_toLeftOf lub  android:layout_below można ustawiać elementy obok siebie

Tak więc:
  • da się sensownie podzielić ekran bez wartości procentowych Guideline w ConstraintLayout
  • to, co ma być wyświetlane na ekranie nie musi być od razu w całoścu widoczne - mogę użyć ScrollView i wewnątrz niego zaprojektować ciekawy układ elementów

Liczyłam na to, że dowiem się coś ciekawego o projektowaniu ekranów. Początkowo byłam sceptyczna, bo nie jestem aż tak początkująca, ale ogólnie warto było obejrzeć, ponieważ pojawiło się wiele przykładów i często omawiane było, dlaczego warto zastosować takie a nie inne podejście.

Kurs, o którym piszę znajduje się tutaj.

środa, 19 sierpnia 2020

Jak dopasować style tekstu - wnioski z Material Design

Jak się okazuje, AndroidStudio ma zaimplementowane style wg Material Design, tylko nigdy nie dałam sobie czasu na to, żeby się w tym zorientować. To teraz już wiem :)
Planowałam te style przenieść do mojego projektu wpisując wszystkie dane, zgodnie z informacjami, a już nie muszę, bo tam wszystko jest. Tylko kroje czcionek zmieniłam.

I teraz wskazówki z tamtej strony (są tam też ciekawe, dobrze ilustrujące zagadnienia przykłady):

  • Nagłówki 
    • to krótkie, ważne teksty,
    • wyraźne, ciekawe kroje czcionek,
    • mniejsze nagłówki będą lepiej wyglądać w spokojniejszym kroju czcionki.
  • Podtytuły
    • mniejsze od nagłówków,
    • krókie teksty,
    • wyraźne kroje czcionek.
  • Treść
    • długa forma,
    • wyraźne kroje czcionek.
  • Podpisy
    • mogą być pod lub nad,
    • dotyczą tekstu, tytułu lub obrazu,
    • najmniejszy rozmiar czcionki,
    • proste, wyraźne kroje czcionek.
  • Przycisk
    • często allCaps,
    • często sans serif,
    • powinien być wyraźny, widoczny, dawać jasno do zrozumienia co robi.
  • Wyrównanie tekstu
    • Najczęściej do lewej
    • Cytaty wyśrodkowane, nie bardzo długie

O typografii z Material Design jest tutaj.

czwartek, 13 sierpnia 2020

Zmiana myślenia

Choć pozornie nie ma to nic wspólnego z programowaniem, od 4 tygodni realizuję program Droga Artysty. Bardzo polecam, to chyba najlepszy program rozwojowy, w jakim brałam udział. A możę pierwszy, za który wzięłam się na poważnie?

Tak czy inaczej - on oraz mój zespół Mastermind pomogli mi odkryć moją największą blokadę.

Ja NIE MOGĘ być programistą

Taka myśl, za każdym razem w mojej głowie. I nie chodzi o to, że nie będę dobrym programistą, czy idealnym, że nie w jakomś języku. Wcale. Nie mogę i już. Nie moja ścieżka, nie moje miejsce. NIE. Wstęp wzbroniony, możesz sobie siedzieć  IT, zajmować się czymkolwiek, ale tego nie wolno dotknąć. Jak Drzewo Poznania Dobra i Zła. A ja się słuchałam, nie moje, to nie. Czy kusiło? Nie wiem. Lubiłam inne rzeczy, lubiłam to, co robiłam.

Aż do środy, 3 tygodnie temu, kiedy uświadomiłam sobie, skąd to się wzięło i dlaczego to jest takie złe.

A zatem się z tego uwalniam, wróciłam do kursu, zaplanowałam kolejne. Wymyśliłam jak wykorzystam wiedzę w praktyce. 

Jest lepiej, serio. Jeśli Cię coś blokuje i nie masz z kim pogadać - napisz do mnie, zrozumiem Cię :)


Zapiszę sobie jeszcze co sobie przypomniałam powtarzając pierwszy moduł kursu (już to umiałam, tylko zapomniałam):

  • Używaj najprostrzego layoutu w kolejności:
    • Frame
    • Linear
    • Constrain
  • Ustawianie tekstu w TextView:
    • setText - wpisuje nową wartość
    • append - dodaje wartość do tego co już było

środa, 1 stycznia 2020

Jak zrobić aplikację bez górnego paska tytułowego?

W głównym stylu aplikacji należy dodać:

        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>


Plik styles.xml może wtedy wyglądać tak:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:fontFamily">@font/italianno</item>
        <item name="android:textColor">@color/black</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
    </style>

</resources>

czwartek, 28 lutego 2019

Dobre praktyki - Lekcja 1


  1. Testuj małe elementy - im mniej, tym lepiej, nawet jeśli to tylko zmiana koloru - upewnij się, że się zmienił tam gdzie powinien.
  2. Testuj małe elementy - nawet jeśli nie powodują widocznej zmiany wyglądu lub zachowania - sprawdzaj, czy nic nie popsuły.
  3. Czytaj materiały branżowe regularnie - warto się uczyć od innych.
  4. Porządnie planuj - najpierw zgrubnie, później coraz dokładniej, im mniejsze zadania tym łatwiej je wykonać nawet przy zmęczeniu.
  5. Usuwaj logi, których nie potrzebujesz.
  6. Upewnij się, że element, którego używasz !=null

niedziela, 5 sierpnia 2018

Room - kilka słów o przechowywaniu danych

  1. Dodaj odpowiednie zależności do build.gradle(Module: app)
    def room_version = "1.1.1"
    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version"
    testImplementation "android.arch.persistence.room:testing:$room_version"
  2. Zsynchronizuj build.gradle
    1. kliknij prawym przyciskiem na build.gradle
    2. wybierz Synchronize build.gradle
  3. Dodaj klasę obiektu, który będzie reprezentował tabelę
    1. Daj jej annotację @Entity
    2. Dodaj kolumnę @PrimaryKey
    3. Dodaj pozostałe kolumny
    4. Dodaj gettery i settery elementów obiektu (na potrzeby Room)
      @Entity
      public class StoryObject {
          @PrimaryKey
          private int storyId;
          @ColumnInfo(name = "main_text")
          private String mainText;
  4. Stwórz interfejs z metodami dostępu do bazy - DAO
    1. Daj jej annotację @Dao
    2. Dodaj metody dostępu (napisane w SQL)
      @Dao
      public interface StoryDao {
          @Query("SELECT * FROM story")
          List<StoryObject> getAll();
          @Insert
          void insertAll(StoryObject... objects);
          @Delete
          void delete(StoryObject object);
      }
  5. Stwórz klasę (abstract) bazy danych
    1. Dodaj jej annotację @Database i przypisz klasy, które ją reprezentują (entities)
    2. Dodaj metodę (abstract), która zwróci odpowiedni obiekt Dao
      @Database(entities = {StoryObject.class}, version = 1)
      public abstract class StoryDatabase extends RoomDatabase {
          public abstract StoryDao getStoryDao();
      }
  6. W kodzie aplikacji wywołaj budowanie bazy danych
    StoryDatabase db = Room.databaseBuilder(getApplicationContext(),
            StoryDatabase.class, "story_database").build();

sobota, 28 lipca 2018

Android - testy wydania

Kilka dni temu wysłałam kolejną wersję aplikacji, jeszcze ciągle w wersji próbnej, testowej, w trakcie pracy. Ogólnie wydawałoby się - nic poważnego. Ale jednak wysłałam ją komuś - to jest poważne, powinnam być za to odpowiedzialna. Zrozumiałam, że nie zrobiłam jej wcześniej absolutnie podstawowych testów wydania. Nawet nie mam przygotowanych... Pora to zmienić.

Testy wydania aplikacji - android (ogólne)

  1. Aplikacja aktualizuje się z poprzedniej wersji do nowej (update)
  2. Aplikacja w aktualnej wersji może być zainstalowana na "czystym" urządzeniu (na takim, na którym nie jest zainstalowana) (instal)
  3. Aplikacja po wybraniu ikony włącza się i pokazuje ekran startowy (start)
  4. Aplikacja po wybraniu przycisku cofinij wyłącza się (end)
  5. Aplikacja wykonuje podstawową funkcję (work)
  6. Aplikacja aktualizuje się do poprzedniej wersji (downgrade)

Testy wydania aplikacji - android (dodatkowe)

  1. Aplikacja działa bez internetu (internet permission)
    1. brak wyjątków
    2. informacja o braku połączenia
    3. niezakłócone działanie
  2. Aplikacja działa przy obracaniu ekranu (orientation)
    1. dźwięk
    2. obraz
    3. funkcje
  3. ...

sobota, 7 kwietnia 2018

Czy zawsze da się wrócić do zadania?

Ustawiając aplikacji niestandardowe atrybuty trzeba się upewnić, że do wszystkich rozpoczętych przez naszą aplikację zadań będzie można wrócić.

Czyli za każdym razem, gdy jakaś aktywność ma dla atrybutu launchMode wartość singleTask lub  singleInstance, aktywność ta powinna:
  • mieć zadeklarowane w manifeście (w tagu <intent filter>), że jest to 
    • aktywność główna - <action android:name="android.intent.action.MAIN" />
    • można się przez nią połączyć z zadaniem - <category android:name="android.intent.category.LAUNCHER" />
  • mieć ustawioną dla atrybutu finishOnTaskLaunch wartość false.

Mieszanie w zadaniu

Tryb włączania aktywności (activity) i ich powiązanie z aktualnym zadaniem (jeśli ma być jakiś nietypowy) można określić przez manifest lub przez kod aplikacji.

Żeby zmienić naturalny sposób obsługi zadania (task) można zadeklarować to w manifeście podając odpowiednie atrybuty do taga <activity>:
  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch
A w aplikacji można posłużyć się odpowiednimi flagami przy wywoływaniu aktywności:
  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP
W przypadku, gdy jedna aktywność wywołuje drugą i obie mają zadeklarowane w jaki sposób ta druga aktywność ma być powiązana z zadaniem, wyższy priorytet ma informacja od aktywności wywołującej.

Ważne - android doskonale radzi sobie ze swoimi zadaniami, kiedy mu się w tym nie przeszkadza. Mieszając w zadaniach należy bardzo dokładnie przetestować wszystkie przypadki cofania z różnych aktywności - upewnić się, że stos będzie odpowiednio obsłużony i aplikacja nie przestanie działać.

piątek, 30 marca 2018

Co to takiego jest to Affinity?

Koligacja (affinity) aktywności (activity) określa do jakiego zadania dana aktywność preferowanie należy.

Domyślnie jest taka sama dla wszystkich aktywności danej aplikacji i jej wartość określana jest przez nazwę paczki aplikacji. Dzięki temu wszystkie aktywności aplikacji są ze sobą powiązane i będą się otwierały w stosie (stack) tego samego zadania (task).

Koligację inną niż domyślna można ustawić zmieniając w manifeście wartość atrybutu taskAffinity dla wybranej aktywności. Wartość ta musi być inna niż nazwa paczki aplikacji (to jest domyślna wartość tego atrybutu).

Koligacja jest brana pod uwagę, gdy:
  • aktywność jest wywoływana z flagą FLAG_ACTIVITY_NEW_TASK - system sprawdza wtedy czy jest jakieś inne zadanie, którego aktywności mają tę samą koligację co wywoływana aktywność - jeśli tak, to aktywność jest do niego przypisywana, jeśli nie to wywoływana aktywność otwiera nowe zadanie
  • atrybut allowTaskReparenting dla danej aktywności ma wartość true - wtedy każde zadanie, z którym dana aktywność ma koligację, przechodząc do gółwnego wątku (foreground) przypisuje sobie na górę stosu i wyświetla tę aktywność
Koligacja przyda się również gdy paczka APK zawiera więcej niż jedną aplikację - wtedy można różne aplikacje odpowiednio ze sobą powiązać (jak mieć 2 aplikacje w jednym .apk - https://stackoverflow.com/questions/10682576/one-apk-file-that-installs-two-apps)

piątek, 23 marca 2018

Jak powiązać aktywność z zadaniem - launchMode

Przede wszystkim można zadeklarować w manifeście dla danej aktyności(activity) odpowiednią wartość atrybutu launchMode:
  • standard
    • za każdym razem tworzone jest nowe wywołanie (instance) danej aktywności w zadaniu (task)
    • aktywność może być obecna w różnych zadaniach - będzie miała swoje oddzielne wywołania w każdym zadaniu, dla którego te wywołania były stworzone
    • aktywność może mieć kilka wywołań w jednym zadaniu - tyle ile razy dana aktywność była wywoływana
  • singleTop
    • nowe wywołanie danej aktywności tworzone jest tylko wtedy, jeśli wywoływana aktywność nie jest aktualnie na górze stosu (top of the stack)
    • gdy onNewIntent() powoduje wywołanie aktywności, która już jest na górze stosu, wtedy zamiast dodania na stos nowego wywołania, obecna aktywność jest aktualizowana o dane, które zawiera wywołanie
    • aktywność może być obecna w różnych zadaniach - będzie miała swoje oddzielne wywołania w każdym zadaniu, dla którego te wywołania były stworzone
    • aktywność może mieć kilka wywołań w jednym zadaniu - tyle ile razy dana aktywność była wywoływana przez inną aktywność (gdy nie była na górze stosu)
  • singleTask
    • nowe wywołanie danej aktywności tworzone jest tylko wtedy, gdy nie ma jeszcze żadnego wywołania tej aktywności w żadnym z zadań, wtedy też tworzone jest nowe zadnie a ta aktywność staje się jego początkową aktywnością
    • gdy onNewIntent() powoduje wywołanie aktywności, która już jest w jakimś zadaniu, wtedy zamiast tworzenia nowego wywołania, obecna tam aktywność jest aktualizowana o dane, które zawiera wywołanie
    • w systemie może być tylko jedno wywołanie danej aktywności
    • przycisk wstecz przenosi użytkownika do poprzedniej aktywności (tej, która wywołała daną aktywność), pomimo iż zostało stworzone nowe zadanie
  •  singleInstance
    • nowe wywołanie danej aktywności tworzone jest tylko wtedy, gdy nie ma jeszcze żadnego wywołania tej aktywności w żadnym z zadań, wtedy też tworzone jest nowe zadnie a ta aktywność staje się jego początkową aktywnością
    • gdy onNewIntent() powoduje wywołanie aktywności, która już jest w jakimś zadaniu, wtedy zamiast tworzenia nowego wywołania, obecna tam aktywność jest aktualizowana o dane, które zawiera wywołanie
    • w systemie może być tylko jedno wywołanie danej aktywności
    • przycisk wstecz przenosi użytkownika do poprzedniej aktywności (tej, która wywołała daną aktywność), pomimo iż zostało stworzone nowe zadanie 
    • wywołanie nowej aktywności przez daną aktywność powoduje stworzenie nowego zadania - aktywność z atrybutem singleInstance jest jedyną aktywnością w zadaniu
Domyślnie atrybut launchMode przyjmuje wartość standard.

Dzięki takiej deklaracji aktywność (o ile nie zostanie wywołana inaczej) będzie się zawsze zachowywać w wyznaczony sposób.
Jeżeli aktywność jednorazowo ma się zachować inaczej zamiast deklarować to w manifeście można wywołać ją poleceniem startActivity() z wybraną flagą:
  • FLAG_ACTIVITY_NEW_TASK - zadziała analogicznie do atrybutu singleTask,
  • FLAG_ACTIVITY_SINGLE_TOP - zadziała analogicznie do atrybutu singleTop,
  • FLAG_ACTIVITY_CLEAR_TOP - jeżeli wywoływana aktywność ma już swoje wywołanie w aktywnym zadaniu, to wszystkie aktywności, które są na stosie ponad nią, zostają zamknięte a ona sama jest aktualizowana.

Poniżej podsumowanie w tabeli przy założeniu, że przedstawione atrybuty dotyczą aktywności A, a aktywność B ma atrybut standard.



aktywność A jest wywoływana przez aktywność B


aktywność A nie ma wywołania w systemie aktywność A ma wywołanie w systemie aktywność A jest wywoływana przez aktywność A aktywność A wywołuje aktywność B wstecz z aktywności A
standard tworzy się nowe wywołanie danej aktywności na górze stosu tworzy się nowe wywołanie danej aktywności na górze stosu tworzy się nowe wywołanie danej aktywności na górze stosu tworzy się nowe wywołanie danej aktywności na górze stosu powrót do poprzedniej aktywności ze stosu
singleTop tworzy się nowe wywołanie danej aktywności na górze stosu tworzy się nowe wywołanie danej aktywności na górze stosu istniejące wywołanie jest aktualizowane tworzy się nowe wywołanie danej aktywności na górze stosu powrót do poprzedniej aktywności ze stosu
singleTask tworzy się nowe wywołanie danej aktywności w nowym zadaniu istniejące wywołanie aktywności A jest aktualizowane i przechodzi do głównego wątku istniejące wywołanie jest aktualizowane tworzy się nowe wywołanie danej aktywności na górze stosu powrót do poprzedniej aktywności z zadania, które wywołało aktywność A
singleInstance tworzy się nowe wywołanie danej aktywności w nowym zadaniu istniejące wywołanie aktywności A jest aktualizowane i przechodzi do głównego wątku istniejące wywołanie jest aktualizowane tworzy się nowe wywołanie danej aktywności w nowym zadaniu powrót do poprzedniej aktywności z zadania, które wywołało aktywność A

środa, 21 marca 2018

Kilka słów o taskach

Zadanie (Task) to zbiór aktywności (Activity) ułożony w stos (stack) tak, żeby klikając przycisk "wstecz" można było cofnąć się do poprzedniej aktywności (back stack). Zbiór ten jest aktywny dla każdej uruchomionej aplikacji, dopóki nie zostanie zamknięty - ale na prawdę zamknięty. System przechowuje w tle (background) otwarte zadania dla wielu uruchomionych aplikacji, chyba, że użytkownik (lub coś innego) świadomie i celowo (lub wskutek błędu) zadanie zamknie.
Przy kliknięciu ikony aplikacji system przywraca z tła do głównego wątku (foreground) istniejące dla danej aplikacji zadanie lub tworzy nowe zadanie jeśli aplikacja nie ma otwartego zadania.

System utrzymuje w tle wiele zadań - tak wiele, jak jest w stanie. W pewnym momencie otwartych zadań robi się tak wiele, że system musi, dla poprawy pamięci, jakieś zadanie zamknąć. Warto o tym pamiętać pisząc aplikację - takie niespodziewane zamknięcie może spowodować w aplikacji błędy i utratę danych, jesli się przed tym nie zabezpieczymy.

System obsługuje każde z zadań oddzielnie, a w przypadku urządzeń, które mogą wyświetlać więcej niż 1 okno (multi-windowed environment, Chromebooks) zadania utrzymywane są oddzielnie
dla każdego okna.

Stos w aplikacji jest zbiorem aktywności działającym zgodnie z zasadą LIFO (Last In First Out).Przy uruchomieniu aplikacji na stos trafia główna aktywność (main activity). Kiedy aktualna aktywność wywołuje kolejną - kolejna trafia na stos nad tę aktywność, która ją wywołała.
Zawsze wyświetlana i działająca jest aktywność z góry stosu.
Przycisk cofnięcia powoduje zakończenie i zamknięcie aktualnej aktywności oraz pobranie i wyświetlenie kolejnej, która znajdowała się pod stosem pod nią.
Stos nie zmienia kolejności aktywności, które w nim są - aktywność może tylko być wprowadzona na wierzch stosu (push) lub usunięta z wierzchu stosu (pop).
Przycisk "wstecz" usuwa po kolei wszystkie aktywności ze stosu i gdy stos jest pusty, zadanie przestaje istnieć. Usunięcie ostatniej aktywności ze stosu przenosi użytkownika do głównego ekranu (home) lub do aplikacji, która to zadanie aktywowała.
Stos przechowuje każde wywłoanie aktywności - to znaczy, że jeśli aplikacja jest tak zbudowana, że dana aktywność jest wywoływana kilkukrotnie w trakcie działania aplikacji, to na stosie znajdą się wszystkie wywołania z ich aktualnym stanem.