Creating Custom Widgets in Badge Magic Android

In this blog, we are going to have a look on how I created this badge preview in fossasia/badge-magic-android.  What is Canvas? Canvas is a class in Android that performs 2D drawing of different objects onto the screen. The saying “a blank canvas” is very similar to what a Canvas object is on Android. It is basically, an empty space to draw onto. Canvas Coordinate System The coordinate system of the Android canvas starts in the top left corner, where [0,0] represents that point. The y axis is positive downwards, and x axis positive towards the right. Some basics of Canvas, lets see how we drew this Preview Badge. The Badge consists of only 2 components: Rounded Rectangle ( Background )Normal Rectangles ( LED Lights ) Let’s see how we create rounded rectangles in android.  // Draw Background canvas.drawRoundRect(bgBounds, 25f, 25f, bgPaint) Using drawRoundRect() we can easily create the badge background. 25f specified is the corner radius of the rectangle. The LED Lights are just drawable resources which are used according to the current state of the LED. private fun drawLED(condition: Boolean, canvas: Canvas, xValue: Int, yValue: Int) { if (condition) { ledEnabled.bounds = cells[xValue].list[yValue] ledEnabled.draw(canvas) } else { ledDisabled.bounds = cells[xValue].list[yValue] ledDisabled.draw(canvas) } } This function draws the LED Lights if the condition is satisfied. When we consider a custom view, we need to consider the changes which occur according. These layout changes are to be controlled and maintained accordingly, Let’s see how we manage the positioning of the led lights for every android device. Spoiler: Simple 10th Grade Maths xD override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { super.onLayout(changed, left, top, right, bottom) val offset = 30 val singleCell = (right - left - (offset * 3)) / badgeWidth val offsetXToAdd: Int = ((((right - offset).toFloat() - (left + offset).toFloat()) - (singleCell * badgeWidth)) / 2).toInt() + 1 cells = mutableListOf() for (i in 0 until badgeHeight) { cells.add(Cell()) for (j in 0 until badgeWidth) { cells[i].list.add(Rect( (offsetXToAdd * 2) + j * singleCell, (offsetXToAdd * 2) + i * singleCell, (offsetXToAdd * 2) + j * singleCell + singleCell, (offsetXToAdd * 2) + i * singleCell + singleCell )) } } bgBounds = RectF((offsetXToAdd).toFloat(), (offsetXToAdd).toFloat(), ((singleCell * badgeWidth) + (offsetXToAdd * 3)).toFloat(), ((singleCell * badgeHeight) + (offsetXToAdd * 3)).toFloat()) } We create an offset which is nothing but the gap from the screen edge to the badge itself, now we need to have gaps on both sides of the badge and we also leave half the offset inside the badge which is the difference between the badge background and the LED starting point, hence we calculate the value of single cells by:  val singleCell = (right - left - (offset * 3)) / badgeWidth We minus the no of pixels on the right of the display to the left, to get the width of the actual screen. Then we minus the padding from the left and right which is offset * 3…

Continue ReadingCreating Custom Widgets in Badge Magic Android