Reputation: 206
Can anyone help me out on how I going to draw semicircle of the picture below with canvas and also how to detect the collection of the drawing object?
I had try to draw it using XML and i dont know how to detect the collision of it. I just want to detect the collision of the black part but not the whole circle. Thank you.
Upvotes: 4
Views: 7982
Reputation: 15835
I've just done something similar, with a custom View:
class SemiCircleView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val paint: Paint = Paint()
private var rectangle: RectF? = null
private var margin: Float
init {
paint.isAntiAlias = true
paint.color = ContextCompat.getColor(context, R.color.colorAquamarine)
paint.style = Paint.Style.STROKE
paint.strokeWidth = 5.dpToPx()
margin = 3.dpToPx() // margin should be >= strokeWidth / 2 (otherwise the arc is cut)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (rectangle == null) {
rectangle = RectF(0f + margin, 0f + margin, width.toFloat() - margin, height.toFloat() - margin)
}
canvas.drawArc(rectangle!!, 90f, 180f, false, paint)
}
}
Add it you your XML layout like this:
<com.example.view.SemiCircleView
android:layout_width="120dp"
android:layout_height="120dp"/>
That's the result:
In my case I want to programmatically control the % of the circle being drawn, so I've added a method setArcProportion
that controls that:
class SemiCircleView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val mainPaint: Paint = Paint()
private val backgroundPaint: Paint = Paint()
private var rectangle: RectF? = null
private var margin: Float
private var arcProportion: Float = 0f
init {
mainPaint.isAntiAlias = true
mainPaint.color = ContextCompat.getColor(context, R.color.colorLutea)
mainPaint.style = Paint.Style.STROKE
mainPaint.strokeWidth = 5.dpToPx()
backgroundPaint.isAntiAlias = true
backgroundPaint.color = ContextCompat.getColor(context, R.color.black_08)
backgroundPaint.style = Paint.Style.STROKE
backgroundPaint.strokeWidth = 5.dpToPx()
margin = 3.dpToPx() // margin should be >= strokeWidth / 2 (otherwise the arc is cut)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (rectangle == null) {
rectangle = RectF(0f + margin, 0f + margin, width.toFloat() - margin, height.toFloat() - margin)
}
canvas.drawArc(rectangle!!, -90f, arcProportion * 360, false, mainPaint)
// This 2nd arc completes the circle. Remove it if you don't want it
canvas.drawArc(rectangle!!, -90f + arcProportion * 360, (1 - arcProportion) * 360, false, backgroundPaint)
}
/**
* @param arcProportion The proportion of the semi circle arc, from 0 to 1. Setting 0 makes the arc invisible, and 1
* makes a whole circle.
*/
fun setArcProportion(arcProportion: Float) {
this.arcProportion = arcProportion
invalidate()
}
}
So if I do semiCircleView.setArcProportion(0.62f)
I have:
Bonus - To make the arc grow with an animation modify setArcProportion
like this:
private const val ANIMATION_BASE_DURATION_MS: Long = 500 // milliseconds
fun setArcProportion(arcProportion: Float) {
ValueAnimator.ofFloat(0f, arcProportion).apply {
interpolator = DecelerateInterpolator()
// The animation duration is longer for a larger arc
duration = ANIMATION_BASE_DURATION_MS + (arcProportion * ANIMATION_BASE_DURATION_MS).toLong()
addUpdateListener { animator ->
[email protected] = animator.animatedValue as Float
[email protected]()
}
start()
}
}
Upvotes: 11
Reputation: 726
In your onDraw method draw a circle .
canvas.drawCircle(x, y, 10, paint);
Now draw a rect with your background colour
Paint fillBackgroundPaint = new Paint();
fillBackgroundPaint.setAntiAlias(true);
fillBackgroundPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(x,y+10,x+10,y-10);
This should serve the purpose.
Upvotes: -1