I am trying to make a custom view with concentric circles made up of dots. I have attached a screenshot for reference. Till the time custom view just have concentric circles it works fine but as soon as I apply DashPathEffect it makes the whole screen sluggish which is very well observable when you try to open or close the navigation drawer. I have attached the logs below. Here is the link to the video explaining the issue https://youtu.be/5Mgz4QhXaQI
Custom View
public class ConcentricCircularView extends View {
    private static final String TAG = "ConcentricCircularView";
    private Paint paint;
    private Context context;
    public ConcentricCircularView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(Utils.dipToPixels(context,getResources().getDimension(R.dimen.d1)));
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
        this.context=context;
    }
    int onDrawCounter = 0;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e(TAG, "Actual radius"+getWidth());
        int radius= (int) (getWidth()/3);
        int distanceBtwDots= (int) Utils.dipToPixels(context,getResources().getDimension(R.dimen.d10));
        Log.e(TAG, "Counter: "+onDrawCounter++);
        for (int i=0;i<10;i++){
            DashPathEffect dashPath = new DashPathEffect(new float[]{1,distanceBtwDots}, 0);
            paint.setPathEffect(dashPath);
//            Log.e(TAG, "Current radius "+radius);
            canvas.drawCircle(getWidth()/2, getHeight()/2,radius, paint);
            radius= (int) (radius+Utils.dipToPixels(context,getResources().getDimension(R.dimen.d15)));
            distanceBtwDots= (int) (distanceBtwDots+Utils.dipToPixels(context,getResources().getDimension(R.dimen.d1)));
        }
    }
}
Logs from console
[

You just have to keep a boolean indicating whether you have to draw something. Currently, you are needlessly drawing exact same thing on each iteration.
As stated by Romain Guy here:
In general, hardware layers should be set on views that are expensive to draw and whose content won't change often.
public class ConcentricCircularView extends View {
    ...
    private boolean shouldDraw = true;
    ...
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (shouldDraw) {
            shouldDraw = false;
            setLayerType(View.LAYER_TYPE_HARDWARE, null);
            // draw your view here
        }
    }
    public void setShouldDraw(boolean shouldDraw) {
        this.shouldDraw = shouldDraw;
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With