I need to draw a point on ImageView Android.
I use custom subclass of View class and override onDraw method like:
public class DrawPoints extends View {
private float x;
private float y;
private Paint mPaint;
public DrawPoints(Context context, float x, float y) {
super(context);
this.x = x;
this.y = y;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("TAG", "onDraw: " + x + "" + y);
mPaint = new Paint();
mPaint.setColor(Color.YELLOW);
canvas.drawCircle(x,y,200,mPaint);
}
}
In my MainActivity I use onTouch event to draw, also do not forget to invalidate(), but it does not draw a point.
public class MainActivity extends AppCompatActivity {
private ImageView mImageView;
private Canvas mCanvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCanvas = new Canvas();
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.image_main);
mImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
float y = motionEvent.getY();
float x = motionEvent.getX();
new DrawPoints(MainActivity.this,x,y).draw(mCanvas);
mImageView.invalidate();
return false;
}
});
}
}
What could it be? I have already read many examples with onDraw on stackoverflow but none help.
You could just create an imageview that draw circle on touch events.
Example:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import java.util.ArrayList;
public class DrawPoints extends android.support.v7.widget.AppCompatImageView {
private static final String TAG = DrawPoints.class.getSimpleName();
private ArrayList<Point> mSavedPoints = new ArrayList<>();
private Point mLastTouchPoint;
private Paint mPaint;
public DrawPoints(Context context) {
super(context);
init();
}
public DrawPoints(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawPoints(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.YELLOW);
}
#Override public boolean dispatchTouchEvent(MotionEvent event) {
mLastTouchPoint = new Point((int) event.getX(), (int) event.getY());
postInvalidate();
return super.dispatchTouchEvent(event);
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mLastTouchPoint != null) {
if (mLastTouchPoint.x > 0 || mLastTouchPoint.y > 0) {
mSavedPoints.add(mLastTouchPoint);
Log.i(TAG, mLastTouchPoint.toString());
}
}
for (Point point : mSavedPoints) {
canvas.drawCircle(point.x, point.y, 200, mPaint);
}
Log.i(TAG, mSavedPoints.toString());
}
}
Related
I am brand new to android and i was wondering if it was possible to add toast onFinishInflate. If this is a stupid question please excuse me.I have created a view like this.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import android.widget.Toast;
public class CustomView extends View {
private Rect rectangle;
private Paint paint;
public CustomView(Context context) {
super(context);
int x = 50;
int y = 50;
int sideLength = 200;
// create a rectangle that we'll draw later
rectangle = new Rect(x, y, sideLength, sideLength);
// create the Paint and set its color
paint = new Paint();
paint.setColor(Color.GRAY);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
canvas.drawRect(rectangle, paint);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
Toast.makeText(getApplicationContext(),"onfinishinflate",Toast.LENGTH_SHORT).show();
}
}
Update
View has it's own method called getContext(), so you can use like this
Toast.makeText(getContext(), "onfinishinflate", Toast.LENGTH_SHORT).show();
Reference
private Context context;
public CustomView(Context context) {
super(context);
this.context = context;
// Rest of ur codes
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
Toast.makeText(context, "onfinishinflate", Toast.LENGTH_SHORT).show();
}
set the context in your class using constructor, and use it for Toast purpose
I created a SurfaceView (you can see it in the following) and started in from my Main Activity. I overwrote the onTouchEvent method in the SurfaceView and the problem is that the data I want to have logged with Log.d isn't logged, I don't get any Message...
Does anyone have an idea how I can fix this?
My SurfaceView:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback {
private float top;
private float left;
private float bottom;
private float right;
private MainThread thread;
MainGamePanel(Context context) {
super(context);
getHolder().addCallback(this);
thread = new MainThread(getHolder(), this);
setFocusable(true);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
setWillNotDraw(false);
thread.setRunningMode(MainThread.RUNNING);
thread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (Exception e) {
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
right = x + 30;
left = x - 30;
top = y - 30;
bottom = y + 30;
Log.d("tag", x + " " + y);
return true;
}
#Override
protected void onDraw(Canvas canvas) {
}
}
My Main Activity:
import android.app.Activity;
import android.os.Bundle;
import android.os.PersistableBundle;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
setContentView(new MainGamePanel(getApplicationContext()));
}
}
Try changing "getApplicationContext()" to "this" in following part of code:
setContentView(new MainGamePanel(getApplicationContext()));
to
setContentView(new MainGamePanel(this));
I have the following code:
package com.teste;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class ball extends View implements View.OnTouchListener {
Bitmap littleBall;
float x, y;
private int mWidth, mHeight;
private GestureDetector mDetector;
public ball(Context context) {
super(context);
}
public ball(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mDetector = new GestureDetector(this.getContext(), new BallListener());
}
#Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
mWidth = View.MeasureSpec.getSize(widthMeasureSpec);
mHeight = View.MeasureSpec.getSize(heightMeasureSpec);
x = mWidth/2;
y = mHeight/2;
setMeasuredDimension(mWidth, mHeight);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
littleBall = BitmapFactory.decodeResource(getResources(), R.drawable.verde);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(littleBall, 200, 200, false);
canvas.drawBitmap(resizedBitmap, (x - (resizedBitmap.getWidth() / 2)), (y - resizedBitmap.getHeight()/2), null);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(getContext(), "teste", Toast.LENGTH_LONG);
return mDetector.onTouchEvent(event);
}
class BallListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_UP) {
x = e.getX();
y = e.getY();
invalidate();
}
return super.onSingleTapUp(e);
}
}
}
In a near future i want make the ball moves to a place when i swipe my finger across the screen. But for the start, my goal is make the LittleBall (created using canvas and bitmap) change its position when i touch at the screen. I am using onTouch and a gestureListener. Searching on the net, i found others ways to get a touch like onTouchListener and even looking and Android Developer Help i did not understand what is the difference between those methods...
Can Someone explain in a easy way when i should use those methods and what im doing wrong to not even show my text?
I have a custom SurfaceView with a method doDraw() that draws a background and a bitmap. The problem is when I run this I get an error
Caused by: java.lang.IllegalArgumentException: canvas object must be the same instance that was previously returned by lockCanvas
I don't see why this is happening. I don't declare any other canvases anywhere else in my code. I only have two other classes, MainActivity and SurfaceViewExample. MainActivity just has an intent to open SurfaceViewExample, and SurfaceViewExample just has a method called by some buttons.
OurView class:
package com.thatoneprogrammerkid.gameminimum;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class OurView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Bitmap testimg;
public int xCoord = 500;
public int yCoord = 500;
public OurView(Context context) {
super(context);
init();
}
public OurView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public OurView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
holder = getHolder();
holder.addCallback(this);
testimg = BitmapFactory.decodeResource(getResources(),R.drawable.testimg);
}
void moveImage(int xChange, int yChange) {
xCoord += xChange;
yCoord += yChange;
doDraw();
}
void doDraw() {
Canvas myCanvas = holder.lockCanvas();
if (myCanvas != null) {
myCanvas.drawARGB(255, 55, 255, 255);
myCanvas.drawBitmap(testimg, xCoord, yCoord, null);
}
holder.unlockCanvasAndPost(myCanvas);
}
#Override
public void surfaceCreated(final SurfaceHolder holder) {
doDraw();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {}
}
Move the unlockCanvasAndPost() inside the if (myCanvas != null) { statement. My guess is lockCanvas() is returning null, and you're attempting to unlock a null reference.
Looking at the source code, the test for "is it the same" comes before the test for "is it locked at all" -- and mCanvas is initialized to a non-null value.
I know there are already answers for this error message but none of those solutions helped my problem. I'm trying to do a Sierpinski Triangle and I have a MySurfaceView class that extends GLSurfaceView and a MyRenderer class that extends Activity and implements Renderer. Here are the classes:
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
public class MySurfaceView extends GLSurfaceView {
private MyRenderer renderer;
private float prevX;
private float prevY;
private float ROTATION_FACTOR = 1.0f;
public MySurfaceView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MySurfaceView(Context context, MyRenderer renderer) {
super(context);
this.renderer = renderer;
this.setRenderer(renderer);
this.setRenderMode(RENDERMODE_WHEN_DIRTY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
float dx = x-prevX;
float dy = y-prevY;
prevX = x;
prevY = y;
float distance = (float) Math.sqrt((double) (dx*dx+dy*dy));
float angle = distance*ROTATION_FACTOR;
if(dy>0){
renderer.increaseRotationAngle(angle);
}else{
renderer.increaseRotationAngle(-angle);
}
this.requestRender();
}
return true;
}
}
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.opengl.GLSurfaceView.Renderer;
public class MyRenderer extends Activity implements Renderer {
private Triangle mTriangle;
private float rotationAngle = 0;
private int level;
private int mFill;
public MyRenderer(int level, int mFill)
{
this.level = level;
this.mFill = mFill;
mTriangle = new Triangle(5, "WireFrame");
}
#Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glRotatef(rotationAngle, 0, 0, 1);
mTriangle.onDrawFrame(gl);
// TODO Auto-generated method stub
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
int delta;
if(width<height){
delta=(height-width)/2;
gl.glViewport(0, delta, width, width);
}else{
delta=(width-height)/2;
gl.glViewport(delta, 0, height, height);
}
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, -0.1f, 0.1f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
// TODO Auto-generated method stub
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.8f, 0.8f, 0.8f, 1);
// TODO Auto-generated method stub
}
public void increaseRotationAngle(float delta)
{
rotationAngle+=delta;
System.out.println("Rotating by "+rotationAngle);
}
}
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
private MySurfaceView view;
private MyRenderer renderer;
private String levelCount;
public String skew;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
renderer = new MyRenderer(3, 1);
view = new MySurfaceView(this, renderer);
view.setRenderer(renderer);
setContentView(view);
}
#Override
public void onPause()
{
view.onPause();
super.onPause();
}
#Override
public void onResume()
{
view.onResume();
super.onResume();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
In the following line of Activity's onCreate()
view = new MySurfaceView(this, renderer);
you create an instance of MySurfaceView class. Its constructor (MySurfaceView(Context context, MyRenderer renderer)) sets a renderer in the line
this.setRenderer(renderer);
So, when you're trying to set the renderer right in the next line of your Activity's onCreate()
view.setRenderer(renderer);
you get the error.
The line is redundant.