Rysowanie na obiektach Canvas

Te warsztaty są częścią kursu Zaawansowany Android w Kotlinie. Najwięcej korzyści z tego kursu uzyskasz, jeśli przejdziesz wszystkie ćwiczenia w kolejności, ale nie jest to obowiązkowe. Wszystkie ćwiczenia z tego kursu znajdziesz na stronie docelowej ćwiczeń z zaawansowanego Androida w Kotlinie.

Wprowadzenie

Android udostępnia kilka metod implementowania w widokach niestandardowej grafiki 2D i animacji.

Oprócz korzystania z elementów rysowalnych możesz tworzyć rysunki 2D za pomocą metod rysowania klasy Canvas. Canvas to dwuwymiarowa powierzchnia do rysowania, która udostępnia metody rysowania. Jest to przydatne, gdy aplikacja musi regularnie odświeżać swój widok, ponieważ to, co widzi użytkownik, zmienia się z czasem. Z tego ćwiczenia w Codelabs dowiesz się, jak utworzyć i narysować obraz na płótnie wyświetlanym w View.

Rodzaje operacji, które możesz wykonać na obszarze roboczym:

  • Wypełnij całe płótno kolorem.
  • Rysuj kształty, takie jak prostokąty, łuki i ścieżki, w stylu zdefiniowanym w obiekcie Paint. Obiekt Paint zawiera informacje o stylu i kolorze rysowanych geometrii (np. linii, prostokątów, owali i ścieżek) lub np. o kroju czcionki tekstu.
  • stosować przekształcenia, takie jak tłumaczenie, skalowanie lub przekształcenia niestandardowe;
  • Przycinanie, czyli stosowanie kształtu lub ścieżki do obszaru roboczego w celu określenia jego widocznych części.

Jak można wyobrazić sobie rysowanie na Androidzie (w bardzo uproszczony sposób)

Rysowanie na Androidzie lub w dowolnym innym nowoczesnym systemie to złożony proces, który obejmuje warstwy abstrakcji i optymalizacji aż do poziomu sprzętu. Sposób rysowania w Androidzie to fascynujący temat, o którym napisano już wiele artykułów. Szczegóły tego procesu wykraczają jednak poza zakres tych zajęć.

W kontekście tego laboratorium i aplikacji, która rysuje na płótnie, aby wyświetlać obraz na pełnym ekranie, możesz to sobie wyobrazić w ten sposób:

  1. Potrzebujesz widoku, w którym będzie wyświetlane to, co rysujesz. Może to być jeden z widoków udostępnianych przez system Android. W tych ćwiczeniach z programowania utworzysz niestandardowy widok, który będzie służyć jako widok treści aplikacji (MyCanvasView).
  2. Ten widok, podobnie jak wszystkie inne, ma własny obszar roboczy (canvas).
  3. Najprostszy sposób rysowania na obszarze widoku polega na zastąpieniu metody onDraw() i rysowaniu na jego obszarze.
  4. Podczas rysowania budynku musisz zapisać w pamięci podręcznej to, co zostało narysowane wcześniej. Istnieje kilka sposobów buforowania danych. Jednym z nich jest bitmapa (extraBitmap). Innym jest zapisywanie historii rysowania w postaci współrzędnych i instrukcji.
  5. Aby rysować na bitmapie pamięci podręcznej (extraBitmap) za pomocą interfejsu API do rysowania na płótnie, utwórz płótno pamięci podręcznej (extraCanvas) dla bitmapy pamięci podręcznej.
  6. Następnie rysujesz na obszarze roboczym pamięci podręcznej (extraCanvas), co powoduje rysowanie na mapie bitowej pamięci podręcznej (extraBitmap).
  7. Aby wyświetlić wszystko, co zostało narysowane na ekranie, musisz poinformować obszar roboczy widoku (canvas), aby narysował bitmapę pamięci podręcznej (extraBitmap).

Co warto wiedzieć

  • Jak utworzyć aplikację z aktywnością i podstawowym układem oraz uruchomić ją w Android Studio.
  • Jak powiązać procedury obsługi zdarzeń z widokami.
  • Jak utworzyć widok niestandardowy.

Czego się nauczysz

  • Jak utworzyć Canvas i rysować na nim w odpowiedzi na dotyk użytkownika.

Jakie zadania wykonasz

  • Utwórz aplikację, która rysuje linie na ekranie w odpowiedzi na dotyk użytkownika.
  • Rejestruj zdarzenia ruchu i w odpowiedzi rysuj linie na płótnie wyświetlanym na ekranie w niestandardowym widoku pełnoekranowym.

Aplikacja MiniPaint używa niestandardowego widoku do wyświetlania linii w odpowiedzi na dotyk użytkownika, jak pokazano na zrzucie ekranu poniżej.

Krok 1. Tworzenie projektu MiniPaint

  1. Utwórz nowy projekt w Kotlinie o nazwie MiniPaint, który korzysta z szablonu Empty Activity (Puste działanie).
  2. Otwórz plik app/res/values/colors.xml i dodaj te 2 kolory.
<color name="colorBackground">#FFFF5500</color>
<color name="colorPaint">#FFFFEB3B</color>
  1. Otwórz aplikację styles.xml
  2. W nadrzędnym stylu AppTheme zastąp DarkActionBar wartością NoActionBar. Spowoduje to usunięcie paska działań, dzięki czemu możesz rysować na pełnym ekranie.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

Krok 2. Tworzenie klasy MyCanvasView

W tym kroku utworzysz niestandardowy widok MyCanvasView do rysowania.

  1. W pakiecie app/java/com.example.android.minipaint utwórz Nowy > Plik/klasa Kotlin o nazwie MyCanvasView.
  2. Spraw, aby klasa MyCanvasView rozszerzała klasę View i przekazywała context: Context. Zaakceptuj sugerowane importy.
import android.content.Context
import android.view.View

class MyCanvasView(context: Context) : View(context) {
}

Krok 3. Ustaw MyCanvasView jako widok treści

Aby wyświetlić to, co narysujesz w MyCanvasView, musisz ustawić je jako widok treści w MainActivity.

  1. Otwórz plik strings.xml i zdefiniuj ciąg znaków, który będzie używany jako opis treści widoku.
<string name="canvasContentDescription">Mini Paint is a simple line drawing app.
   Drag your fingers to draw. Rotate the phone to clear.</string>
  1. Otwórz aplikację MainActivity.kt
  2. onCreate() usuń setContentView(R.layout.activity_main).
  3. Utwórz instancję MyCanvasView.
val myCanvasView = MyCanvasView(this)
  1. Poniżej poproś o wyświetlenie układu myCanvasView na pełnym ekranie. W tym celu ustaw flagę SYSTEM_UI_FLAG_FULLSCREEN na myCanvasView. W ten sposób widok całkowicie wypełnia ekran.
myCanvasView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN
  1. Dodaj opis treści.
myCanvasView.contentDescription = getString(R.string.canvasContentDescription)
  1. Poniżej ustaw widok treści na myCanvasView.
setContentView(myCanvasView)
  1. Uruchom aplikację. Zobaczysz całkowicie biały ekran, ponieważ obszar roboczy nie ma rozmiaru i nie narysowano na nim jeszcze niczego.

Krok 1. Zastąpienie metody onSizeChanged()

Metoda onSizeChanged() jest wywoływana przez system Android za każdym razem, gdy zmienia się rozmiar widoku. Ponieważ widok początkowo nie ma rozmiaru, metoda onSizeChanged() jest wywoływana po utworzeniu i rozszerzeniu widoku przez działanie. Ta onSizeChanged() metoda jest więc idealnym miejscem do utworzenia i skonfigurowania obszaru widoku.

  1. MyCanvasView na poziomie klasy zdefiniuj zmienne dla obszaru rysowania i mapy bitowej. Zadzwoń do extraCanvas i extraBitmap. To Twoja mapa bitowa i obszar rysowania, w którym możesz przechowywać w pamięci podręcznej to, co zostało wcześniej narysowane.
private lateinit var extraCanvas: Canvas
private lateinit var extraBitmap: Bitmap
  1. Zdefiniuj zmienną na poziomie klasy backgroundColor dla koloru tła obszaru rysowania i zainicjuj ją za pomocą wartości colorBackground zdefiniowanej wcześniej.
private val backgroundColor = ResourcesCompat.getColor(resources, R.color.colorBackground, null)
  1. W MyCanvasView zastąp metodę onSizeChanged(). Ta metoda wywołania zwrotnego jest wywoływana przez system Android z zmienionymi wymiarami ekranu, czyli z nową szerokością i wysokością (do których ma nastąpić zmiana) oraz starą szerokością i wysokością (z których ma nastąpić zmiana).
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
   super.onSizeChanged(width, height, oldWidth, oldHeight)
}
  1. Wewnątrz onSizeChanged() utwórz instancję Bitmap z nową szerokością i wysokością, które są rozmiarem ekranu, i przypisz ją do extraBitmap. Trzeci argument to konfiguracja koloru mapy bitowej. ARGB_8888 przechowuje każdy kolor w 4 bajtach i jest zalecany.
extraBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
  1. Utwórz instancję CanvasextraBitmap i przypisz ją do extraCanvas.
 extraCanvas = Canvas(extraBitmap)
  1. Określ kolor tła, którym ma zostać wypełniony element extraCanvas.
extraCanvas.drawColor(backgroundColor)
  1. W przypadku onSizeChanged() za każdym razem, gdy funkcja jest wykonywana, tworzone są nowa mapa bitowa i nowe płótno. Potrzebujesz nowej mapy bitowej, ponieważ rozmiar się zmienił. Jest to jednak wyciek pamięci, ponieważ stare mapy bitowe pozostają w pamięci. Aby to naprawić, przed utworzeniem kolejnego elementu odzyskaj pamięć extraBitmap, dodając ten kod bezpośrednio po wywołaniu funkcji super.
if (::extraBitmap.isInitialized) extraBitmap.recycle()

Krok 2. Zastąpienie metody onDraw()

Wszystkie rysunki dla MyCanvasView są tworzone w onDraw().

Na początek wyświetl płótno, wypełniając ekran kolorem tła ustawionym w onSizeChanged().

  1. Zastąp onDraw() i narysuj zawartość buforowanego extraBitmap na obszarze roboczym powiązanym z widokiem. Metoda drawBitmap() Canvas występuje w kilku wersjach. W tym kodzie podajesz bitmapę, współrzędne x i y (w pikselach) lewego górnego rogu oraz null dla Paint, ponieważ ustawisz to później.
override fun onDraw(canvas: Canvas) {
   super.onDraw(canvas)
canvas.drawBitmap(extraBitmap, 0f, 0f, null)
}


Zwróć uwagę, że obszar roboczy przekazywany do onDraw() i używany przez system do wyświetlania mapy bitowej różni się od obszaru roboczego utworzonego w metodzie onSizeChanged() i używanego przez Ciebie do rysowania na mapie bitowej.

  1. Uruchom aplikację. Cały ekran powinien być wypełniony określonym kolorem tła.

Aby rysować, potrzebujesz obiektu Paint, który określa styl rysowania, oraz obiektu Path, który określa, co jest rysowane.

Krok 1. Inicjowanie obiektu Paint

  1. W pliku MyCanvasView.kt na najwyższym poziomie zdefiniuj stałą szerokość kreski.
private const val STROKE_WIDTH = 12f // has to be float
  1. Na poziomie klasy MyCanvasView zdefiniuj zmienną drawColor, która będzie przechowywać kolor rysowania, i zainicjuj ją za pomocą zdefiniowanego wcześniej zasobu colorPaint.
private val drawColor = ResourcesCompat.getColor(resources, R.color.colorPaint, null)
  1. Na poziomie klasy poniżej dodaj zmienną paint dla obiektu Paint i zainicjuj ją w ten sposób:
// Set up the paint with which to draw.
private val paint = Paint().apply {
   color = drawColor
   // Smooths out edges of what is drawn without affecting shape.
   isAntiAlias = true
   // Dithering affects how colors with higher-precision than the device are down-sampled.
   isDither = true
   style = Paint.Style.STROKE // default: FILL
   strokeJoin = Paint.Join.ROUND // default: MITER
   strokeCap = Paint.Cap.ROUND // default: BUTT
   strokeWidth = STROKE_WIDTH // default: Hairline-width (really thin)
}
  • Wartość color elementu paint to drawColor zdefiniowana wcześniej.
  • isAntiAlias określa, czy ma być stosowane wygładzanie krawędzi. Ustawienie isAntiAlias na true wygładza krawędzie rysunku bez wpływu na kształt.
  • isDither, gdy true, wpływa na sposób próbkowania w dół kolorów o wyższej precyzji niż urządzenie. Na przykład dithering to najpopularniejszy sposób na zmniejszenie zakresu kolorów obrazów do 256 kolorów (lub mniej).
  • style określa typ malowania, które ma być zastosowane do pociągnięcia pędzlem, czyli w zasadzie linii. Paint.Style określa, czy rysowany element jest wypełniony, obrysowany czy jedno i drugie (w tym samym kolorze). Domyślnie wypełniany jest obiekt, do którego stosowana jest farba. („Wypełnienie” koloruje wnętrze kształtu, a „kreska” – jego kontur).
  • strokeJoinPaint.Join określa sposób łączenia linii i segmentów krzywych na ścieżce z obrysem. Wartość domyślna to MITER.
  • strokeCap ustawia kształt końca linii na kształt zakończenia. Paint.Cap określa, jak wygląda początek i koniec linii i ścieżek. Wartość domyślna to BUTT.
  • strokeWidth określa szerokość kreski w pikselach. Domyślna szerokość to bardzo cienka linia, więc jest ona ustawiona na zdefiniowaną wcześniej stałą STROKE_WIDTH.

Krok 2. Inicjowanie obiektu Path

Path to ścieżka rysowanego przez użytkownika kształtu.

  1. MyCanvasView dodaj zmienną path i zainicjuj ją za pomocą obiektu Path, aby przechowywać ścieżkę rysowaną podczas śledzenia dotyku użytkownika na ekranie. Zaimportuj android.graphics.Path dla Path.
private var path = Path()

Krok 1. Reagowanie na ruch na wyświetlaczu

Metoda onTouchEvent() w widoku jest wywoływana za każdym razem, gdy użytkownik dotknie ekranu.

  1. MyCanvasView zastąp metodę onTouchEvent(), aby zapisać w pamięci podręcznej współrzędne xy przekazanego elementu event. Następnie użyj wyrażenia when, aby obsługiwać zdarzenia ruchu związane z dotknięciem ekranu, przesuwaniem po nim i zwolnieniem dotyku. Są to zdarzenia, które są istotne przy rysowaniu linii na ekranie. W przypadku każdego typu zdarzenia wywołaj metodę narzędziową, jak pokazano w kodzie poniżej. Pełną listę zdarzeń dotykowych znajdziesz w dokumentacji klasy MotionEvent.
override fun onTouchEvent(event: MotionEvent): Boolean {
   motionTouchEventX = event.x
   motionTouchEventY = event.y

   when (event.action) {
       MotionEvent.ACTION_DOWN -> touchStart()
       MotionEvent.ACTION_MOVE -> touchMove()
       MotionEvent.ACTION_UP -> touchUp()
   }
   return true
}
  1. Na poziomie klasy dodaj brakujące zmienne motionTouchEventXmotionTouchEventY, aby buforować współrzędne x i y bieżącego zdarzenia dotykowego (współrzędne MotionEvent). Ustaw wartość początkową na 0f.
private var motionTouchEventX = 0f
private var motionTouchEventY = 0f
  1. Utwórz szablony 3 funkcji: touchStart(), touchMove()touchUp().
private fun touchStart() {}

private fun touchMove() {}

private fun touchUp() {}
  1. Kod powinien się skompilować i uruchomić, ale na razie nie zobaczysz niczego innego niż kolorowe tło.

Krok 2. Implementacja funkcji touchStart()

Ta metoda jest wywoływana, gdy użytkownik po raz pierwszy dotknie ekranu.

  1. Na poziomie klasy dodaj zmienne, aby buforować najnowsze wartości x i y. Gdy użytkownik przestanie się poruszać i odsunie palec, te punkty staną się punktem początkowym następnej ścieżki (kolejnego segmentu linii do narysowania).
private var currentX = 0f
private var currentY = 0f
  1. Zaimplementuj metodę touchStart() w ten sposób: Zresetuj path, przejdź do współrzędnych x-y zdarzenia dotykowego (motionTouchEventXmotionTouchEventY) i przypisz do tej wartości currentXcurrentY.
private fun touchStart() {
   path.reset()
   path.moveTo(motionTouchEventX, motionTouchEventY)
   currentX = motionTouchEventX
   currentY = motionTouchEventY
}

Krok 3. Implementacja funkcji touchMove()

  1. Na poziomie zajęć dodaj zmienną touchTolerance i ustaw jej wartość na ViewConfiguration.get(context).scaledTouchSlop.
private val touchTolerance = ViewConfiguration.get(context).scaledTouchSlop

Korzystając ze ścieżki, nie musisz rysować każdego piksela ani za każdym razem prosić o odświeżenie wyświetlacza. Zamiast tego możesz (i będziesz) interpolować ścieżkę między punktami, co znacznie poprawi wydajność.

  • Jeśli palec prawie się nie poruszył, nie musisz rysować.
  • Jeśli palec przesunął się o mniej niż touchTolerance, nie rysuj.
  • scaledTouchSlop zwraca odległość w pikselach, o jaką może się przesunąć dotyk, zanim system uzna, że użytkownik przewija ekran.
  1. Określ metodę touchMove(). Oblicz przebytą odległość (dx, dy), utwórz krzywą między dwoma punktami i zapisz ją w path, zaktualizuj bieżące wartości currentXcurrentY oraz narysuj path. Następnie wywołaj funkcję invalidate(), aby wymusić ponowne narysowanie ekranu ze zaktualizowanym elementem path.
private fun touchMove() {
   val dx = Math.abs(motionTouchEventX - currentX)
   val dy = Math.abs(motionTouchEventY - currentY)
   if (dx >= touchTolerance || dy >= touchTolerance) {
       // QuadTo() adds a quadratic bezier from the last point,
       // approaching control point (x1,y1), and ending at (x2,y2).
       path.quadTo(currentX, currentY, (motionTouchEventX + currentX) / 2, (motionTouchEventY + currentY) / 2)
       currentX = motionTouchEventX
       currentY = motionTouchEventY
       // Draw the path in the extra bitmap to cache it.
       extraCanvas.drawPath(path, paint)
   }
   invalidate()
}

Szczegółowy opis tej metody:

  1. Oblicz odległość, o jaką przesunięto obiekt (dx, dy).
  2. Jeśli ruch był większy niż tolerancja dotyku, dodaj segment do ścieżki.
  3. Ustaw punkt początkowy następnego segmentu na punkt końcowy tego segmentu.
  4. Użyj quadTo() zamiast lineTo(), aby utworzyć gładką linię bez narożników. Zobacz krzywe Beziera.
  5. Wywołaj funkcję invalidate(), aby (ostatecznie wywołać funkcję onDraw() i) ponownie narysować widok.

Krok 4. Zaimplementuj funkcję touchUp()

Gdy użytkownik przestanie dotykać ekranu, wystarczy zresetować ścieżkę, aby nie została narysowana ponownie. Nic nie jest rysowane, więc nie trzeba unieważniać.

  1. Zaimplementuj metodę touchUp().
private fun touchUp() {
   // Reset the path so it doesn't get drawn again.
   path.reset()
}
  1. Uruchom kod i narysuj coś palcem na ekranie. Zauważ, że po obróceniu urządzenia ekran zostanie wyczyszczony, ponieważ stan rysowania nie jest zapisywany. W przypadku tej przykładowej aplikacji jest to celowe, aby użytkownik mógł w prosty sposób wyczyścić ekran.

Krok 5. Narysuj ramkę wokół szkicu

Gdy użytkownik rysuje na ekranie, aplikacja tworzy ścieżkę i zapisuje ją w mapie bitowej extraBitmap. Metoda onDraw() wyświetla dodatkową mapę bitową na obszarze rysowania widoku. Więcej rysunków możesz wykonać w onDraw(). Możesz na przykład narysować kształty po narysowaniu mapy bitowej.

W tym kroku narysujesz ramkę wokół krawędzi zdjęcia.

  1. W sekcji MyCanvasView dodaj zmienną o nazwie frame, która zawiera obiekt Rect.
private lateinit var frame: Rect
  1. Na końcu onSizeChanged() zdefiniuj wstawkę i dodaj kod, aby utworzyć element Rect, który będzie używany w ramce, korzystając z nowych wymiarów i wstawki.
// Calculate a rectangular frame around the picture.
val inset = 40
frame = Rect(inset, inset, width - inset, height - inset)
  1. onDraw() po narysowaniu mapy bitowej narysuj prostokąt.
// Draw a frame around the canvas.
canvas.drawRect(frame, paint)
  1. Uruchom aplikację. Zwróć uwagę na ramkę.

Zadanie (opcjonalne): przechowywanie danych w ścieżce

W obecnej aplikacji informacje o rysunku są przechowywane w mapie bitowej. To dobre rozwiązanie, ale nie jedyne możliwe. Sposób przechowywania historii rysowania zależy od aplikacji i różnych wymagań. Jeśli na przykład rysujesz kształty, możesz zapisać listę kształtów wraz z ich lokalizacją i wymiarami. W przypadku aplikacji MiniPaint możesz zapisać ścieżkę jako Path. Jeśli chcesz spróbować, poniżej znajdziesz ogólne wskazówki, jak to zrobić.

  1. W pliku MyCanvasView usuń cały kod dotyczący extraCanvasextraBitmap.
  2. Dodaj zmienne dla dotychczasowej ścieżki i ścieżki, która jest obecnie rysowana.
// Path representing the drawing so far
private val drawing = Path()

// Path representing what's currently being drawn
private val curPath = Path()
  1. onDraw() zamiast rysować mapę bitową narysuj zapisane i bieżące ścieżki.
// Draw the drawing so far
canvas.drawPath(drawing, paint)
// Draw any current squiggle
canvas.drawPath(curPath, paint)
// Draw a frame around the canvas
canvas.drawRect(frame, paint)
  1. touchUp() dodaj bieżącą ścieżkę do poprzedniej i zresetuj bieżącą ścieżkę.
// Add the current path to the drawing so far
drawing.addPath(curPath)
// Rewind the current path for the next touch
curPath.reset()
  1. Uruchom aplikację. Nie powinno być żadnej różnicy.

Pobierz kod ukończonego ćwiczenia.

$  git clone https://github.com/googlecodelabs/android-kotlin-drawing-canvas


Możesz też pobrać repozytorium jako plik ZIP, rozpakować go i otworzyć w Android Studio.

Pobierz plik ZIP

  • Canvas to dwuwymiarowa powierzchnia do rysowania, która udostępnia metody rysowania.
  • Element Canvas może być powiązany z instancją View, która go wyświetla.
  • Obiekt Paint zawiera informacje o stylu i kolorze, które określają sposób rysowania geometrii (takich jak linie, prostokąty, owale i ścieżki) oraz tekstu.
  • Typowym sposobem pracy z obszarem rysowania jest utworzenie niestandardowego widoku i zastąpienie metod onDraw()onSizeChanged().
  • Zastąp metodę onTouchEvent(), aby rejestrować dotknięcia użytkownika i reagować na nie, rysując różne elementy.
  • Możesz użyć dodatkowej mapy bitowej do buforowania informacji o rysunkach, które zmieniają się z upływem czasu. Możesz też przechowywać kształty lub ścieżkę.

Kurs Udacity:

Dokumentacja dla deweloperów aplikacji na Androida:

W tej sekcji znajdziesz listę możliwych zadań domowych dla uczniów, którzy wykonują ten moduł w ramach kursu prowadzonego przez instruktora. Nauczyciel musi:

  • W razie potrzeby przypisz pracę domową.
  • Poinformuj uczniów, jak przesyłać projekty.
  • Oceń zadania domowe.

Instruktorzy mogą korzystać z tych sugestii w dowolnym zakresie i mogą zadawać inne zadania domowe, które uznają za odpowiednie.

Jeśli wykonujesz ten kurs samodzielnie, możesz użyć tych zadań domowych, aby sprawdzić swoją wiedzę.

Odpowiedz na te pytania

Pytanie 1

Które z tych komponentów są wymagane do pracy z Canvas? Zaznacz wszystkie pasujące opcje.

▢ Bitmap

▢ Paint

▢ Path

▢ View

Pytanie 2

Co (ogólnie) robi wywołanie invalidate()?

▢ Unieważnia i ponownie uruchamia aplikację.

▢ Usuwa rysunek z mapy bitowej.

▢ Oznacza, że poprzedni kod nie powinien być uruchamiany.

▢ Informuje system, że musi ponownie narysować ekran.

Pytanie 3

Jaką funkcję pełnią obiekty Canvas, BitmapPaint?

▢ Powierzchnia rysowania 2D, bitmapa wyświetlana na ekranie, informacje o stylu rysowania.

▢ Powierzchnia rysowania 3D, bitmapa do buforowania ścieżki, informacje o stylu rysowania.

▢ Powierzchnia rysowania 2D, bitmapa wyświetlana na ekranie, styl widoku.

▢ Pamięć podręczna informacji o rysowaniu, bitmapa do rysowania, informacje o stylu rysowania.

Linki do innych ćwiczeń z tego kursu znajdziesz na stronie docelowej ćwiczeń z zaawansowanego Androida w Kotlinie.