Array of objects to draw on canvas - java

I have an array of objects that need to be drawn to a canvas; each object is represented as:
scatterPlot.java
package scatter.plot;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.view.View;
public class scatterPoint extends View {
private final Point coordinates;
private final int itemShape;
private Paint itemColour = new Paint(Paint.ANTI_ALIAS_FLAG);
private scatterPoint[] mShapes;
public scatterPoint(Context context, Point p, int shape, Paint colour) { // Constructor
super(context);
coordinates = p;
itemShape = shape;
itemColour = colour;
}
//get set points
public void setPoints(scatterPoint[] p){
mShapes = p;
}
public scatterPoint[] getScatterPoints(){
return mShapes;
}
#Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
int radius = 10;
for (scatterPoint i : mShapes) {
switch(itemShape){
case 0:
canvas.drawRect(i.coordinates.x - radius, i.coordinates.y - radius, i.coordinates.x + radius, i.coordinates.y + radius, i.itemColour);
break;
case 1:
Path path = new Path();
path.moveTo(i.coordinates.x - radius, i.coordinates.y - radius);
path.lineTo(i.coordinates.x, i.coordinates.y + radius);
path.lineTo(i.coordinates.x + radius, i.coordinates.y - radius);
path.lineTo(i.coordinates.x - radius, i.coordinates.y - radius);
path.close();
canvas.drawPath(path, i.itemColour);
break;
case 2:
canvas.drawCircle(i.coordinates.x, i.coordinates.y, radius, i.itemColour);
break;
}
}
}
public Point getCoordinates(){
return coordinates;
}
public int getShape(){
return itemShape;
}
public Paint getColour(){
return itemColour;
}
}
Relevant methods from main (ScatterPlotActivity.java):
package scatter.plot;
import java.util.Random;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.WindowManager;
import android.widget.FrameLayout;
public class ScatterPlotActivity extends Activity {
FrameLayout main;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
main = (FrameLayout) findViewById(R.id.main_view);
scatterPoint[] points = generatePoints();
//
//add scatterPoint to main
//
}
public scatterPoint[] generatePoints(){
//
return points;
}
}
Any ideas on what is wrong with how I'm trying to draw these objects?

I think the problem comes from the fact that you're creating each time a new FrameLayout. Declare your FrameLayout in your main and then call your method drawPoints like this:
drawPoint(points[i], main);
and your method will look like this :
public void drawPoint(scatterPoint point, FrameLayout main) {
main.addView(point);
}
This way they will always be added to the same Layout.

The problem is:
public void drawPoint(scatterPoint point) {
FrameLayout main = (FrameLayout) findViewById(R.id.main_view);
main.addView(point);
}
Make your FrameLayout main; a global variable. Then, right after you call setContentView(R.layout.x); in onActivityCreated(), call main = (FrameLayout) findViewById(R.id.main_view);
You only want to make this call once. Every time the current implementation calls public void drawPoint(scatterPoint point);, the FrameLayout is being reinitialized and clearing all the old drawings.

By the looks of things, you are actually drawing all of your scatter point views. However, due to how you are adding them to the FrameLayout, they are stacking on top of each other. Look in your drawPoint() method. You add the point to FrameLayout, which was designed to only handle one view (for more on this statement refer to FrameLayout), and the FrameLayout just draws the new view right over the last view drawn.
class ScatterShape {
public float mX = 0, mY = 0;
public int mShape = 0;
public Paint mColor = new Paint();
public ScatterShape(float x, float y, int shape, int color) {
mX = x;
mY = y;
mShape = shape;
mColor.setColor(color);
}
}
public class ScatterShaperDrawer extends View {
private List<ScatterShape> mShapes = new ArrayList<ScatterShapes>();
private float mmRadius = 5;
// Make getter and setter
#Override public void onDraw(Canvas canvas) {
for (ScatterShape i : mShapes) {
switch(i.mShape){
case 0:
canvas.drawRect(i.mX - mRadius, i.mY - mRadius, i.mX + mRadius, i.mY + mRadius, itemColor);
break;
case 1:
Path path = new Path();
path.moveTo(i.mX - mRadius, i.mY - mRadius);
path.lineTo(i.mX, i.mY + mRadius);
path.lineTo(i.mX + mRadius, i.mY - mRadius);
path.lineTo(i.mX - mRadius, i.mY - mRadius);
path.close();
canvas.drawPath(path, i.mColor);
break;
case 2:
canvas.drawCircle(i.mX, i.mY, mRadius, i.mColor);
break;
}
}
}
}

Related

Creating a path for animation given a set of coordinate points in Android Studio

I asked this question before, but now I've stumbled around and figured out a direction.
Basically, I need to record the user's finger's movements around the screen, and replay an animation of that movement on a view upon pressing a replay button, as well as a reverse animation of it when pressing a reverse button. I'm trying to achieve this by saving the finger's (x,y) coordinates in onTouch(), which I store in an ArrayList for PointF objects, then create a path for the view to animate on based on the coordinates stored in said ArrayList. Then I'll need to animate along that path. However, I am not sure how to create a path based on an arraylist that could be of any length.
Code related to the animation so far:
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import java.util.ArrayList;
/**
* TODO: document your custom view class.
*/
public class MyView extends View {
ArrayList<PointF>theCoords;
ArrayList<Float> xcord;
ArrayList<Float> ycord;
private Paint paint;
//coordinates
private float x;
private float y;
public MyView (Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
xcord = new ArrayList<Float>();
ycord= new ArrayList<Float>();
theCoords=new ArrayList<PointF>();
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPaint();
xcord = new ArrayList<Float>();
ycord= new ArrayList<Float>();
theCoords=new ArrayList<PointF>();
}
public MyView(Context context) {
super(context);
initPaint();
xcord = new ArrayList<Float>();
ycord= new ArrayList<Float>();
theCoords=new ArrayList<PointF>();
}
//initialize paint object
private void initPaint(){
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setTextSize(40);
}
#Override
//drawing on the canvas
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
canvas.drawCircle(x,y,50,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
theCoords.clear();
xcord.clear();
ycord.clear();
x = event.getX();
y = event.getY();
PointF p1 = new PointF(x,y);
theCoords.add(p1);
postInvalidate();
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
x = event.getX();
y = event.getY();
PointF p2 = new PointF(x,y);
theCoords.add(p2);
postInvalidate();
break;
}
return true;
}
#RequiresApi(api = Build.VERSION_CODES.R)
public void replayAnim()
{
PointF pcur;
PointF pnext;
//create path
for(int i =0;i<theCoords.size()-1;i++)
{
pcur=new PointF(theCoords.get(i));
pnext=new PointF(theCoords.get(i+1));
//how to form a path with these?
}
//anim along the path
}
public void reverseAnim()
{
//the original code I have, which only
//moves the view to its original position
for (int i = xcord.size() - 1; i >= 0; i--)
{
x = xcord.get(i);
y = ycord.get(i);
Log.d("ReverseAnimation", "x: " + Float.toString(x));
postInvalidate();
}
}
public float getX()
{
return x;
}
public float getY()
{
return y;
}
} ```

How to update the onDraw() of Java on android studio

So I just started learn how to create an app with android-studio and I'm trying to make a simple animation. For exemple I thought of a bouncing ball, but for the moment I can't make my ball move. I don't understand perfectly how everything works but I managed to draw a ball in the screen, now I want my ball to move but the problem is that I can't manage to update my screen (which is drawn by the onDraw function) while it is opened, the phone just show the final screen when all the movement is finished. I heard that I had to use invalidate function but I don't know how to use it and I tried to make a move function to use it. I would like to know what would be the simplest change I have to do on my code to see the ball moving on the screen.
package com.example.myfirstapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import java.util.Random;
public class AnimationActivity extends AppCompatActivity {
public int posX= 300;
public int posY= 300;
public int radius= 50;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
RenderView renderView = new RenderView(this);
setContentView(renderView);
while(posX<2000) {
renderView.move();
setContentView(renderView);
}
}
class RenderView extends View {
public RenderView(Context context){
super(context);
}
public void move(){
posX=posX+1;
//SystemClock.sleep(2);
invalidate();
}
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
canvas.drawRGB(255, 255, 255);
Paint ball = new Paint();
ball.setAntiAlias(true);
ball.setARGB(255,255,0,0);
ball.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawCircle(posX,posY,radius,ball);
}
}
}
Try this code
public class MainActivity extends AppCompatActivity {
public int posX = 300;
public int posY = 300;
public int radius = 50;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
RenderView renderView = new RenderView(this);
setContentView(renderView);
/* while (posX < 2000) {
renderView.move();
renderView.invalidate();
}*/
}
class RenderView extends View {
public RenderView(Context context) {
super(context);
}
public void move() {
posX++;
//SystemClock.sleep(2);
}
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
canvas.drawRGB(255, 255, 255);
Paint ball = new Paint();
ball.setAntiAlias(true);
ball.setColor(getResources().getColor(R.color.colorAccent));
ball.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawCircle(posX, posY, radius, ball);
if (posX > 350) {
posX = 300;
posY+=10;
}
posX++;
invalidate();
}
}
}

Save real-time detected face(Track Faces) image using 'android-vision' library

For my university thesis, I need a android program which can detect and recognize a face in real time. I have read about 'android-vision' library and tested the example code.
https://github.com/googlesamples/android-vision/tree/master/visionSamples/FaceTracker/app/src/main/java/com/google/android/gms/samples/vision/face/facetracker.
Modified code:
package com.google.android.gms.samples.vision.face.facetracker;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.samples.vision.face.facetracker.ui.camera.GraphicOverlay;
import com.google.android.gms.vision.face.Face;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Graphic instance for rendering face position, orientation, and landmarks within an associated
* graphic overlay view.
*/
class FaceGraphic extends GraphicOverlay.Graphic
{
private static final float FACE_POSITION_RADIUS = 10.0f;
private static final float ID_TEXT_SIZE = 40.0f;
private static final float ID_Y_OFFSET = 50.0f;
private static final float ID_X_OFFSET = -50.0f;
private static final float BOX_STROKE_WIDTH = 5.0f;
public Canvas canvas1;
public Face face;
int i =0;
int flag = 0;
private static final int COLOR_CHOICES[] = {
Color.BLUE,
Color.CYAN,
Color.GREEN,
Color.MAGENTA,
Color.RED,
Color.WHITE,
Color.YELLOW
};
private static int mCurrentColorIndex = 0;
private Paint mFacePositionPaint;
private Paint mIdPaint;
private Paint mBoxPaint;
private volatile Face mFace;
private int mFaceId;
private float mFaceHappiness;
public Bitmap myBitmap ;
FaceGraphic(GraphicOverlay overlay)
{
super(overlay);
mCurrentColorIndex = (mCurrentColorIndex + 1) % COLOR_CHOICES.length;
final int selectedColor = COLOR_CHOICES[mCurrentColorIndex];
mFacePositionPaint = new Paint();
mFacePositionPaint.setColor(selectedColor);
mIdPaint = new Paint();
mIdPaint.setColor(selectedColor);
mIdPaint.setTextSize(ID_TEXT_SIZE);
mBoxPaint = new Paint();
mBoxPaint.setColor(selectedColor);
mBoxPaint.setStyle(Paint.Style.STROKE);
mBoxPaint.setStrokeWidth(BOX_STROKE_WIDTH);
}
void setId(int id)
{
mFaceId = id;
flag = 1;
}
/**
* Updates the face instance from the detection of the most recent frame. Invalidates the
* relevant portions of the overlay to trigger a redraw.
*/
void updateFace(Face face)
{
mFace = face;
postInvalidate();
}
/**
* Draws the face annotations for position on the supplied canvas.
*/
#Override
public void draw(Canvas canvas)
{
face = mFace;
if (face == null)
{
return;
}
// Draws a circle at the position of the detected face, with the face's track id below.
float x = translateX(face.getPosition().x + face.getWidth() / 2);
float y = translateY(face.getPosition().y + face.getHeight() / 2);
// canvas.drawCircle(x, y, FACE_POSITION_RADIUS, mFacePositionPaint);
canvas.drawText("id: " + mFaceId, x + ID_X_OFFSET, y + ID_Y_OFFSET, mIdPaint);
// canvas.drawText("happiness: " + String.format("%.2f", face.getIsSmilingProbability()), x - ID_X_OFFSET, y - ID_Y_OFFSET, mIdPaint);
// canvas.drawText("right eye: " + String.format("%.2f", face.getIsRightEyeOpenProbability()), x + ID_X_OFFSET * 2, y + ID_Y_OFFSET * 2, mIdPaint);
// canvas.drawText("left eye: " + String.format("%.2f", face.getIsLeftEyeOpenProbability()), x - ID_X_OFFSET*2, y - ID_Y_OFFSET*2, mIdPaint);
// Draws a bounding box around the face.
float xOffset = scaleX(face.getWidth() / 2.0f);
float yOffset = scaleY(face.getHeight() / 2.0f);
float left = x - xOffset;
float top = y - yOffset;
float right = x + xOffset;
float bottom = y + yOffset;
canvas.drawRect(left, top, right, bottom, mBoxPaint);
Log.d("MyTag", "hello "+i);
i++;
if (flag == 1)
{
flag = 0;
canvas1=canvas;
// send face image to server for recognition
new MyAsyncTask().execute("ppppp");
}
}
class MyAsyncTask extends AsyncTask<String, Void, String>
{
private Context context;
public MyAsyncTask()
{
// TODO Auto-generated constructor stub
//context = applicationContext;
}
protected String doInBackground(String... params)
{
try
{
Log.d("MyTag", "face.getWidth() "+face.getWidth());
Bitmap temp_bitmap = Bitmap.createBitmap((int)face.getWidth(), (int)face.getHeight(), Bitmap.Config.RGB_565);
canvas1.setBitmap(temp_bitmap);
}
catch (Exception e)
{
Log.e("MyTag", "I got an error", e);
e.printStackTrace();
}
Log.d("MyTag", "doInBackground");
return null;
}
protected void onPostExecute(String result) {
Log.d("MyTag", "onPostExecute " + result);
// tv2.setText(s);
}
}
}
It give me this error:
12-16 03:08:00.310 22926-23044/com.google.android.gms.samples.vision.face.facetracker E/MyTag: I got an error
java.lang.UnsupportedOperationException
at android.view.HardwareCanvas.setBitmap(HardwareCanvas.java:39)
at com.google.android.gms.samples.vision.face.facetracker.FaceGraphic$MyAsyncTask.doInBackground(FaceGraphic.java:175)
at com.google.android.gms.samples.vision.face.facetracker.FaceGraphic$MyAsyncTask.doInBackground(FaceGraphic.java:158)
This code can detect face in real time. For recognition part, I am planning to use 'JavaCV' https://github.com/bytedeco/javacv. If I can capture the face in a bitmap then I can save it in .jpg image then I can recognize it. Could you please give me some advise, how to save detected face. Thank you.
TL;DR: Capture a Frame, process it, then save/export.
From the source
#Override
public void setBitmap(Bitmap bitmap) {
throw new UnsupportedOperationException();
}
This means that the Canvas cannot handle the setBitmap(Bitmap bitmap) method
You have several issues with what you are performing.
First: Loads of AsynkTask(s), and many are usless/redundand
If you are using the com.google.android.gms.vision.* classes, then you are likely receiveing around 30 events per second. When an event occurs, the captured Frame is almost assured to be different from the one evaluated. You are racing against your conditions.
Second: Using Canvas to set Bitmap
Always, when using a Class, check its documentation and ancestors and finally its implementation.
An ImageView would perform as you desire. By receiving a Bitmap, then setting to it. All racing conditions would be handled by the OS< and redundant requests would be dropped by the Main Looper
Finally
If what you need is perhaps "Take a picture, when someone is smiling with eyes closed", then you need to inverse your logic. Use a source to generate Frame(s). Then process the Frame, and if it meets your criteria, save it.
This codelabs project does almost what you want, and it explains its details very well

How to make a rounded square groupicon instead of a circle groupicon

Hello I have a launcher i've been working on and I want to make the folder icon a rounded square like this:.
right now its a circle the shape is made via java code no xml is used
here's the code:
package com.appname.viewutil;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import com.launchername.activity.Home;
import com.launchername.util.Tool;
public class GroupIconDrawable extends Drawable{
private int outlinepad;
Bitmap[] icons;
public float iconSize;
Paint paint;
Paint paint2;
Paint paint4;
private int iconSizeDiv2;
private float padding;
private float scaleFactor = 1;
private boolean needAnimate, needAnimateScale;
private float sx = 1;
private float sy = 1 ;
public GroupIconDrawable(Bitmap[] icons,float size){
init(icons,size);
}
private void init(Bitmap[] icons,float size){
this.icons = icons;
this.iconSize = size;
iconSizeDiv2 = Math.round(iconSize / 2f);
padding = iconSize /25f;
this.paint = new Paint();
paint.setColor(Color.WHITE);
paint.setAlpha(150);
paint.setAntiAlias(true);
this.paint4 = new Paint();
paint4.setColor(Color.WHITE);
paint4.setAntiAlias(true);
paint4.setFlags(Paint.ANTI_ALIAS_FLAG);
paint4.setStyle(Paint.Style.STROKE);
outlinepad = Tool.dp2px(2, Home.launcher);
paint4.setStrokeWidth(outlinepad);
this.paint2 = new Paint();
paint2.setAntiAlias(true);
paint2.setFilterBitmap(true);
}
public void popUp(){
sy = 1;
sx = 1;
needAnimate = true;
needAnimateScale = true;
invalidateSelf();
}
public void popBack(){
needAnimate = false;
needAnimateScale = false;
invalidateSelf();
}
#Override
public void draw(Canvas canvas) {
canvas.save();
if (needAnimateScale){
scaleFactor = Tool.clampFloat(scaleFactor-0.09f,0.5f,1f);
}else {
scaleFactor = Tool.clampFloat(scaleFactor+0.09f,0.5f,1f);
}
canvas.scale(scaleFactor,scaleFactor,iconSize/2,iconSize/2);
Path clipp = new Path();
clipp.addCircle(iconSize / 2,iconSize / 2,iconSize / 2-outlinepad, Path.Direction.CW);
canvas.clipPath(clipp, Region.Op.REPLACE);
canvas.drawCircle(iconSize / 2, iconSize / 2, iconSize / 2-outlinepad,paint);
canvas.drawBitmap(icons[0],null,new RectF(padding,padding, iconSizeDiv2-padding, iconSizeDiv2-padding),paint2);
canvas.drawBitmap(icons[1],null,new RectF(iconSizeDiv2+padding,padding,iconSize-padding, iconSizeDiv2-padding),paint2);
canvas.drawBitmap(icons[2],null,new RectF(padding, iconSizeDiv2+padding, iconSizeDiv2-padding,iconSize-padding),paint2);
canvas.drawBitmap(icons[3],null,new RectF(iconSizeDiv2+padding, iconSizeDiv2+padding,iconSize-padding,iconSize-padding),paint2);
canvas.clipRect(0,0,iconSize,iconSize, Region.Op.REPLACE);
canvas.drawCircle(iconSize / 2, iconSize / 2, iconSize/2-outlinepad,paint4);
canvas.restore();
if (needAnimate){
paint2.setAlpha(Tool.clampInt(paint2.getAlpha()-25,0,255));
invalidateSelf();
}else if (paint2.getAlpha() != 255){
paint2.setAlpha(Tool.clampInt(paint2.getAlpha()+25,0,255));
invalidateSelf();
}
}
#Override
public void setAlpha(int i) {}
#Override
public void setColorFilter(ColorFilter colorFilter) {}
#Override
public int getOpacity() {return PixelFormat.TRANSPARENT;}
}
any ideas on how to make it a rounded square like in the picture?
any help would be awesome!
thanks in advance :)
Replace the calls to addCircle and drawCircle with the appropriate RoundRect functions- addRoundRect and drawRoundRect.

How to draw a new circle every time the screen is touched?

I want the program to draw a circle whenever the screen gets touched and if the screen gets touched on another position I want the program to draw a circle again but without deleting the old one!
Now my problem is that it doesn't just draw a new circle in addition to the old one. It draws a new circle and deletes the old one. I tried to find a solution but nothing worked.
So can anyone please help me?
So it's working now!
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
public class SingleTouchEventView extends View {
private Paint paint = new Paint();
List<Point> points = new ArrayList<Point>();
public SingleTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
paint.setColor(Color.GREEN);
for(Point p: points){
canvas.drawCircle(p.x, p.y, 20, paint);
}
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Point p = new Point();
p.x = (int)event.getX();
p.y = (int)event.getY();
points.add(p);
invalidate();
case MotionEvent.ACTION_MOVE: // a pointer was moved
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
break;
}
}
invalidate();
return true;
}
}
You can achieve it by maintaining a list of points as a private instance variable:
private List<Point> points = new ArrayList<Point>;
Then you can add new points to this list every time a new touch event occurs:
Point p = new Point();
p.x = event.getX();
p.y = event.getY();
points.add(p);
invalidate();
Now in the onDraw() method you can print all the points in the list:
paint.setColor(Color.GREEN);
for(Point point: points){
canvas.drawCircle(point.x, point.y, 20, paint);
}
invalidate();
Why not make a circle object which stores the coordinates of where to paint the circle, then add these objects to an array. Then in your paint method iterate through the array get the coordinates from each object and paint the circle using the coordinates?
So in your onclick method create a new circle object with the coordinates gained from the touch
one of my changing circle classes:
public class GrowCircle {
float x, y;int radius;
Paint myp = new Paint();
int colr,colg,colb;
int redvar=1;
int bluevar=5;
int greenvar=2;
int tripper=10;
int change=2;
Random rand = new Random();
public GrowCircle(float x, float y){
this.x=x;
this.y=y;
this.radius=2;
this.colr=rand.nextInt(254)+1;
this.colg=rand.nextInt(254)+1;
this.colb=rand.nextInt(254)+1;
}
public void update(){
if(tripper<=1||tripper>=15){
change=-change;
}
Random col = new Random();
myp.setColor(Color.argb(255,colr,colg,colb));
colr+=redvar;
colg+=greenvar;
colb+=bluevar;
if(colr<=5||colr>=250){
redvar=-redvar;
}
if(colg<=5||colg>=250){
greenvar=-greenvar;
}
if(colb<=5||colb>=250){
bluevar=-bluevar;
}
}
public void drawThis(Canvas canvas){
myp.setStrokeWidth(tripper);
myp.setStyle(Style.STROKE);
canvas.drawCircle(x, y, radius, myp);
}
}
so play with that and make it how you want and then do this:
///var declaration
CopyOnWriteArrayList<GrowCircle> gcirc= new CopyOnWriteArrayList<GrowCircle>();
//in update method
for(GrowCircle circ:gcirc){
circ.update();
}
// in draw method
for(GrowCircle circ:gcirc){
circ.drawThis(c);
}
//and in onTouch
float tx =event.getX();
float ty = event.getY();
gcirc.add(new GrowCircle(tx,ty));

Categories

Resources