I am new to programing. I am trying to move a circle by using the OnTouchListener, but I don't know how to call it within the onTouch event as I have a Class for Circle with x and y and a class called Drawing (d) which draws it on the canvas. I have highlighted bellow the lines which I find problematic. Thank you.
``
public class FirstPicture extends Activity implements OnTouchListener {
Drawing d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
d=new Drawing(this);
setContentView(d);
d.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
**d.c1.getX() = event.getX();
d.c1.getY()= event.getY();**
d.invalidate();
return true;
}
}
public class Drawing extends View{
Context ctx;
Circle c1;
public Drawing(Context context) {
super(context);
this.ctx = context;
c1 = new Circle (165, 350, 33);
}
protected void onDraw (android.graphics.Canvas canvas){
Paint p = new Paint();
Paint p1 = new Paint ();
Paint p2 = new Paint ();
Paint p3= new Paint();
Paint p4 = new Paint();
p2.setColor(Color.WHITE);
p.setColor(Color.GREEN);
p3.setColor(Color.RED);
p1.setColor(Color.BLACK);
p4.setColor(Color.BLUE);
p1.setStyle(Style.FILL);
p1.setStyle(Style.FILL_AND_STROKE);
p1.setTextSize(19);
canvas.drawCircle(c1.getX(), c1.getY(), c1.getR(), p4);
canvas.drawText("100", c1.getX()-15, c1.getY()+5, p1);
}
}
public class Circle {
private float x;
private float y;
private float r;
public Circle(float x, float y, float r) {
super();
this.x = x;
this.y = y;
this.r = r;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getR() {
return r;
}
public void setR(float r) {
this.r = r;
}
}
You're trying to assign to a getter:
d.c1.getX() = event.getX()
How about exposing an update method on your Drawing view.
private int circleCenterX;
private int circleCenterY;
public void update(int x, int y) {
this.circleCenterX = x;
this.circleCenterY = y;
}
#Override
protected void draw(Canvas canvas) {
canvas.drawCircle(circleCenterX, circleCenterY, c1.getR(), p4);
canvas.drawText("100", c1.getX() - 15, c1.getY() + 5, p1);
}
Then your onTouch becomes:
#Override
public boolean onTouch(View v, MotionEvent event) {
d.update(event.getX(), event.getY());
return true;
}
Instantiate all your Paint objects outside of the draw method - perhaps in your constructor where you instantiate the circle. Instantiating objects is a relatively heavy operation and you don't want to do it while draw() is happening, especially as it happens 60x a second.
I'm semi-sure the draw() method on the view will automatically be called so there's no need to invalidate the view (but even if you do, it won't redraw the view until the next frame anyway - take this bullet point and this bit inside parentheses with a pinch of salt!)
Related
I draw particles and move it successfully but when i draw a line between particles, it does not work correctly. I set the min distance is 20, so if the distance between 2 particles is smaller than 20 ,then drawing a line. But it still draws a line eventhough the distance is higher than 20. Here is the example problem picture. example problem
I found that the line is redrawed fastly, sometime it causes flashing redrawing line. Anyone have any ideas how to make smoother animation ?
Here is the code:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private canvasview canvasView;
final private int InitParticle=10;
final private ArrayList<particle> arrayList=new ArrayList<particle>(InitParticle);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
canvasView=new canvasview(this) ;
setContentView(canvasView);
// Create particles object and pass to the arrayList
InitArray();
// Passing particle arrayList to canvas
canvasView.passingArrFromMain(arrayList);
}
public void InitArray()
{
for(int i=0;i<InitParticle;i++)
{
particle Particle=new particle();
Particle.initialize(canvasView.get_WidthScreen(),canvasView.get_HeightScreen());
arrayList.add(Particle);
}
}
}
particle.java
public class particle {
private int x,y;
final private Random random=new Random();
private int xdirection,ydirection,randomdirection;
public particle()
{
this.x=0;
this.y=0;
this.xdirection=3;
this.ydirection=3;
this.randomdirection=random.nextInt(99); // random number for chosing direction
}
// Get position of particle
public int getx()
{
return x;
}
public int gety()
{
return y;
}
// Random position of particle
public void initialize(int a,int b)
{
this.x= random.nextInt(a);
this.y= random.nextInt(b);
}
public int getXdirection()
{
return xdirection;
}
public int getYdirection()
{
return ydirection;
}
public void setXdirection()
{
this.xdirection=-this.xdirection;
}
public void setYdirection()
{
this.ydirection=-this.ydirection;
}
public void move(int x,int y) {
if (this.randomdirection >= 0 && this.randomdirection < 25) {
this.x = this.x + x;
this.y = this.y + y;
} else if (this.randomdirection >= 25 && this.randomdirection < 50) {
this.x = this.x - x;
this.y = this.y + y;
} else if (this.randomdirection >= 50 && this.randomdirection < 75) {
this.x = this.x - x;
this.y = this.y - y;
} else if (this.randomdirection >= 75 && this.randomdirection < 100) {
this.x = this.x + x;
this.y = this.y - y;
}
}
}
canvasview.java
public class canvasview extends View {
final private int mindistance=20;
final private Paint paint;
final private int H=getContext().getResources().getDisplayMetrics().heightPixels;
final private int W=getContext().getResources().getDisplayMetrics().widthPixels;
private ArrayList<particle> arrayParticles;
final private Paint linepaint=new Paint(Paint.ANTI_ALIAS_FLAG);
public canvasview(Context context)
{
super(context);
// Set canvas background
setBackgroundColor(Color.parseColor("#898984"));
setLayoutParams(new RelativeLayout.LayoutParams(W,H));
// Set paint for drawing circle
paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(Color.parseColor("#E7E7E5"));
// Set paint for drawing line
linepaint.setStrokeWidth(5);
linepaint.setColor(Color.parseColor("#6B6C65"));
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
// Drawing Particles
for(int i=0;i<arrayParticles.size();i++) {
canvas.drawCircle(arrayParticles.get(i).getx(), arrayParticles.get(i).gety(), 20, paint);
}
// Drawing line between particles
for(int i=0;i<arrayParticles.size();i++) {
for(int j=i+1;j<arrayParticles.size();j++) {
int a=arrayParticles.get(i).getx()-arrayParticles.get(j).getx();
int b=arrayParticles.get(i).gety()-arrayParticles.get(j).gety();
if(Math.sqrt(a^2+b^2)<mindistance) {
canvas.drawLine(arrayParticles.get(i).getx(), arrayParticles.get(i).gety(), arrayParticles.get(j).getx(), arrayParticles.get(j).gety(), linepaint);
}
}
}
// Moving particles
update();
}
// Get Width and Height of Screen for random position of particle
public int get_WidthScreen()
{
return W;
}
public int get_HeightScreen()
{
return H;
}
// Get a copy of particle arrayList form MainActivity
public void passingArrFromMain(ArrayList<particle> arrayList)
{
this.arrayParticles=arrayList;
}
// Updating the new position of particles
public void update()
{
for (int i=0;i<arrayParticles.size();i++)
{
// Check edge of the screen
if(arrayParticles.get(i).getx()>get_WidthScreen())
arrayParticles.get(i).setXdirection();
if (arrayParticles.get(i).gety()>get_HeightScreen())
arrayParticles.get(i).setYdirection();
if (arrayParticles.get(i).getx()<0)
arrayParticles.get(i).setXdirection();
if (arrayParticles.get(i).gety()<0)
arrayParticles.get(i).setYdirection();
arrayParticles.get(i).move(arrayParticles.get(i).getXdirection(),arrayParticles.get(i).getYdirection());
// Redraw the canvas
invalidate();
}
}
}
I started lately developing for android and got stuck trying to add multiple Views to a Layout. It actually works for the first touch, but after that it does nothing. The Log though keeps working and showing that the touch has been detected and shows the position of the event. I have the following code
public class MainActivity extends Activity {
private LinearLayout mLayout;
private Context con = this;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayout = (LinearLayout) findViewById(R.id.lLayout);
mLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mLayout.addView(createNewView(event.getX(), event.getY()));
Log.d("this ","View has been add." + event.getX()+ ", " + event.getY());
break;
}
return false;
}
});
}
private markerView createNewView(float x, float y) {
final LayoutParams lparams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
final markerView mView = new markerView(con, 150, x, y);
mView.setLayoutParams(lparams);
return mView;
}}
and
public class markerView extends View implements View.OnTouchListener{
private Paint paint = new Paint();
private int diameter;
private float X,Y;
public markerView(Context context, int dia, float dx, float dy) {
super(context);
diameter = dia;
X = dx; Y = dy;
paint.setColor(Color.GREEN);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth((float) 4.0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.drawCircle(X, Y, diameter, paint);
canvas.restore();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}}
Try remove final tag on your final markerView mView = new markerView(con, 150, x, y);
i just found that the Views ave been created but never show up because the first one has the size of the parentLayout. so i just add the following methode and it worked. the position needs to be changed because of the RelativeLayout but thats not a problem ;)
here is the code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(2*diameter, 2*diameter);
}
I'm working on a project that requires me to draw a circle at a random location on the screen when the user touches the screen. When the touch event occurs it also needs to remove the last circle I drew, so that there can only be one circle on the screen at one time.
I have a class Circle, that I use to create a circle:
public class Circle extends View {
private final float x;
private final float y;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public Circle(Context context, float x, float y, int r) {
super(context);
mPaint.setColor(0x000000);
this.x = x;
this.y = y;
this.r = r;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
canvas.drawCircle(x, y, r, mPaint);
}
}
This is the activity from which a new Circle is created. It will also monitor touch events. Right now it is drawing a circle in the upper left hand corner of the screen, but that code will need to be moved into the onTouch method. I will likely calculate the random number using Random.
public class FingerTappingActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_finger_tapping);
LinearLayout circle = (LinearLayout) findViewById(R.id.lt);
View circleView = new Circle(this, 300, 300, 150);
circleView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
circle.addView(circleView);
circle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
}
}
I have never worked with touch events before such as these and have no idea how to go about this. Some tips would be greatly appreciated.
Do some thing like this ,
public class DrawCircles extends View {
private float x = 100;
private float y = 100;
private int r = 50;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
canvas.drawCircle(x, y, r, mPaint);
}
public DrawCircles(Context context) {
super(context);
init();
}
public DrawCircles(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawCircles(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
void init() {
mPaint.setColor(0x000000);
// logic for random call here;
}
Random random = new Random();
void generateRandom() {
int minRadius = 100;
int w = getWidth();
int h = getHeight();
this.x = random.nextInt(w);
this.y = random.nextInt(h);
this.r = minRadius + random.nextInt(100);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
generateRandom();
invalidate();
return super.onTouchEvent(event);
}
}
This view will draw random circles inside the view . make some adjustments for generating x & y coordinates . add this view to xml then it will work.
I am in need of a good resource like a tutorial or sample code that would draw an expanding circle of different thickness. To be exact, a small full circle that would expand and shrink over time like a few seconds.
Thanks for the help.
I am relatively new on this and so I would like to ask for help on this.
Thanks.
This class will help:
public class BallView extends View {
public float x;
public float y;
private final int r;
public int color;
public void setColor(int color) {
mPaint.setColor(color);
}
#Override
public float getX() {
return x;
}
#Override
public void setX(float x) {
this.x = x;
}
#Override
public float getY() {
return y;
}
#Override
public void setY(float y) {
this.y = y;
}
public int getR() {
return r;
}
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//construct new ball object
public BallView(Context context, float x, float y, int r) {
super(context);
//color hex is [transparncy][red][green][blue]
mPaint.setColor(0xFF15FFD4); //not transparent. color is white
this.x = x;
this.y = y;
this.r = r; //radius
}
//qcalled by invalidate()
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r, mPaint);
}
}
You can use it to draw a ball in your main activity using mainView.addView(mBallView) to add it to the view and BallView.invalidate to actually draw it and according to whatever mechanisms you want to achieve you can use the setter method to set the radius of the circle as time increases or whatever you'd like. Make sure to use a Timer that calls RedrawHandler.post() within it and redraws the view within there with the updated radius values.
I have two doubts in canvas android.
They are explained below:
Firstly, I had drawn a row of circles on canvas, i want to capture the x and y coordinates of the circle(only on one circle)drawn so that I can draw a bitmap over the circle(in center).
Secondly, I want to imply touch event on circle i.e I want them to change color when some one touch them Can anybody help me with this?
for #2:
calculate the distance between the center of your point and the touch event - if the distance is smaller than the radius of your circle - you pressed on the circle
First you should create GridSector class for your "circle zone".
public class GridSector {
private int x = 0;
private int y = 0;
private Rect rect = new Rect(0, 0, 0, 0);
public GridSector(int x, int y, Rect rect) {
this.x = x;
this.y = y;
this.rect = rect;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Rect getRect() {
return rect;
}
public void setRect(Rect rect) {
this.rect.set(rect.left, rect.top, rect.right, rect.bottom);
}
}
Then Create view what you wanna touch.
public class GridSectorsView extends View {
GridSector currentSelectedSector;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawCircle(canvas); // draw your circles;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
invalidate(currentSelectedSector.getRect()); // update your circles (call onDraw Function ) ;
}
}
}