Slide 1

Slide 1 text

Busuu 2019 Busuu 2019 Android Canvas in Depth

Slide 2

Slide 2 text

Busuu 2019 Busuu 2019 Busuu - language learning community 2

Slide 3

Slide 3 text

Busuu 2019 3 Android dev for 5 years Love art Love animations and drawing Let’s talk Canvas and optimisation Nik Shevchenko

Slide 4

Slide 4 text

Busuu 2019 4 Canvas is a the main class for drawing 2D graphics Part of android.graphics collection What Text, Lines, Ovals, Arcs, Bitmaps…. Where x, y coordinates How Paint object What is a Canvas Bitmap Canvas Button

Slide 5

Slide 5 text

Busuu 2019 5 What is a Canvas Every View has a canvas fun onDraw(Canvas canvas) To redraw - invalidate() Rendering commands stored in DisplayList Sent to GPU for OpenGL to consume Bitmap Canvas Button

Slide 6

Slide 6 text

Busuu 2019 6 What is a Canvas Every View has a canvas fun onDraw(Canvas canvas) To redraw - invalidate() Rendering commands stored in DisplayList Sent to GPU for OpenGL to consume CPU GPU Bitmap Canvas Button

Slide 7

Slide 7 text

Busuu 2019 7 onDraw -> Dispaly List Drawn out: how Android renders (Google I/O '18) https://www.youtube.com/watch?v=zdQRIYOST64

Slide 8

Slide 8 text

Busuu 2019 8

Slide 9

Slide 9 text

Busuu 2019 9 Layouts Quick but not always calls propagate in the hierarchy Prompt to overdraw Double Taxation

Slide 10

Slide 10 text

Busuu 2019 10 Calls propagate in the hierarchy Layout Inspector Flatten views - Constraint Layout Lint

Slide 11

Slide 11 text

Busuu 2019 11 Prompt to overdraw Painter's algorithm redrawing pixels Turn on in the settings Remove backgrounds Reducing transparency

Slide 12

Slide 12 text

Busuu 2019 12 Double Taxation 2x layout-and-measure RelativeLayout LinearLayout Horizontal / max height Root element or a ViewHolder

Slide 13

Slide 13 text

Busuu 2019 13 calls propagate in the hierarchy Prompt to overdraw Double Taxation Layouts Solutions - Tools Lint Layout inspector GPU overdraw settings Profile GPU Rendering Systrace

Slide 14

Slide 14 text

Busuu 2019 14 Profile GPU Profiling

Slide 15

Slide 15 text

Busuu 2019 15 Profile GPU Profiling

Slide 16

Slide 16 text

Busuu 2019 16 Profile GPU Profiling

Slide 17

Slide 17 text

Busuu 2019 17 Systrace App in Android tools Android 10+ Perfetto UI adb pull /data/local/traces/

Slide 18

Slide 18 text

Busuu 2019 18 Systrace example

Slide 19

Slide 19 text

Busuu 2019 19 Systrace example

Slide 20

Slide 20 text

Busuu 2019 20 Systrace example

Slide 21

Slide 21 text

Busuu 2019 21 Systrace example

Slide 22

Slide 22 text

Busuu 2019 22 Systrace example

Slide 23

Slide 23 text

Busuu 2019 23 What if... Canvas inside Viewholder

Slide 24

Slide 24 text

Busuu 2019 24 Profile GPU Profiling

Slide 25

Slide 25 text

Busuu 2019 25 3x

Slide 26

Slide 26 text

Busuu 2019 26 Profile GPU Profiling Constraint Layout performance https://android.jlelse.eu/constraint-layout-performance-870e5f23 8100

Slide 27

Slide 27 text

Busuu 2019 27 3x Constraint Layout

Slide 28

Slide 28 text

Busuu 2019 28 Canvas in Real life Gmail Messenger

Slide 29

Slide 29 text

Busuu 2019 29 Docs Great descriptions https://developer.android.com/topic/performance/rendering/optimizing-view-hierarchies https://developer.android.com/topic/performance/rendering/overdraw https://developer.android.com/topic/performance/rendering/profile-gpu

Slide 30

Slide 30 text

Busuu 2019 Busuu 2019 Speech Recognition Study 30

Slide 31

Slide 31 text

Busuu 2019 31 Speech Recognition Animation Nothing similar out there Randomised waves from a circle Based on mic input 31

Slide 32

Slide 32 text

Busuu 2019 32 1. Calculate random arcs around the circle 2. Random heights for each arcs 3. Draw them 4. Animate them up and down 5. Clear & Repeat The steps

Slide 33

Slide 33 text

Busuu 2019 33 1. Calculate random Arcs 2. Random heights for each arcs heights = angles.map { random(20) * voiceAmplitude } voiceAmplitude = [0 - 1]

Slide 34

Slide 34 text

Busuu 2019 34 Draw Arcs private val path = Path() for (i in 0 until angles.size) { path.reset() // calculate oval path.addOval(oval, Path.Direction.CW) rotationAngle = currentAngle /2 + futureAngle /2 canvas.rotate(rotationAngle, center.x, center.y) canvas.drawPath(path, wavePaint) }

Slide 35

Slide 35 text

Busuu 2019 35 Draw Arcs private val path = Path() for (i in 0 until angles.size) { path.reset() // calculate oval path.addOval(oval, Path.Direction.CW) rotationAngle = currentAngle /2 + futureAngle /2 canvas.rotate(rotationAngle, center.x, center.y) canvas.drawPath(path, wavePaint) }

Slide 36

Slide 36 text

Busuu 2019 36 Draw Arcs + randomness Arcs -> Ovals Paint(ANTI_ALIAS_FLAG).apply { setStyle(Paint.Style.STROKE) setStyle(Paint.Style.FILL)

Slide 37

Slide 37 text

Busuu 2019 37 Draw 3 layers of Arcs

Slide 38

Slide 38 text

Busuu 2019 38 Ovals size Left, top, right, bottom

Slide 39

Slide 39 text

Busuu 2019 39 Get coordinates with Math.sin

Slide 40

Slide 40 text

Busuu 2019 40 Where are we... + Random Arcs + Random height for each arc + White circle on top + 3 layers with different + Animation

Slide 41

Slide 41 text

Busuu 2019 41 Add animation

Slide 42

Slide 42 text

Busuu 2019 42 Iterations “Always take into account design re-iterations. They usually pay off” Cit. Nik

Slide 43

Slide 43 text

Busuu 2019 43 Iterations + Add a “Dominant” and 2 subdominants

Slide 44

Slide 44 text

Busuu 2019 44 Iterations + Add a “Dominant” and 2 subdominants + Add microphone

Slide 45

Slide 45 text

Busuu 2019 45 Iterations + Add a “Dominant” and 2 subdominants + Add microphone

Slide 46

Slide 46 text

Busuu 2019 46 Iterations + Add a “Dominant” and 2 subdominants + Add microphone + Add Alpha and gradients

Slide 47

Slide 47 text

Busuu 2019 47 Iterations + Add a “Dominant” and 2 subdominants + Add microphone + Add Alpha and gradients + Slower and darker when moving

Slide 48

Slide 48 text

Busuu 2019 48 Iterations + Add a “Dominant” and 2 subdominants + Add microphone + Add Alpha and gradients + Slower and darker when moving Ship it!

Slide 49

Slide 49 text

Busuu 2019 49 How does it perform?

Slide 50

Slide 50 text

Busuu 2019 50 To remember Don’t allocate memory in onDraw() Preview in AS works after compiling - mock with isInEditMode Accessibility - setContentDescription() Don’t Canvas everything - business / performance needs

Slide 51

Slide 51 text

Busuu 2019 Busuu 2019 51 Thanks for listening! Embrace custom drawing! Make it unique. Embrace open source! https://github.com/nshevchenko/SpeechWaves Come work with us - busuu.com/jobs Have a great evening! Nik