Metoda onDraw w Androidzie – DSP#10

Aplikacje służące do rysowania palcem po ekranie to jeden z pierwszych, które piszemy przechodząc samouczki (przynajmniej te, na platformy mobilne). Co ciekawe, w Androidze zarówno tworzenie widoków jak i rysowanie palcem jest obsługiwane przez ten sam zestaw klas. W przypadku rysowania mamy płótno, obiekt pędzla i metodę typu onTouch(). W przypadku tworzenia widoków metody narysuj kwadrat, narysuje linię, etc..

Wspólną dla obu tych podejść jest metoda onDraw(), która jak sama nazwa wskazuje służy do rysowania. A tak wyglądają efekty moich ostatnich prac:

Istna sztuka współczesna, jak by co można składać oferty 😉 A teraz co się tutaj właściwie dzieje? Tło tego widoku pochodzi z klasy MainActivity, w której wszystko testuję:

Z kolei ten różowy kolor pochodzi z pliku xml definiującego layout, również w testowej aplikacji:

Nie przetestowałem jeszcze wszystkich atrybutów, na to będzie czas później, ale póki co z umiarkowanym optymizmem można założyć, że będzie dobrze.

A teraz przejdźmy do mięska, wklejam kod odpowiedzialny za narysowanie tych fragmentów:

Do góry zostały zdefiniowane nowe obiekty typu Paint, które będą odpowiadały za właściwości graficzne wszystkich obiektów tego widoku, poniżej znajdują się kolory, które już pokazywałem, ale tym razem zostały rozbudowane o settery. Tzn settery dla tych obiektów istniały cały czas, ale w momencie dodania poniżej zmiennej dyrektywy set, można napisać zmodyfikowany setter. W moim znajduje się dyrektywa field = value która oznacza przypisz wartość do pola. Nie musimy podawać nazwy pola, mam zdefiniowane w Kotlinie słówko field. Następnie definiujemy kolor obiektowi typu Paint. A także wywołujemy invalidate() które jest odpowiedzialne za ponowne narysowanie obiektów. Tutaj uwaga, którą będę musiał dodać do readme projektu, w przypadku gdyby te operacje odbywały się po za wątkiem UI (głównym w Androidzie) należy wywołać metodę postInvalidate(). Kolejnym nowym elementem jest metoda init() wywoływana w konstruktorze. Użycie jej jest zalecane, ponieważ metoda onDraw() może być wywoływana bardzo często i dlatego tworzenie w niej za każdym razem obiektów typu Paint mogłoby negatywnie wpłynąć na wydajność. W ciele metody init znajduje się przypisywanie parametrów obiektom Paint, ta metoda na pewno zostanie jeszcze rozbudowana.

Przejdźmy do samego rysowania, odpowiada za to ten kawałek kodu:

Metoda drawPaint() odpowiada po prostu za rysowanie zgodnie z wytycznymi znajdującymi się w obiekcie Paint. Dzięki temu jest idealna do np, wypełnienia tła. Z kolei drawRect() rysuje prostokąty, natomiast drawRectF() prostokąty z zaokrąglonymi rogami. Są 2 powody, dla których nie mogę użyć tej metody:

  • Adnotacja „NewApi” oznacza tyle, że ta metoda nie jest kompatybilna ze wszystkimi wersjami androida dla których udostępnię bibliotekę (z dokumentacji wynika, że ta metoda pojawiła się w API 21)
  • Ta metoda rysuje zaokrąglenia do góry i na dole, a ja potrzebował bym tylko do góry.

Tym problemem zajmę się w następnych tygodniach, jak i tym, żeby prawidłowo obsługiwać rozmiary i ustawienia elementów, do czego służą metody onSizeChanged() oraz onMeasure().

To tyle, jeśli chodzi o podstawy rysowania w Androidzie. Całość została zaccomitowana jako „drawing” i wszystkie bieżące zmiany można podejrzeć na githubie pod tym linkiem.

  • Te settery w ten sposób definiowane to nadpisują settera na konkretnej instancji obiektu, dobrze rozumiem ? W sensie na przypisaniu wartości do tej jednej zmiennej ?

    • migellal

      Tak, właśnie tak to działa 😉 Za darmo w Kotlinie dostajesz setter o kodzie: „field = value” Jeśli chcesz coś więcej, to piszesz set pod wartością i definiujesz sobie co tam potrzeba. Dodatkowo ukrycie settera, albo gettera uzyskamy przez dodanie modyfikatora private przed get lub set.