SlideShare una empresa de Scribd logo
Charting Like a Pro
By Guy Griv
@guygriv @guy.griv @grivos
Custom View
override fun onDraw(canvas: Canvas) {
canvas.drawRect()
canvas.drawRoundRect()
canvas.drawPath()
canvas.drawText()
canvas.drawCircle()
paint.style
paint.color
paint.strokeWidth
paint.pathEffect
paint.shader
}
Paint * Canvas = ∞
Example
onDraw Breakdown
override fun onDraw(canvas: Canvas) {
drawGradient(canvas)
drawGuidelines(canvas)
drawLineAndMarkers(canvas)
drawWeeks(canvas)
drawScales(canvas)
}
Calculate Markers Positions
private fun calcPositions(markers: List<Marker>) {
val max = markers.maxBy { it.value }
val min = markers.minBy { it.value }
pxPerUnit = chartHeight / (max - min)
zeroY = max * pxPerUnit + paddingTop
val step = (width - 2 * padding - scalesWidth) / (markers.size - 1)
for ((i, marker) in markers.withIndex()) {
val x = step * i + paddingLeft
val y = zeroY - entry.value * pxPerUnit
marker.currentPos.x = x
marker.currentPos.y = y
}
}
drawGradient()
override fun onDraw(canvas: Canvas) {
drawGradient(canvas)
drawGuidelines(canvas)
drawLineAndMarkers(canvas)
drawWeeks(canvas)
drawScales(canvas)
}
drawGradient()
private fun drawGradient(canvas: Canvas) {
path.reset()
path.moveTo(paddingLeft, zeroY)
for (marker in markers) {
path.lineTo(marker.targetPos.x, entry.targetPos.y)
}
// close the path
path.lineTo(markers.last().targetPos.x, zeroY)
path.lineTo(paddingLeft, zeroY)
canvas.drawPath(path, gradientPaint)
}
// prepare the gradient paint
val colors = intArrayOf(colorStart, colorEnd))
val gradient = LinearGradient(
0f, paddingTop, 0f, zeroY, colors, null, CLAMP
)
gradientPaint.style = FILL
gradientPaint.shader = gradient
drawGuidelines()
override fun onDraw(canvas: Canvas) {
drawGradient(canvas)
drawGuidelines(canvas)
drawLineAndMarkers(canvas)
drawWeeks(canvas)
drawScales(canvas)
}
drawGuidelines()
// prepare the guideline paint
dottedPaint.style = STROKE
dottedPaint.strokeWidth = DOTTED_STROKE_WIDTH_DP
dottedPaint.pathEffect = DashPathEffect(floatArrayOf(INTERVAL, INTERVAL), 0f)
private fun drawGuidelines(canvas: Canvas) {
for (i in 0..markers.lastIndex step 7) {
val marker = markers[i]
guidelinePath.reset()
guidelinePath.moveTo(entry.currentPos.x, paddingTop)
guidelinePath.lineTo(entry.currentPos.x, zeroY)
canvas.drawPath(guidelinePath, dottedPaint)
}
}
drawLineAndMarkers()
override fun onDraw(canvas: Canvas) {
drawGradient(canvas)
drawGuidelines(canvas)
drawLineAndMarkers(canvas)
drawWeeks(canvas)
drawScales(canvas)
}
private fun drawLineAndMarkers(canvas: Canvas) {
var previousMarker: Entry? = null
for (marker in markers) {
if (previousMarker != null) {
// draw the line
drawLine(
canvas,
previousMarker.currentPos,
marker.currentPos
)
}
previousMarker = marker
// draw the marker
canvas.drawCircle(
entry.currentPos.x,
entry.currentPos.y,
pointRadius,
pointPaint
)
}
}
drawLineAndMarkers()
drawWeeks()
override fun onDraw(canvas: Canvas) {
drawGradient(canvas)
drawGuidelines(canvas)
drawLineAndMarkers(canvas)
drawWeeks(canvas)
drawScales(canvas)
}
private fun drawWeeks(canvas: Canvas) {
for ((i, week) in weeks.withIndex()) {
textPaint.getTextBounds(week, 0, week.length, rect)
val x = middle(i)
val y = zeroY + rect.height()
val halfWidth = rect.width() / 2f
val halfHeight = rect.height() / 2f
val left = x - halfWidth - padding
val top = y - halfHeight - padding
val right = x + halfWidth + padding
val bottom = y + halfHeight + padding
rect.set(left, top, right, bottom)
paint.color = bgColor
paint.style = FILL
canvas.drawRoundRect(rect, radius, radius, paint)
paint.color = strokeColor
paint.style = STROKE
canvas.drawRoundRect(rect, radius, radius, paint)
canvas.drawText(week, x, keyY, textPaint)
}
}
drawWeeks()
drawScales()
override fun onDraw(canvas: Canvas) {
drawGradient(canvas)
drawGuidelines(canvas)
drawLineAndMarkers(canvas)
drawWeeks(canvas)
drawScales(canvas)
}
private fun drawScales(canvas: Canvas) {
val x = markers.last().currentPos.x + padding
for (scale in scales) {
val y = zeroY - scale * pxPerUnit
val formatted = NumberFormat.getIntegerInstance().format(scale)
canvas.drawText(formatted, x, y, textPaint)
}
}
drawScales()
Result
Summary
• Don’t be afraid of building a custom view (when needed)

• Learn about the main Canvas and Paint APIs

• Break the design down to its layers
Thank You!
@guygriv @guy.griv @grivos

Más contenido relacionado

Similar a Charting like a pro - Guy Griv, Pepper

HTML5 Canvas - The Future of Graphics on the Web
HTML5 Canvas - The Future of Graphics on the WebHTML5 Canvas - The Future of Graphics on the Web
HTML5 Canvas - The Future of Graphics on the Web
Robin Hawkes
 
Advanced html5 diving into the canvas tag
Advanced html5 diving into the canvas tagAdvanced html5 diving into the canvas tag
Advanced html5 diving into the canvas tag
David Voyles
 
program logbook 2
program logbook 2program logbook 2
program logbook 2
Jack Eastwood
 
Html5 canvas
Html5 canvasHtml5 canvas
Html5 canvas
Nisa Soomro
 
Nodebox for Data Visualization
Nodebox for Data VisualizationNodebox for Data Visualization
Nodebox for Data Visualization
Lynn Cherny
 
Exploring Canvas
Exploring CanvasExploring Canvas
Exploring Canvas
Kevin Hoyt
 
Css5 canvas
Css5 canvasCss5 canvas
Css5 canvas
Vadim Spiridenko
 
Canvas
CanvasCanvas

Similar a Charting like a pro - Guy Griv, Pepper (8)

HTML5 Canvas - The Future of Graphics on the Web
HTML5 Canvas - The Future of Graphics on the WebHTML5 Canvas - The Future of Graphics on the Web
HTML5 Canvas - The Future of Graphics on the Web
 
Advanced html5 diving into the canvas tag
Advanced html5 diving into the canvas tagAdvanced html5 diving into the canvas tag
Advanced html5 diving into the canvas tag
 
program logbook 2
program logbook 2program logbook 2
program logbook 2
 
Html5 canvas
Html5 canvasHtml5 canvas
Html5 canvas
 
Nodebox for Data Visualization
Nodebox for Data VisualizationNodebox for Data Visualization
Nodebox for Data Visualization
 
Exploring Canvas
Exploring CanvasExploring Canvas
Exploring Canvas
 
Css5 canvas
Css5 canvasCss5 canvas
Css5 canvas
 
Canvas
CanvasCanvas
Canvas
 

Más de DroidConTLV

Mobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, NikeMobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, Nike
DroidConTLV
 
Doing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra TechnologiesDoing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra Technologies
DroidConTLV
 
No more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola SolutionsNo more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola Solutions
DroidConTLV
 
Mobile at Scale: from startup to a big company - Dor Samet, Booking.com
Mobile at Scale: from startup to a big company - Dor Samet, Booking.comMobile at Scale: from startup to a big company - Dor Samet, Booking.com
Mobile at Scale: from startup to a big company - Dor Samet, Booking.com
DroidConTLV
 
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, ClimacellLiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
DroidConTLV
 
MVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, LightricksMVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, Lightricks
DroidConTLV
 
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
DroidConTLV
 
Building Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaBuilding Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice Ninja
DroidConTLV
 
New Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy ZukanovNew Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy Zukanov
DroidConTLV
 
Designing a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, GettDesigning a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, Gett
DroidConTLV
 
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, PepperThe Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
DroidConTLV
 
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDevKotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
DroidConTLV
 
Flutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalFlutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, Tikal
DroidConTLV
 
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bisReactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
DroidConTLV
 
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevelFun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
DroidConTLV
 
DroidconTLV 2019
DroidconTLV 2019DroidconTLV 2019
DroidconTLV 2019
DroidConTLV
 
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, MondayOk google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
DroidConTLV
 
Introduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, WixIntroduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, Wix
DroidConTLV
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
DroidConTLV
 
Educating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz TamirEducating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz Tamir
DroidConTLV
 

Más de DroidConTLV (20)

Mobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, NikeMobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, Nike
 
Doing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra TechnologiesDoing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra Technologies
 
No more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola SolutionsNo more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola Solutions
 
Mobile at Scale: from startup to a big company - Dor Samet, Booking.com
Mobile at Scale: from startup to a big company - Dor Samet, Booking.comMobile at Scale: from startup to a big company - Dor Samet, Booking.com
Mobile at Scale: from startup to a big company - Dor Samet, Booking.com
 
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, ClimacellLiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
 
MVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, LightricksMVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, Lightricks
 
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
 
Building Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaBuilding Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice Ninja
 
New Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy ZukanovNew Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy Zukanov
 
Designing a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, GettDesigning a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, Gett
 
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, PepperThe Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
 
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDevKotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
 
Flutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalFlutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, Tikal
 
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bisReactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
 
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevelFun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
 
DroidconTLV 2019
DroidconTLV 2019DroidconTLV 2019
DroidconTLV 2019
 
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, MondayOk google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
 
Introduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, WixIntroduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, Wix
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
 
Educating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz TamirEducating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz Tamir
 

Último

Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
Zilliz
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
Mariano Tinti
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
SitimaJohn
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
Hiroshi SHIBATA
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
Project Management Semester Long Project - Acuity
Project Management Semester Long Project - AcuityProject Management Semester Long Project - Acuity
Project Management Semester Long Project - Acuity
jpupo2018
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
ssuserfac0301
 
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
saastr
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
Postman
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
Edge AI and Vision Alliance
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
Wouter Lemaire
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Wask
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
tolgahangng
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 

Último (20)

Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
Project Management Semester Long Project - Acuity
Project Management Semester Long Project - AcuityProject Management Semester Long Project - Acuity
Project Management Semester Long Project - Acuity
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
 
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 

Charting like a pro - Guy Griv, Pepper

  • 1. Charting Like a Pro By Guy Griv @guygriv @guy.griv @grivos
  • 2.
  • 3.
  • 4.
  • 5. Custom View override fun onDraw(canvas: Canvas) { canvas.drawRect() canvas.drawRoundRect() canvas.drawPath() canvas.drawText() canvas.drawCircle() paint.style paint.color paint.strokeWidth paint.pathEffect paint.shader } Paint * Canvas = ∞
  • 7. onDraw Breakdown override fun onDraw(canvas: Canvas) { drawGradient(canvas) drawGuidelines(canvas) drawLineAndMarkers(canvas) drawWeeks(canvas) drawScales(canvas) }
  • 8. Calculate Markers Positions private fun calcPositions(markers: List<Marker>) { val max = markers.maxBy { it.value } val min = markers.minBy { it.value } pxPerUnit = chartHeight / (max - min) zeroY = max * pxPerUnit + paddingTop val step = (width - 2 * padding - scalesWidth) / (markers.size - 1) for ((i, marker) in markers.withIndex()) { val x = step * i + paddingLeft val y = zeroY - entry.value * pxPerUnit marker.currentPos.x = x marker.currentPos.y = y } }
  • 9. drawGradient() override fun onDraw(canvas: Canvas) { drawGradient(canvas) drawGuidelines(canvas) drawLineAndMarkers(canvas) drawWeeks(canvas) drawScales(canvas) }
  • 10. drawGradient() private fun drawGradient(canvas: Canvas) { path.reset() path.moveTo(paddingLeft, zeroY) for (marker in markers) { path.lineTo(marker.targetPos.x, entry.targetPos.y) } // close the path path.lineTo(markers.last().targetPos.x, zeroY) path.lineTo(paddingLeft, zeroY) canvas.drawPath(path, gradientPaint) } // prepare the gradient paint val colors = intArrayOf(colorStart, colorEnd)) val gradient = LinearGradient( 0f, paddingTop, 0f, zeroY, colors, null, CLAMP ) gradientPaint.style = FILL gradientPaint.shader = gradient
  • 11. drawGuidelines() override fun onDraw(canvas: Canvas) { drawGradient(canvas) drawGuidelines(canvas) drawLineAndMarkers(canvas) drawWeeks(canvas) drawScales(canvas) }
  • 12. drawGuidelines() // prepare the guideline paint dottedPaint.style = STROKE dottedPaint.strokeWidth = DOTTED_STROKE_WIDTH_DP dottedPaint.pathEffect = DashPathEffect(floatArrayOf(INTERVAL, INTERVAL), 0f) private fun drawGuidelines(canvas: Canvas) { for (i in 0..markers.lastIndex step 7) { val marker = markers[i] guidelinePath.reset() guidelinePath.moveTo(entry.currentPos.x, paddingTop) guidelinePath.lineTo(entry.currentPos.x, zeroY) canvas.drawPath(guidelinePath, dottedPaint) } }
  • 13. drawLineAndMarkers() override fun onDraw(canvas: Canvas) { drawGradient(canvas) drawGuidelines(canvas) drawLineAndMarkers(canvas) drawWeeks(canvas) drawScales(canvas) }
  • 14. private fun drawLineAndMarkers(canvas: Canvas) { var previousMarker: Entry? = null for (marker in markers) { if (previousMarker != null) { // draw the line drawLine( canvas, previousMarker.currentPos, marker.currentPos ) } previousMarker = marker // draw the marker canvas.drawCircle( entry.currentPos.x, entry.currentPos.y, pointRadius, pointPaint ) } } drawLineAndMarkers()
  • 15. drawWeeks() override fun onDraw(canvas: Canvas) { drawGradient(canvas) drawGuidelines(canvas) drawLineAndMarkers(canvas) drawWeeks(canvas) drawScales(canvas) }
  • 16. private fun drawWeeks(canvas: Canvas) { for ((i, week) in weeks.withIndex()) { textPaint.getTextBounds(week, 0, week.length, rect) val x = middle(i) val y = zeroY + rect.height() val halfWidth = rect.width() / 2f val halfHeight = rect.height() / 2f val left = x - halfWidth - padding val top = y - halfHeight - padding val right = x + halfWidth + padding val bottom = y + halfHeight + padding rect.set(left, top, right, bottom) paint.color = bgColor paint.style = FILL canvas.drawRoundRect(rect, radius, radius, paint) paint.color = strokeColor paint.style = STROKE canvas.drawRoundRect(rect, radius, radius, paint) canvas.drawText(week, x, keyY, textPaint) } } drawWeeks()
  • 17. drawScales() override fun onDraw(canvas: Canvas) { drawGradient(canvas) drawGuidelines(canvas) drawLineAndMarkers(canvas) drawWeeks(canvas) drawScales(canvas) }
  • 18. private fun drawScales(canvas: Canvas) { val x = markers.last().currentPos.x + padding for (scale in scales) { val y = zeroY - scale * pxPerUnit val formatted = NumberFormat.getIntegerInstance().format(scale) canvas.drawText(formatted, x, y, textPaint) } } drawScales()
  • 20. Summary • Don’t be afraid of building a custom view (when needed) • Learn about the main Canvas and Paint APIs • Break the design down to its layers