Home > front end >  Custom view will not update if run after onViewCreated()
Custom view will not update if run after onViewCreated()

Time:01-24

I have built a custom view class called progressCircle which is a snapchat-like, circular progress bar - this is inside a constraint layout, over a circular button.

This view has parameter angle which when called from onViewCreated(), will work perfectly if run

progressCircle.angle = 100f

However, I am trying to animate this onClick. If I run this same code, onClick, the progressCircle will not show up?! After trial and error, I found that updating the background colour here made the view visible & it was updated. IE;

 button.setOnClickListener {
      progressCircle.setBackgroundColor(android.R.color.transparent)
      progressCircle.angle = 270f
 }

Whats going on here, and how can I fix this so I can animate it properly...

Edit:

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

    private val paint: Paint
    private val rect: RectF

    private val fillPaint: Paint
    private val fillRect: RectF

    var angle: Float
    var startAngle: Float = 0f

    init {

        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ProgressCircle)
        angle = typedArray.getFloat(R.styleable.ProgressCircle_angle, 0f)
        typedArray.recycle()

        val offsetAngle = 0f
        val color = getColor(context, R.color.outputON)
        val strokeWidth = 15f
        val circleSize = 276f

        paint = Paint().apply {
            setAntiAlias(true)
            setStyle(Paint.Style.STROKE)
            setStrokeWidth(strokeWidth)
            setColor(color)
        }

        rect = RectF(
            strokeWidth,
            strokeWidth,
            (circleSize - strokeWidth),
            (circleSize - strokeWidth)
        )

        fillPaint = Paint().apply {
            setAntiAlias(true)
            setStyle(Paint.Style.FILL)
            setColor(getColor(context, R.color.flat_blue_1))
        }

        val offsetFill = strokeWidth
        fillRect = RectF(
            offsetFill,
            offsetFill,
            (circleSize - offsetFill),
            (circleSize - offsetFill)
        )

        //Initial Angle (optional, it can be zero)
        angle = offsetAngle
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (getColor(context, R.color.flat_blue_1) > 0) {
            canvas.drawArc(rect, 0f, 360f, false, fillPaint)
        }
        canvas.drawArc(rect, startAngle, angle, false, paint)
    }
}

TIA

CodePudding user response:

By default, a View only redraws itself when something has changed - i.e., when the view is "invalidated" as per the View documentation:

Drawing is handled by walking the tree and recording the drawing commands of any View that needs to update. After this, the drawing commands of the entire tree are issued to screen, clipped to the newly damaged area.

If you want your custom view to redraw itself when the angle property is changed, you need to call invalidate():

var angle: Float
    set(value) {
        // Do the default behavior of setting the value
        field = value

        // Then call invalidate() to force a redraw
        invalidate()
    }
}
  •  Tags:  
  • Related