I am developing an app where the user can mark a damage icon on a car. The car here is basically an image and the damage icon is also an image. I am able to draw an image, where the user touches the car, using this code:
public class TestActivity extends Activity {
private Button btn_save, btn_resume;
private ImageView iv_canvas;
private Bitmap baseBitmap;
private Canvas canvas;
private Paint paint;
public Bitmap bt;
public Bitmap ct;
boolean ismove = false;
private static final int SWIPE_MIN_DISTANCE = 50;
int i = 0;
private float x = 0;
public HashMap<String, String> testholdmap = new HashMap<String, String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// The initialization of a brush, brush width is 5, color is red
paint = new Paint();
paint.setStrokeWidth(5);
paint.setColor(Color.RED);
iv_canvas = (ImageView) findViewById(R.id.iv_canvas);
iv_canvas.setOnTouchListener(touch);
bt = BitmapFactory.decodeResource(getResources(),
R.drawable.damage_mark_r_ic);
}
private View.OnTouchListener touch = new OnTouchListener() {
// Coordinate definition finger touch
float startX;
float startY;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
// Press the user action
case MotionEvent.ACTION_DOWN:
// The first drawing initializes the memory image, specify the
// background is white
if (baseBitmap == null) {
baseBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.b_ferrari_f152_000_0000).copy(
Bitmap.Config.ARGB_8888, true);
canvas = new Canvas(baseBitmap);
}
// Recording began to touch point coordinate
startX = event.getX();
startY = event.getY();
break;
// The user's finger on the screen of mobile action
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
float stopX = event.getX();
float stopY = event.getY();
if (startX == stopX) {
canvas.drawBitmap(bt, startX, startY, paint);
// The pictures to the ImageView
iv_canvas.setImageBitmap(baseBitmap);
} else if (startX - stopX > 50 || stopX - startX > 50) {
baseBitmap = null;
}
break;
default:
break;
}
return true;
}
};
}
My problem is figuring out how to remove this icon if it already drawn. I want it to function this way: I draw a damage icon on x,y position, and if the user clicks on x,y position again, then this damage icon will be removed.
How can I achieve this?
Use this:
canvas.drawColor(0, Mode.CLEAR);
or
overlayBitmap.eraseColor(Color.TRANSPARENT);
This sets an existing Bitmap to all transparent.
My solution would be like follows :
Every time the user click on image - store the damge bounds (x,y,w,h) in list
and Draw it on the canvas
If user click again at the same damage image - remove it from list and redraw(clean canvas - Canvas.drawColor(Color.WHITE)) everything again : the car and remaining images in the list
Related
I have an Activity that load an image from a URL using Picasso Library.
This image is larger than the screen, which is why in the method "onTouch" implement a code to scroll the image by simulating a map.
The problem I have is that I draw circles on that image, every time I click on screen I should paint a circle and erase the previous.
Using this line canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY); turns my whole bitmap black.
I need paint a Circle over the image when I click on screen and Delete Previous
Here's a fragment of Code of my Activity
To load image into imageView and create a bitmap to draw a canvas on a copy bitmap
Picasso.with(getApplicationContext()).load(url).into(imageView, new Callback() {
#Override
public void onSuccess() {
imageView.setVisibility(View.VISIBLE);
lineABmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
lineAMutBmp = lineABmp.copy(Bitmap.Config.RGB_565, true);
copy = Bitmap.createBitmap(lineAMutBmp);
canvas = new Canvas(copy);
imageView.setImageBitmap(copy);
}
});
To paint circle
private void drawBeacon() {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
canvas.drawCircle(startX, startY, circle_radius, circle);
canvas.drawRect(startX - 50,//left
startY - 30, // top
startX + 50, //right
startY - 10, rect); //bottom
canvas.drawText(" Minor: " + beacon.getMinor(),
startX - 45,
startY - 15, text);
imageView.invalidate();
}
init Paint
init(){
circle = new Paint();
circle.setColor(Color.rgb(46, 204, 113));
circle.setStyle(Paint.Style.FILL);
circle.setStrokeWidth(10);
circle_radius = 10;
text = new Paint();
text.setColor(Color.BLACK);
text.setTextSize(16);
text.setFakeBoldText(true);
rect = new Paint();
rect.setColor(ContextCompat.getColor(getApplicationContext(), R.color.white_80));
rect.setStyle(Paint.Style.FILL_AND_STROKE); }
OnTouch, in this method I make zoom and drag image and call method to draw the Circles
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
float[] m = new float[9];
matrix.getValues(m);
float transX = m[Matrix.MTRANS_X] * -1;
float transY = m[Matrix.MTRANS_Y] * -1;
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: //first finger down only
savedMatrix.set(matrix);
if (draw) {
startX = Math.abs((event.getX() + transX) / scale);
startY = Math.abs((event.getY() + transY) / scale);
drawBeacon();
} else {
...
}
break;
case MotionEvent.ACTION_UP: //first finger lifted
case MotionEvent.ACTION_POINTER_UP: //second finger lifted
...
break;
case MotionEvent.ACTION_POINTER_DOWN: //second finger down
....
break;
case MotionEvent.ACTION_MOVE:
....
break;
}
} //perform the transformation.
view.setImageMatrix(matrix);
return true; // indicate event was handled
}
Finally do it myself. I create a copy of bitmap inside my method
private void drawBeacon() {
Bitmap tmpBitmap = Bitmap.createBitmap(copyOriginal);
Canvas canvas = new Canvas(tmpBitmap);
....
bitmapLayers.add(1, tmpBitmap);
bt_delete.setVisibility(View.VISIBLE);
imageView.setImageBitmap(tmpBitmap);
draw = false;
}
I have an interesting situation if someone can see what i'm doing wrong? I have a class called TrackView below. It essentially opens up a hole where you touch the screen to reveal a hidden background only at that touch point. This all works great when I call it from setContentView(new TrackView(this)). Graphics are fast and fluid. If I use the exact same TrackView class in the manner below which is started from a service(why i'm using WindowManager), graphics are drawn very poorly and slow. The structure of the view hierarchy in each case is identical. I've also tried SurfaceView and the problem did not go away.
public class OverlayTesting
{
private WindowManager wm;
private LayoutInflater li;
private RelativeLayout rl;
private View v;
private TrackView tv;
public OverlayTesting(Context context)
{
wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
li = LayoutInflater.from(context);
v = li.inflate(R.layout.activity_overlay, null);
rl = (RelativeLayout) v.findViewById(R.id.relativeLayout);
tv = new TrackView(context);
rl.addView(tv);
}
public void show()
{
wm.addView(rl, new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
}
private class TrackView extends View
{
Bitmap bitmapBase;
Bitmap bitmapDefault;
Bitmap bitmapUsed;
Canvas canvasBase;
Canvas canvasDefault;
Canvas canvasUsed;
Paint paint1;
Paint paint2;
int displayHeight;
int displayWidth;
int X = -100;
int Y = -100;
public TrackView(Context context)
{
super(context);
Display display = wm.getDefaultDisplay();
Point point = new Point();
display.getSize(point);
displayWidth = point.x;
displayHeight = point.y;
// create base background
bitmapBase = Bitmap.createBitmap(displayWidth, displayHeight, Bitmap.Config.ARGB_8888);
canvasBase = new Canvas(bitmapBase);
canvasBase.drawColor(Color.WHITE);
// create overlays and masks
bitmapDefault = Bitmap.createBitmap(displayWidth, displayHeight, Bitmap.Config.ARGB_8888);
canvasDefault = new Canvas(bitmapDefault);
canvasDefault.drawColor(Color.BLACK);
bitmapUsed = Bitmap.createBitmap(displayWidth, displayHeight, Bitmap.Config.ARGB_8888);
canvasUsed = new Canvas(bitmapUsed);
// paint structures here
}
#Override
public boolean onTouchEvent(MotionEvent ev)
{
switch (ev.getAction())
{
case MotionEvent.ACTION_DOWN:
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
// refresh overlay with default bitmap and open new hole at XY
// refresh overlay code here
// refresh core view canvas showing only area at XY
// draw canvas code here
}
}
}
I'm making an application which can crop the image of the person. The layout of my application will give a better description
Here the rectangle will be used to capture the image defined by its length and width. The rectangle is movable. How would I go about re-sizing the rectangle. For eg. in WhatsApp when you touch the region inside the rectangle, the rectangle moves. If you touch the edges of rectangle, it provides the ability to re-size image suitable for cropping. So, I have 2 questions. 1) How to receive Touch events on edges of rectangle and 2) How would I re-size my rectangle. I'm using canvas to draw my rectangle. The code for this is as follows:
public class CustomView extends Views
{
public CustomView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);;
paint.setColor(Color.BLUE);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(0, 0, 300, 300, paint);
}
}
You should implement the OnTouchListener and check in MotionEvent.ACTION_DOWN if you touch the rectangle and modify right, left, bottom and top of rectangle in MotionEvent.ACTION_MOVE
I provided a not tested example:
public class CustomView extends View {
private float left=0,right = 300, top = 0, bottom = 300;
public CustomView(Context context)
{
super(context);
setOnTouchListener( new OnTouchListener() {
float oldX, oldY;
#Override
public boolean onTouch(View v, MotionEvent event) {
boolean touch = false;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
touch = isTouchBorderRect();
break;
case MotionEvent.ACTION_UP:
touch = false;
case MotionEvent.ACTION_MOVE:
if (touch){
float newX = event.getRawX();
float newY = event.getRawY();
float deltaX = newX-oldX;
float deltaY = newY-oldY;
left-=deltaX;
right +=deltaX;
bottom += deltaY;
top -= deltaY;
}
break;
}
return false;
}
});
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);;
paint.setColor(Color.BLUE);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(left, top, right, bottom, paint);
}
}
In isTouchBorderRect() method you should check if you have touched the rectangle.
This code is not tested but show the idea that you want to develop.
In my app Draw paint in free hand on Map view but searching lot of information finally got from rectangle shape draw on mapview but i want in place of rectangle draw free hand like zigzag how to change my code Any help please..
MapOverlay.java
public class MapOverlay extends Overlay {
private float x1,y1,x2,y2;
private GeoPoint p1=null,p2=null;
private MapExampleActivity mv = null;
private Paint paint = new Paint();
private Path path = new Path();
private boolean isUp = false;
//constructor receiving the initial point
public MapOverlay(MapExampleActivity mapV,float x,float y){
paint.setStrokeWidth(2.0f);
x1 = x;
y1 = y;
mv = mapV;
p1 = mapV.getMapView().getProjection().fromPixels((int)x1,(int)y1);
}
//override draw method to add our custom drawings
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
if(p1 != null && p2 != null){
//get the 2 geopoints defining the area and transform them to pixels
//this way if we move or zoom the map rectangle will follow accordingly
Point screenPts1 = new Point();
mapView.getProjection().toPixels(p1, screenPts1);
Point screenPts2 = new Point();
mapView.getProjection().toPixels(p2, screenPts2);
//draw inner rectangle
paint.setColor(Color.BLUE);
// paint.setStyle(Style.FILL);
canvas.drawPath(path, paint);
canvas.drawRect(screenPts1.x, screenPts1.y, screenPts2.x, screenPts2.y, paint);
//draw outline rectangle
// paint.setColor(Color.YELLOW);
paint.setStyle(Style.STROKE);
// canvas.drawRect(screenPts1.x, screenPts1.y, screenPts2.x, screenPts2.y, paint);
canvas.drawPath(path, paint);
}
return true;
}
#Override
public boolean onTouchEvent(MotionEvent e, MapView mapView) {
if(mv.isEditMode() && !isUp){
if(e.getAction() == MotionEvent.ACTION_DOWN){
x1 = y1 = 0;
x1 = e.getX();
y1 = e.getY();
p1 = mapView.getProjection().fromPixels((int)x1,(int)y1);
}
//here we constantly change geopoint p2 as we move out finger
if(e.getAction() == MotionEvent.ACTION_MOVE){
x2 = e.getX();
y2 = e.getY();
p2 = mapView.getProjection().fromPixels((int)x2,(int)y2);
}
//---when user lifts his finger---
if (e.getAction() == MotionEvent.ACTION_UP) {
isUp = true;
}
return true;
}
return false;
}
}
using this i able to draw like this rectangle shapes and draw up to again you click the toggle button(possible to draw multiple times)
i want draw lines instead of rectangle like below image(draw multiple times).
finally i found this link this link provide rectangle shape draw http://n3vrax.wordpress.com/2011/08/13/drawing-overlays-on-android-map-view/
just change rectangle to free draw any idea please....
You can free hand draw a line using the code bellow:
Code
public class HandDrawOverlay extends Overlay {
private boolean editMode = false;
private boolean isTouched = false;
private Paint paint = new Paint();
private Point screenPt1 = new Point();
private Point screenPt2 = new Point();
private ArrayList<GeoPoint> points = null;
public HandDrawOverlay(){
paint.setStrokeWidth(2.0f);
paint.setStyle(Style.STROKE);
paint.setColor(Color.BLUE);
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
if(points != null && points.size() > 1){
mapView.getProjection().toPixels(points.get(0), screenPt1);
for(int i=1; i<points.size();i++){
mapView.getProjection().toPixels(points.get(i), screenPt2);
canvas.drawLine(screenPt1.x, screenPt1.y, screenPt2.x, screenPt2.y, paint);
screenPt1.set(screenPt2.x, screenPt2.y);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent e, MapView mapView) {
if(editMode){
int x = (int)e.getX();
int y = (int)e.getY();
GeoPoint geoP = mapView.getProjection().fromPixels(x,y);
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
isTouched = true;
points = new ArrayList<GeoPoint>();
points.add(geoP);
break;
case MotionEvent.ACTION_MOVE:
if(isTouched)
points.add(geoP);
break;
case MotionEvent.ACTION_UP:
if(isTouched)
points.add(geoP);
isTouched = false;
break;
}
mapView.invalidate();
return true;
}
return false;
}
/**
* #return the editMode
*/
public boolean isEditMode() {
return editMode;
}
/**
* #param editMode the editMode to set
*/
public void setEditMode(boolean editMode) {
this.editMode = editMode;
}
}
to use
HandDrawOverlay handDrawOverlay;
handDrawOverlay = new HandDrawOverlay();
mapView.getOverlays().add(handDrawOverlay);
//Set edit mode to true to start drwaing
handDrawOverlay.setEditMode(true);
//Set edit mode to true to stop drwaing
handDrawOverlay.setEditMode(false);
Note
This is a full functioning example to help you starting. However, you should optimize the code to make it more efficient (i.e. using Path to store the drawing path in onDraw(), reducing the number of points recorded in onTouch(), etc.).
Enjoy it.
My basic goal is to subtract a Path from a predetermined region (also created with a Path) in Android 1.6.
Is there anyway to get Region.setPath to treat the path passed to it the same way the canvas treats a stroked path (which is what my users are seeing)?
I understand that the Style is used for Painting to the canvas, but I need the behavior to reflect what is drawn on canvas and the path being drawn is Stroked.
The behavior works find when adding shapes to the path (path.addRect, path.addCircle), but not when using lineTo, quadTo, cubeTo. My only other option is to compose a path of nothing but rects or circles.
public class ComplexRegions extends Activity {
static Display display;
/** Code Sample for StackOverflow */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
display = getWindowManager().getDefaultDisplay();
setContentView(new SampleView(this));
}
private static class SampleView extends View {
Path orig_path, finger_path;
Paint dirty_paint, fingerpaint, temp_paint;
Region orig_region, clip, fingerregion, tempregion;
Canvas c;
int h, w;
public float mX, mY, dx, dy;
boolean b;
public SampleView(Context context) {
super(context);
fingerregion = new Region();
tempregion = new Region();
orig_region = new Region();
clip = new Region();
orig_path = new Path();
finger_path = new Path();
dirty_paint = new Paint();
dirty_paint.setStyle(Paint.Style.STROKE);
dirty_paint.setColor(Color.BLUE);
dirty_paint.setStrokeWidth(5);
dirty_paint.setStrokeCap(Paint.Cap.ROUND);
dirty_paint.setStrokeJoin(Paint.Join.ROUND);
dirty_paint.setAntiAlias(false);
fingerpaint = new Paint();
fingerpaint.setColor(Color.GREEN);
fingerpaint.setStrokeWidth(10);
fingerpaint.setStyle(Paint.Style.STROKE);
fingerpaint.setStrokeCap(Paint.Cap.ROUND);
fingerpaint.setStrokeJoin(Paint.Join.ROUND);
fingerpaint.setAntiAlias(false);
temp_paint = new Paint();
temp_paint.setColor(Color.RED);
temp_paint.setStrokeWidth(1);
temp_paint.setStyle(Paint.Style.STROKE);
temp_paint.setStrokeCap(Paint.Cap.ROUND);
temp_paint.setStrokeJoin(Paint.Join.ROUND);
temp_paint.setAntiAlias(false);
w = display.getWidth();
h = display.getHeight();
clip.set(0, 0, w, h);
orig_path.addRect(w*0.25f, h*0.55f, w*0.65f, h*0.65f, Path.Direction.CW);
orig_region.setPath(orig_path, clip);
}
#Override
protected void onDraw(Canvas c) {
c.drawPath(orig_path, dirty_paint);
c.drawPath(finger_path, fingerpaint);
//following line shows that finger_path is
//behaving as though fill and stroke is on
//after being passed to the region class
c.drawPath(tempregion.getBoundaryPath(), temp_paint);
invalidate();
}
//L T R B
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)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;
}
private void touch_start(float x, float y) {
finger_path.moveTo(x, y);
//finger_path.addCircle(x, y, 25, Path.Direction.CCW);
//when addCircle is only Path method used on path the result is fine
}
private void touch_move(float x, float y){
finger_path.lineTo(x, y);
}
private void touch_up() {
//*PROBLEM* Seems like setPath forces finger_path to default to fill and stroke
fingerregion.setPath(finger_path, clip);
//set tempregion to the region resulting from this Op
tempregion.op(orig_region, fingerregion, Region.Op.DIFFERENCE);
//check if the resulting region is empty
if(tempregion.isEmpty()){
for(int i = 0;i<100;i++)
Log.e("CR", "Region Completely Covered.");
}
}
}
}