Reputation: 307
I have an activity which has an ImageView
in it. What I want to do is be able to draw where the user touches that Imageview
with an image from the drawable folder. I've read that the best way is to use Canvas, but I'm not sure where and how I integrate the onDraw
method with the onTouchListener
. This is what I have so far:
public class Main extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView)findViewById(R.id.textView);
final ImageView image = (ImageView) findViewById(R.id.imageView2);
//Bitmap
Bitmap viewBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(viewBitmap);
image.draw(canvas);
image.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
textView.setText("Touch coordinates : " + String.valueOf(event.getX()) + "x" + String.valueOf(event.getY()));
return false;
}
});
}
}
So what I want to do is when the user touches the ImageView
, an image will be drawn exactly where he touched it.
Upvotes: 4
Views: 4113
Reputation: 1
I edited your class like this and it works for me
public class MyImageView extends androidx.appcompat.widget.AppCompatImageView {
private Bitmap mMarker;
private Path mPath, circlePath ;
private Paint paint, circlePaint;
private Canvas mCanvas;
//Java constructor
public MyImageView(Context context) {
super(context);
init();
}
//XML constructor
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mTouches = new ArrayList<Point>();
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(12);
mPath = new Path();
Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mMarker = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mMarker);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, paint);
// kill this so we don't double draw
mPath.reset();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
@Override
protected void onDraw(Canvas c) {
//Let the image be drawn first
super.onDraw(c);
c.drawBitmap(mMarker, 0, 0, paint);
c.drawPath( mPath, paint);
c.drawPath( circlePath, circlePaint);
}
}
Upvotes: 0
Reputation: 63303
You're going to want to subclass ImageView
in order to override its onDraw()
method. By doing so, you can also to the custom touch handling in onTouchEvent()
instead of attaching a listener. This is not a complete example, but something like the following:
public class CustomImageView extends ImageView {
private ArrayList<Point) mTouches;
private Bitmap mMarker;
//Java constructor
public CustomImageView(Context context) {
super(context);
init();
}
//XML constructor
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mTouches = new ArrayList<Point>();
mMarker = BitmapFactory.decodeResource(context.getResources(), R.drawable.my_marker_image);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//Capture a reference to each touch for drawing
if(event.getAction() == MotionEvent.ACTION_DOWN) {
mTouches.add( new Point(event.getX(), event.getY()) );
return true;
}
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas c) {
//Let the image be drawn first
super.onDraw(c);
//Draw your custom points here
Paint paint = new Paint();
for(Point p : mTouches) {
c.drawBitmap(mMarker, p.x, p.y, paint);
}
}
}
HTH!
Upvotes: 3