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);
}
Related
I am Working on a android project where i am stuck with removing a view on onTouch method when MotionEvent.ACTION_UP is triggered.
My code is as follows
#Override
public boolean onTouch(View v, MotionEvent event) {
int x = 0;
int y = 0;
View point = null;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
if(touch_circle(x,y)) {
point = new Circle_draw(getApplicationContext(),x,y);
layout.addView(point);
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
and more code related to this are as follows
public class Circle_draw extends View{
int width;
int height;
public Circle_draw(Context context,int width,int height) {
super(context);
this.width = width;
this.height = height;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
canvas.drawCircle(width,height,5,paint);
}
}
how can i remove this view from my activity class?? using Action_UP
and the Whole Code for this activity is as follows:-
public class MainActivity extends Activity implements View.OnTouchListener{
RelativeLayout layout;
int height;
int width;
View control;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setVariables();
layout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
layout.addView(control);
control.setOnTouchListener(this);
}
public void setVariables(){
layout = (RelativeLayout) findViewById(R.id.controllerLayout);
height = getWindowManager().getDefaultDisplay().getHeight();
width = getWindowManager().getDefaultDisplay().getWidth();
control = new ThumbController(getApplicationContext());
}
#Override
public boolean onTouch(View v, MotionEvent event) {
int x = 0;
int y = 0;
View point = null;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
if(touch_circle(x,y)) {
point = new Circle_draw(getApplicationContext(),x,y);
layout.addView(point);
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
public boolean touch_circle(int x,int y){
boolean touch = false;
x=x-width;
y=y-height;
int distance = (int) Math.sqrt(Math.pow(x,2) + Math.pow(y,2));
//Toast.makeText(getApplicationContext(),"distance=" + String.valueOf(distance),Toast.LENGTH_SHORT).show();
if(distance<=120){
touch = true;
}
return touch;
}
public class ThumbController extends View{
public ThumbController(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int radius = 120;
Paint paint = new Paint();
width = width-75;
height = height-150;
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawCircle(width, height, radius, paint);
}
}
public class Circle_draw extends View{
int width;
int height;
public Circle_draw(Context context,int width,int height) {
super(context);
this.width = width;
this.height = height;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
canvas.drawCircle(width,height,5,paint);
}
}
}
I use Canvas to draw bitmap by touch screen but they don't show bitmap on apps.
public class MainActivity extends Activity {
public LinearLayout screenlayout;
public void draw (int x, int y){
Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.dam);
Canvas canvas=new Canvas(b);
canvas.drawBitmap(b, x, y, null);
}
public void onCreate(Bundle saveInstanceState){
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
final LinearLayout screenlayout= (LinearLayout)findViewById(R.id.screenlayout);
screenlayout.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int x = (int) event.getRawX();
int y = (int) event.getRawY();
draw(x,y);
break;
case MotionEvent.ACTION_MOVE:
break;
default:
break;
}
return true;
}
});
}
}
As Ganpat Kaliya answer, I provide another code to solve this problem. Thanks to Ganpat Kaliya.
public class MainActivity extends Activity {
public static float vtx;
public static float vty;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test view = new Test(this);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
addContentView(view, params);
view.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
float a = event.getX();
float b = event.getY();
vtx=a;
vty=b;
v.invalidate();
return true;
}
});
}
}
And:
public class Test extends View {
public Test(Context context) {
super(context);
}
public void draw(Canvas canvas) {
float x=MainActivity.vtx;
float y=MainActivity.vty;
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(6);
canvas.drawLine(10,10,50,50,paint);
paint.setColor(Color.RED);
canvas.drawLine(50, 50, 90, 10, paint);
canvas.drawCircle(50, 50, 3, paint);
canvas.drawCircle(x,y,10,paint);
Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.dam);
canvas.drawBitmap(b, x, y, null);
}
}
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!)
I'm making an app which paints a circle with a Touch event on the screen. The next code works fine:
Class Punto extends view{
Paint paint;
Point point = new Point();
Public Punto(Context contex){
super(context);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
paint.setColor(Color.BLUE);
canvas.drawCircle(point.x,point.y,10,paint);
}
#Override
public boolean onTouchEvent (MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
point.x = event.getX();
point.y = event.getY();
break;
}
return true;
}
class Point{
float x,y;
}
Activity:
public class Pintar extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Punto punto = new Punto(this);
setContentView(punto);
}
However I need that the circle be painted on a picture (in my case is a market's plane) but I don't know how I can do this.
Simply extend an ImageView:
class Punto extends ImageView {
I'm sorry, I assumed that the code you posted compiled...
Try this:
public class TouchImage extends ImageView {
Paint paint = new Paint();
Point point = new Point();
public TouchImage(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.BLUE);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(point.x, point.y, 10, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
point.x = event.getX();
point.y = event.getY();
invalidate();
}
return true;
}
class Point {
float x, y;
}
}
With a layout like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Use your reverse package name, for instance "example.com" is -->
<com.example.TouchImage
android:id="#+id/touchImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/map" />
</LinearLayout>
And an Activity that intercepts the coordinates when the TouchImage is touched:
public class Example extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TouchImage touchImage = (TouchImage) findViewById(R.id.touchImage);
touchImage.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Call the existing onTouchEvent() in TouchImage,
// if it draws a circle fetch the coordinates
if(v.onTouchEvent(event)) {
// Do something with event.getX(), event.getY()
}
return true;
}
});
}
}
I have this class:
My problem:
public class Example extends Activity implements OnClickListener{
DrawView view1;
Canvas canvas = new Canvas();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view1 = new DrawView(this);
setContentView(view1);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
view1.setFirstCoord(x, y);
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
view1.setSecondCoord(x, y);
view1.dispatchDraw(canvas);
break;
}
return true;
}
public class DrawView extends LinearLayout {
private Paint paint = new Paint();
public int x1, x2;
public int y1, y2;
public DrawView(Context c){
super(c);
LayoutInflater inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
addView(inflater.inflate(R.layout.union, null));
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(10);
}
#Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.drawLine(0, 50, 900,2000 , paint);//WORKS
canvas.drawLine((int) x1, (int) y1,(int) x2,(int) y2, paint);//NO WORKS
}
public void setFirstCoord(int e, int f){
x1 = e;
y1 = f;
}
public void setSecondCoord(int e, int f){
x2 = e;
y2 = f;
}
}
}
When the next line is executed I see the "example" line on the screem:
canvas.drawLine(0, 50, 900,2000 , paint);
But when the following line "is executed" is not painted any straight line. Why???
canvas.drawLine((int) x1, (int) y1,(int) x2,(int) y2, paint);
I also tried with:
canvas.drawLine(x1, y1, x2, y2, paint);
But, obviously, the results are the same.
I also tried with executed a onDraw() method but any line is painted because onDraw paint under de "UI" (under the content of the layout .xml file)
I hope found somebody who can help me. I think the solution can very easy but I'm going crazy trying things without finding the solution.
Thanks!!!
The solution:
public class Example extends Activity implements OnClickListener{
DrawView view1;
Canvas canvas = new Canvas();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view1 = new DrawView(this);
setContentView(view1);
view1.setOnClickListener(this);
}
public class DrawView extends LinearLayout {
private Paint paint = new Paint();
public int x1, x2;
public int y1, y2;
public DrawView(Context c){
super(c);
LayoutInflater inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
addView(inflater.inflate(R.layout.union, null));
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(10);
}
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
view1.setFirstCoord(x, y);
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
view1.setSecondCoord(x, y);
view1.onDraw(canvas);
view1.postInvalidate();
break;
}
return true;
}
public void setFirstCoord(int e, int f){
x1 = e;
y1 = f;
}
public void setSecondCoord(int e, int f){
x2 = e;
y2 = f;
}
public void onDraw(Canvas canvas){
canvas.drawLine((int) x1, (int) y1,(int) x2,(int) y2, paint);
}
}
}
THANKS AGAIN for your help and your attention. It's a pleasure!!!
Instead of putting your drawing code in dispatch draw, try putting it in onDraw.
Then modify your onTouch method to look like this:
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
view1.setFirstCoord(x, y);
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
view1.setSecondCoord(x, y);
view1.postInvalidate();
break;
}
return true;
}
If you want to use the OnClickListener interface for this, you need to set your activity as an OnClickListener for the view:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view1 = new DrawView(this);
setContentView(view1);
// Add this:
view1.setOnClickListener(this);
}
Otherwise, onTouchEvent will never be called.
Also, onTouchEvent should be named onClick.
move OnTouchEvent to the DrawView, not the activity
Make DrawView extend View, not LinearLayout
Instead of dispatchDraw, implement method onDraw and in onTouchEvent, call invalidate()
I think your problem might be that the x/y coordinates you retrieve in the activity are in the screen space, while your draw coordinates on the canvas are in the canvas space.
So (0,0) in your activity is not the same location as (0,0) of your canvas.
You should probably receive the touchevent inside the view instead of in the activity, then the coordinate system will be the same for both the touchevent and the canvas draw.