0

I'm making half circle custom view on Android. However, I'm struggling to remove the un-needed bottom white space on wrap content. I think because it is drawing based on 'a full circle' calculation. I'm sharing my Custom View implementation, as well as how I call it from my application. See also this image: Click here for the screenshot

Note: If I change the onMeasure size, then it will cut the upper circle: Click here for the screenshot

class CircularProgressView(context: Context, attrs: AttributeSet) : View(context, attrs) {

    private var circle = RectF()
    private val paint = Paint()
    private var size = 0

    init {
        paint.isAntiAlias = true
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = strokeWidth.toFloat()
        paint.strokeCap = Paint.Cap.BUTT

        setupAttributes(attrs)
    }

    private fun setupAttributes(attrs: AttributeSet?) {

        // TypedArray objects are shared and must be recycled.
        typedArray.recycle()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        drawBackground(canvas)
    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        size = Math.min(measuredWidth, measuredHeight)

        setMeasuredDimension(size, size)
    }


    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)

        val centerX = w / 2
        val centerY = h / 2

        // Pick the minimum value so that it can fit the container. Radius is half size
        val radius = size / 2f

        // Create the background and progress circle, adding dialStrokeWidth in equation so that make sure the dial can fit container
        circle.top = (centerY - radius)
        circle.bottom = (centerY + radius)
        circle.left = (centerX - radius)
        circle.right = (centerX + radius)
    }

    private fun drawBackground(canvas: Canvas) {
        paint.shader = null
        paint.color = backGroundColor
        canvas.drawArc(circle, startAngle, sweepAngle, false, paint)
    }
}

This is how I use it:

<com.enova.circular_progress.CircularProgressView
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:background="@color/white"
                    app:backgroundColor="@color/colorHint"
                    app:dialColor="@color/colorPrimary"
                    app:foregroundColorEnd="@color/colorPrimary"
                    app:foregroundColorStart="@color/colorPrimaryDark"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toRightOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    app:percent="80">
                </com.enova.circular_progress.CircularProgressView>               

nsutanto
  • 93
  • 3
  • 9

1 Answers1

0

Change your onMeasure. YOu're setting your measured width and height to the same value. If you only want to display a top half circle, then you want to set the height to half the width. Otherwise, it will think the view is the full circle in height.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • SO it shouldn't be half, since iafter looking at your screenshot you go below the halfway point (more than 180 degrees of arc). Figure out how far below 0 you go using trigonometry and change your size based on that value. But the answer is that your onMeasure was wrong and needs to be adjusted. If its not accurate, you get whitespace – Gabe Sechan Apr 02 '19 at 19:20