How to Draw a Circle with Animation in Android with Circle Size Based on a Value

How to draw a circle with animation in android with circle size based on a value

You have to draw the circle view, and after that you should create an animation to it.

Creating the circle view:

public class Circle extends View {

private static final int START_ANGLE_POINT = 90;

private final Paint paint;
private final RectF rect;

private float angle;

public Circle(Context context, AttributeSet attrs) {
super(context, attrs);

final int strokeWidth = 40;

paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
//Circle color
paint.setColor(Color.RED);

//size 200x200 example
rect = new RectF(strokeWidth, strokeWidth, 200 + strokeWidth, 200 + strokeWidth);

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

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint);
}

public float getAngle() {
return angle;
}

public void setAngle(float angle) {
this.angle = angle;
}
}

Creating the animation class to set the new angle:

public class CircleAngleAnimation extends Animation {

private Circle circle;

private float oldAngle;
private float newAngle;

public CircleAngleAnimation(Circle circle, int newAngle) {
this.oldAngle = circle.getAngle();
this.newAngle = newAngle;
this.circle = circle;
}

@Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime);

circle.setAngle(angle);
circle.requestLayout();
}
}

Put circle into your layout:

<com.package.Circle
android:id="@+id/circle"
android:layout_width="300dp"
android:layout_height="300dp" />

And finally starting the animation:

Circle circle = (Circle) findViewById(R.id.circle);

CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240);
animation.setDuration(1000);
circle.startAnimation(animation);

The result is:
Sample Image

Embedded Animation , draw circle and rotate image

Please follow this instrutions:

Add this library to your project (gradle):

implementation 'com.github.Triggertrap:SeekArc:v1.1'

Note that due to a bug you will need to add this line in the manifest under the application tag:

tools:replace="android:icon"

in the activity layout add the view:
i prepare the parameters for your preferences:

<com.triggertrap.seekarc.SeekArc
android:id="@+id/seekArc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="30dp"
app:progress="20"
app:arcColor="#00ffffff"
app:thumb="@drawable/ic_androido"
app:startAngle="0"
app:sweepAngle="360"
app:touchInside="false"
android:focusable="false"
android:clickable="false"/>

add this drawable in your resource/drawable (ic_androido.xml):

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="42dp"
android:height="42dp"
android:viewportWidth="413.137"
android:viewportHeight="413.137">

<path
android:fillColor="#AAC148"
android:pathData="M311.358,136.395H101.779c-4.662,0-8.441,3.779-8.441,8.441v175.749 c0,4.662,3.779,8.441,8.441,8.441h37.363v59.228c0,13.742,11.14,24.883,24.883,24.883l0,0c13.742,0,24.883-11.14,24.883-24.883 v-59.228h34.803v59.228c0,13.742,11.14,24.883,24.883,24.883l0,0c13.742,0,24.883-11.14,24.883-24.883v-59.228h37.882 c4.662,0,8.441-3.779,8.441-8.441V144.836C319.799,140.174,316.02,136.395,311.358,136.395z" />
<path
android:fillColor="#AAC148"
android:pathData="M57.856,136.354L57.856,136.354c-13.742,0-24.883,11.14-24.883,24.883v101.065 c0,13.742,11.14,24.883,24.883,24.883l0,0c13.742,0,24.883-11.14,24.883-24.883V161.237 C82.738,147.495,71.598,136.354,57.856,136.354z" />
<path
android:fillColor="#AAC148"
android:pathData="M355.281,136.354L355.281,136.354c-13.742,0-24.883,11.14-24.883,24.883v101.065 c0,13.742,11.14,24.883,24.883,24.883l0,0c13.742,0,24.883-11.14,24.883-24.883V161.237 C380.164,147.495,369.024,136.354,355.281,136.354z" />
<path
android:fillColor="#AAC148"
android:pathData="M103.475,124.069h205.692c5.366,0,9.368-4.943,8.266-10.195 c-6.804-32.428-27.45-59.756-55.465-75.543l17.584-31.727c1.19-2.148,0.414-4.855-1.734-6.045 c-2.153-1.193-4.856-0.414-6.046,1.734l-17.717,31.966c-14.511-6.734-30.683-10.495-47.734-10.495 c-17.052,0-33.224,3.761-47.735,10.495L140.869,2.292c-1.191-2.149-3.898-2.924-6.045-1.734c-2.148,1.19-2.924,3.897-1.734,6.045 l17.584,31.727c-28.015,15.788-48.661,43.115-55.465,75.544C94.106,119.126,98.108,124.069,103.475,124.069z M267.697,76.786 c0,5.282-4.282,9.565-9.565,9.565c-5.282,0-9.565-4.282-9.565-9.565c0-5.282,4.282-9.565,9.565-9.565 C263.415,67.221,267.697,71.504,267.697,76.786z M154.508,67.221c5.282,0,9.565,4.282,9.565,9.565c0,5.282-4.282,9.565-9.565,9.565 c-5.282,0-9.565-4.282-9.565-9.565C144.943,71.504,149.225,67.221,154.508,67.221z" />

The code in your Activity class:

        SeekArc seekArc;
int progress = 0;
seekArc = (SeekArc) findViewById(R.id.seekArc);

final Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
seekArc.setProgress(progress++);
if (progress >= 100) {
handler.removeCallbacks(this);
return;
}
handler.postDelayed(this, 300);
}
}, 50);

Sample Image

library credit to https://github.com/neild001/SeekArc

icon credit to https://www.flaticon.com/free-icon/android_174836#term=android&page=1&position=1

Flutter Draw a circle border with 3 multiple colors and values

Animation can be handled by TweenAnimationBuilder and it will be played on build.
To achieve desired result we must use customPainter.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}

class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TweenAnimationBuilder(
duration: const Duration(seconds: 2),
tween: Tween(begin: 0.0, end: 1.0),
curve: Curves.easeOutCubic,
builder: (BuildContext context, dynamic value, Widget child) {
return CustomPaint(
painter: OpenPainter(
totalQuestions: 300,
learned: 75,
notLearned: 75,
range: value),
);
},
),
),
);
}
}

class OpenPainter extends CustomPainter {
final learned;
final notLearned;
final range;
final totalQuestions;
double pi = math.pi;

OpenPainter({this.learned, this.totalQuestions, this.notLearned, this.range});
@override
void paint(Canvas canvas, Size size) {
double strokeWidth = 7;
Rect myRect = const Offset(-50.0, -50.0) & const Size(100.0, 100.0);

var paint1 = Paint()
..color = Colors.red
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke;
var paint2 = Paint()
..color = Colors.green
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke;
var paint3 = Paint()
..color = Colors.yellow
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke;

double firstLineRadianStart = 0;
double _unAnswered = (totalQuestions - notLearned - learned) * range / totalQuestions;
double firstLineRadianEnd = (360 * _unAnswered) * math.pi / 180;
canvas.drawArc(
myRect, firstLineRadianStart, firstLineRadianEnd, false, paint1);

double _learned = (learned) * range / totalQuestions;
double secondLineRadianEnd = getRadians(_learned);
canvas.drawArc(myRect, firstLineRadianEnd, secondLineRadianEnd, false, paint2);
double _notLearned = (notLearned) * range / totalQuestions;
double thirdLineRadianEnd = getRadians(_notLearned);
canvas.drawArc(myRect, firstLineRadianEnd + secondLineRadianEnd, thirdLineRadianEnd, false, paint3);

// drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)
}

double getRadians(double value) {
return (360 * value) * pi / 180;
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}

Sample Image
Hopefully someone will find this helpfull :) Feel free to improve on this! Happy coding !

How to animate the drawing of arc in android

One of the most important rules of programming for Android is that you should limit things you do in onDraw as much as you can. Ideally you shouldn't be allocating anything in onDraw method. Just drawing on canvas.

And unfortunately that's only the first thing that is wrong with your code.

You should think about it this way: a single canvas object is only viable during a single (simple) onDraw method call. So you cannot reuse it inside a separate thread.

For your case you should start a separate thread (just like you did in your example), but inside it you should only update a View's field that represents the arc's angle and ask for your View to redraw (the invalidate() method).

public class TestView extends View {

private float currentAngle;

//... some needed methods (be sure to init rectF and paint somewhere here)

public void startAnimatingArc(final float maxAngle) {
currentAngle = 0;
new Thread(new Runnable() {
public void run() {
while (currentAngle < maxAngle) {
invalidate();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
currentAngle++;
}
}).start();
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rectF, 0, currentAngle, false, paint);
// you should try not to add anything else in this call
// (unless you want to draw something else as well)
}
}

The whole "animation" code architecture could be much better as well. But the main problem is with the canvas interaction, so that's what I corrected in your code.



Related Topics



Leave a reply



Submit