How to animate a line in android? - android

I need to draw a line from point A(x1,y1) to point B(x2, y2). But instead of just show the line, I need to see the line was actually drawn - little bit by little bit, at a controllable speed - from point A to point B. I've tried alarms and loops for this but cant find my solution.I am working on surface view. Please give solution for this

U can do it like this:
private int startX = 0;
private int startY = 0;
private int endX = 0;
private int endY = 0;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setColor(Color.RED);
}
};
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(startX, startY, endX, endY, paint);
if (endX != 300 && endY != 300) { // set end points
endY++;
endX++;
postInvalidateDelayed(15); // set time here
}
}

Related

Filling the gap between 2 paths on a canvas

Im developing an android app with the help of dlib, i have a code that with the help of the 68 face landmarks i draw a path for the outer part of the lips and another one for the inner path of the lips is there any way that with 2 different paths i can fill the gap in between them?
i've seen methods like, fill the outer one and fill the inside one with white so it looks like you're only painting the outside part but i cant do that since im painting it over the an image and i just want to color the lips, is there any way to accomplish this?
This is the code i used to paint the lips:
for (final VisionDetRet ret : results) {
// Draw landmark
int x = 0;
ArrayList<android.graphics.Point> landmarks = ret.getFaceLandmarks();
int ppX = 0, ppY = 0;
Paint mFaceLandmardkPaint = new Paint();
mFaceLandmardkPaint.setColor(Color.GREEN);
mFaceLandmardkPaint.setStrokeWidth(2);
mFaceLandmardkPaint.setStyle(Paint.Style.STROKE);
Path pth = new Path();
pth.setFillType(Path.FillType.EVEN_ODD);
Path pth2 = new Path();
pth2.setFillType(Path.FillType.EVEN_ODD);
for (android.graphics.Point point : landmarks) {
if (x >= 48 && x <= 60) {
int pointX = (int) (point.x);
int pointY = (int) (point.y);
if (x != 48) {
//canvas.drawLine(pointX, pointY, ppX, ppY, mFaceLandmardkPaint);
pth.lineTo(pointX, pointY);
} else {
pth.moveTo(pointX, pointY);
}
ppX = pointX;
ppY = pointY;
//canvas.drawCircle(pointX, pointY, 1, mFaceLandmardkPaint);
} else if (x > 60) {
pth.close();
}
if (x >= 61) {
int pointX = (int) (point.x);
int pointY = (int) (point.y);
if (x != 61) {
//canvas.drawLine(pointX, pointY, ppX, ppY, mFaceLandmardkPaint);
pth2.lineTo(pointX, pointY);
} else {
pth2.moveTo(pointX, pointY);
}
ppX = pointX;
ppY = pointY;
//canvas.drawCircle(pointX, pointY, 1, mFaceLandmardkPaint);
}
x++;
}
pth2.close();
Paint red = new Paint();
red.setColor(android.graphics.Color.RED);
red.setStyle(Paint.Style.FILL);
c.drawPath(pth2, mFaceLandmardkPaint);
c.drawPath(pth, red);
}
This code generates a full painted mouth.
Is there any way to accomplish this with native canvas, paint and paths?

DrawLine function changes color of my lines, when it shouldn't

This is the onDraw method I have:
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, mBitmapPaint); // Deseneaza Bitmapul mutabil
if (shapes.size() > 0) {
for (ShapeFromLines shapesfromline : shapes) {
if (shapesfromline.size() > 1) {
LogService.log("", "shapes: " + shapesfromline.size());
float startx, starty;
startx = shapesfromline.get(0).stopX;
starty = shapesfromline.get(0).stopY;
for (int i = 1; i < shapesfromline.size(); i++) {
LogService.log("", "----size color in ondraw: " + shapesfromline.get(i).getPaint().getColor());
canvas.drawLine(startx, starty, shapesfromline.get(i).getStopX(), shapesfromline.get(i).stopY, shapesfromline.get(i).getPaint());
LogService.log("", "shapes: drawn");
startx = shapesfromline.get(i).stopX;
starty = shapesfromline.get(i).stopY;
}
}
}
}
for (int i = 0; i < bitmaps.size(); i++) {
if ((bitmaps.get(i).bitmap != null)) {
canvas.save();
canvas.rotate(bitmaps.get(i).rectrotateVal, bitmaps.get(i).pX + (bitmaps.get(i).bitmap.getWidth() / 2), bitmaps.get(i).pY + (bitmaps.get(i).bitmap.getHeight() / 2));
mBitmapPaint.setAlpha(bitmaps.get(i).alpha);
// canvas.drawRect(bitmaps.get(i).rect, cPaint);
canvas.drawBitmap(bitmaps.get(i).bitmap, bitmaps.get(i).pX, bitmaps.get(i).pY, mBitmapPaint);
canvas.restore();
}
}
mBitmapPaint.setAlpha(255);
canvas.drawPath(mPath, paint);
}
}
As you can I I have some Shapes (each shape is created from an arraylist of points named ShapesFromLines. Now the first point of my shape is from the touchDown (ontouchevent), where I save the current location. then the other points are saved on touch up. When you press the screen the first time it will draw a point, then the second time, it will connect those 2 points, then 3, etc. I save the X,Y and Paint on each point.
As you can see, I have a logservice on draw, which returns the paint value for those points. Now I have a function with a color picker that changes the color of the current path. But this manages to change the color of all my straight lines. Now I checked, when I want to add a picture, the main paint is set to transparent. And then the lines are transparent, but the points (that should be connected) have the right color. Any ideea what could be wrong?
when I created the objects, i passed the paint as a reference, and when changing it, it would change the paint also.
I did this to fix it:
Paint linepaint = new Paint();
linepaint.setColor(paint.getColor());
linepaint.setAlpha(paint.getAlpha());
linepaint.setAntiAlias(true);
linepaint.setDither(true);
linepaint.setStyle(paint.getStyle());
linepaint.setStrokeJoin(paint.getStrokeJoin());
linepaint.setStrokeCap(paint.getStrokeCap());
linepaint.setStrokeWidth(paint.getStrokeWidth());
pointsForLines.add(new Points(stopX, stopY, linepaint));
Where paint was the global paint I was using before

How to draw only a part of arc in canvas

I'm developing an analog clock widget and the dial of clock is an image.
I want to draw an arc segment like in the image(as shown in orange).
paint.setColor(Color.GREEN);
paint.setStrokeWidth(20);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(100, 100, 200, paint);
I tried with drawcircle and also with drawArc but could not proceed since i want only a part of arc and not a complete arc. Any ideas ?
I made this class hope it help you, all variable are in spanish but its quite simple,
the constructor SemiCirculo use as parameters the rgb for the semicircle and the resolution (number of triangles for your semicircle)
the CalcularPuntosPorcentaje method use as parameters the center of the circle, the starting angle, the widht of the angle, and the radio.
the method ImprimeCirculo use the canvas as parameter, it is used to draw the semicircle once it has allready been calcultaed the points of the semicircle with the previus mentioned method.
the CalcularPuntosPorcentaje method is similar to CalcularPuntosPorcentaje, but insted of the starting and the widht angle parameters it use a % from 0 to 100
finaly the SetOffset and SetColor are used to change the default starting poing o reference for the angle and the color of the semicircle
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
public class SemiCirculo {
private Path circulo;
private Paint color;
private float px, py, radio, anguloI, anchoa,offset;
private int r, g, b;
private int resolucion;
private float puntox[],puntoy[];
public SemiCirculo(int r1, int g1, int b1, int resolucion1) {
this.offset = 0;
this.color = new Paint();
this.r = r1;
this.g = g1;
this.b = b1;
this.color.setColor(Color.rgb(r, g, b));
color.setAntiAlias(true);
circulo = new Path();
this.resolucion = resolucion1;
this.puntox = new float[this.resolucion];
this.puntoy = new float[this.resolucion];
this.anguloI = 0;
this.anchoa = 1;
}
public void SetOffset(float off) {
this.offset = off;
}
public void SetColor(int r1,int g1, int b1){
this.r=r1;
this.g=g1;
this.b=b1;
this.color.setColor(Color.rgb(r, g, b));
}
public void CalcularPuntosPorcentaje(float px1, float py1,
float porcentaje, float radio1) {
this.anguloI = 0 + this.offset;
this.px = px1;
this.py = py1;
this.radio = radio1;
this.anguloI = 0;
this.anchoa = porcentaje / 100 * 360;
this.CalcularPuntos(px, py, anguloI, anchoa, radio);
}
public void CalcularPuntos(float px1, float py1, float anguloI1,
float anchoangulo, float radio1) {
this.anguloI = anguloI1 + this.offset;
this.anchoa = anchoangulo;
this.px = px1;
this.py = py1;
this.radio = radio1 ;
float angulo = 360 - this.anguloI - this.anchoa;
for (int i = 0; i < resolucion; i++) {
this.puntox[i] = this.px - (float) Math.sin(Math.toRadians(angulo))
* this.radio;
this.puntoy[i] = this.py - (float) Math.cos(Math.toRadians(angulo))
* this.radio;
angulo = (360 - this.anguloI - this.anchoa)
+ ((this.anchoa / (float) (this.resolucion)) * (i + 2));
}
this.circulo.reset();
this.circulo.moveTo(this.px, this.py);
for (int i = 0; i < resolucion; i++) {
this.circulo.lineTo(this.puntox[i], this.puntoy[i]);
}
}
public void ImprimeCirculo(Canvas canvas) {
canvas.drawPath(this.circulo, this.color);
}
}
You need to use this method:
canvas.drawArc(innerRect, -11.0f, 11.0f + 6.0f, true, paintx);
for docs see here:
http://developer.android.com/reference/android/graphics/Canvas.html#drawArc%28android.graphics.RectF,%20float,%20float,%20boolean,%20android.graphics.Paint%29
Be sure set the angle parameters correctly! And use float!
The first angle is the start of your arc and the second angle param is the sweep angle, ie how many degrees long should the angle be - measured clockwise.
Try it, it will work for sure. Just needs a little playing around :-)

How to display text dynamically on pie chart in android?

I have worked on pie chart in android. I found an excellent solution from http://tutorials-android.blogspot.in/2011/05/how-create-pie-chart-in-android.html and worked on that. I am able to display the pie chart with colors but in my application in addition to colors I need to display the text also dynamically on that pie chart. How can I display text dynamically on those pie chart slices?
Please help me regarding this...Will be thankful...
To draw piechart you had use very long process.....Hope this help you..
public class Demo extends Activity {
/** Called when the activity is first created. */
float values[]={500,400,300,200,100};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout linear=(LinearLayout) findViewById(R.id.linear);
values=calculateData(values);
linear.addView(new MyGraphview(this,values));
}
private float[] calculateData(float[] data) {
// TODO Auto-generated method stub
float total=0;
for(int i=0;i<data.length;i++)
{
total+=data[i];
}
for(int i=0;i<data.length;i++)
{
data[i]=360*(data[i]/total);
}
return data;
}
public class MyGraphview extends View
{
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
private float[] value_degree;
private int[] COLORS={Color.BLUE,Color.GREEN,Color.GRAY,Color.CYAN,Color.RED};
RectF rectf = new RectF (10, 10, 200, 200);
int temp=0;
public MyGraphview(Context context, float[] values) {
super(context);
value_degree=new float[values.length];
for(int i=0;i<values.length;i++)
{
value_degree[i]=values[i];
}
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
for (int i = 0; i < value_degree.length; i++) {//values2.length; i++) {
if (i == 0) {
paint.setColor(COLORS[i]);
canvas.drawArc(rectf, 0, value_degree[i], true, paint);
}
else
{
temp += (int) value_degree[i - 1];
paint.setColor(COLORS[i]);
canvas.drawArc(rectf, temp, value_degree[i], true, paint);
}
}
}
}
}
Which set the color according to values in decending order...
And for text,you can set dynamic text separately and give color square in front of text:)
To draw text at the centre of each pie chart segment you need to calculate the centre of each segment. The centre of each text item to paint on that segment should align with that centre point - which is achieved by subtracting half the text bounds width from the central x coord (or using paint.setTextAlign(Align.CENTER); ) and half the text bound height from the central y coord.
As for finding the centre of a segment, it requires just a little bit more consideration than using simple geometry.
The central coords of a segment can be found by:
x = (/* radius of pie chart */ /2)*cos(/*angle in RADIANS */) [angle in radians = Math.toRadians(/*half the sweep angle in degrees*/)
y = (/* radius of pie chart */ /2)*sin(/*angle in RADIANS */)
Almost there... dont forget to add the x and y coords of the centre of your pie chart to the above x and y values, otherwise you're trying to paint on a circle centring on (0,0) in your custom view!
Say your pie chart is centred at the actual centre of your view, you want to be adding:
x += getWidth()/2;
y += getHeight()/2;
Last but not least, accounting for the length of the text to be painted - get the bounds of your text using, for example:
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextAlign(Align.CENTER); // This centres the text horizontally
String labelText = "TEST";
Rect textBounds = new Rect();
paint.getTextBounds(labelText, 0, labelText.length(), textBounds);
y -= textBounds.height()/2;
Then your text should appear correctly.
You can use the library called MPAndroidChart, which is very simple and easy to use. Simply import this
compile 'com.github.PhilJay:MPAndroidChart:v3.0.1'
and add this line in your gradle file
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
Hope this will help you.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mState != IS_READY_TO_DRAW) {
return;
}
canvas.drawColor(mBgcolor);
mBagpaints.setAntiAlias(true);
mBagpaints.setStyle(Paint.Style.FILL);
mBagpaints.setColor(0x88FF0000);
mBagpaints.setStrokeWidth(0.0f);
mLinePaints.setAntiAlias(true);
mLinePaints.setColor(0xff000000);
mLinePaints.setStrokeWidth(3.0f);
mLinePaints.setStyle(Paint.Style.STROKE);
RectF mOvals = new RectF(mGapleft, mGapTop, mWidth - mGapright, mHeight
- mGapBottm);
mStart = START_INC;
PieDetailsItem item;
for (int i = 0; i < mdataArray.size(); i++) {
item = (PieDetailsItem) mdataArray.get(i);
mBagpaints.setColor(item.color);
mSweep = (float) 360* ((float) item.count / (float) mMaxConnection);
canvas.drawArc(mOvals, mStart, mSweep, true, mBagpaints);
canvas.drawArc(mOvals, mStart, mSweep, true, mLinePaints);
mStart = mStart + mSweep;
// set your text here
canvas.drawText("here is some text", mStart, someYvalue, mLinePaints);
}
mState = IS_DRAW;
}
Just some drawText() calls ought to work fine.
You'll have to do a little math to decide where your y coordinate should be

Android - Why doesn't my axis draw?

The following is supposed to draw an axis in the middle of the screen. However, nothing appears. I am positive that is has to do with my Paths.
#Override
protected void onDraw(Canvas canvas) {
//Variables declared here temporarily for testing purposes
int canterX = getWidth() /2;
int centerY = getHeight() /2;
int radius = 150;
Path verticalAxis = new Path();
Path horizontalAxis = new Path();
drawAxis();
}
private void drawAxis(Canvas canvas) {
int axisLineThickness = 1;
int verticalEndX;
int verticalEndY;
int horizontalEndX;
int horizontalEndY;
Paint axisPaint = new Paint();
axisPaint.setColor(Color.WHITE);
axisPaint.setStrokeWidth(axisLineThickness);
double theta;
for(int i = 90; i < 360; i += 180) {
theta = toRadians(i);
verticalEndX = centerX + (int) ((cos(theta)) * radius);
verticalEndY = centerY + (int) ((sin(theta)) * radius);
verticalAxis.moveTo(centerX, centerY);
verticalAxis.lineTo(verticalEndX, verticalEndY);
}
canvas.drawPath(verticalAxis, axisColor);
for(int i = 90; i < 360; i += 180) {
theta = toRadians(i);
horizontalEndX = centerX + (int) ((cos(theta)) * radius);
horizontalEndY = centerY + (int) ((sin(theta)) * radius);
horizontalAxis.moveTo(centerX, centerY);
horizontalAxis.lineTo(verticalEndX, verticalEndY);
}
canvas.drawPath(horizontalAxis, axisColor);
}
I know I can make the axis draw if I add the following to the vertical and horizontal for loops respectively:
Vertical For Loop:
canvas.drawLine(centerX, centerY, verticalEndX, verticalEndY, paint);
Horizontal For Loop:
canvas.drawLine(centerX, centerY, horizontalEndX, horizontalEndY, paint);
But I don't want to solve the issue this way, I want to correct what is wrong with my paths. Can anyone tell me why the points aren't adding to my path correctly? The loop should only go through twice which creates a line for each side of the axis. Ie. One loop creates the top of the vertical axis and the second loop creates the bottom part.
How do I get my paths create that full line and then draw it outside of the loop?
Paint's default style appears to be FILL, so maybe just having a line in your path is confusing things. Try setting it to STROKE:
axisPaint.setStyle(Paint.Style.STROKE);
See Paint.Style

Categories

Resources