8

In my app I want to draw line on imageview along with finger. I want the output like the following:enter image description here

In this screen fish is the imageview and red lines are drawing lines. So I followed the link below to develop the app link. This is my code:

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.addphoto);

    btnAddPhoto=(Button)findViewById(R.id.add);
    btnEdit=(Button)findViewById(R.id.edit);
    imageView=(ImageView)findViewById(R.id.photo);

    btnAddPhoto.setOnClickListener(this);
    btnEdit.setOnClickListener(this);
    imageView.setOnTouchListener(this);         
}

    @Override
public void onWindowFocusChanged(boolean hasFocus){
    width=imageView.getWidth();
    height=imageView.getHeight();

    Log.e("heightttt",""+height);
    Log.e("Widthhhh",""+width);

}

    @Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    if(v.equals(btnAddPhoto)){

        popup.setVisibility(View.VISIBLE);
    }

    if(v.equals(btnEdit)){
       bitmap = Bitmap.createBitmap((int) width, (int) height,Bitmap.Config.ARGB_8888);
        canvas = new Canvas(bitmap);
        paint = new Paint();
        paint.setColor(Color.BLACK);
        imageView.setImageBitmap(bitmap);
        imageView.setOnTouchListener(this);
    }
}

    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
          downx = event.getX();
          downy = event.getY();
          break;
        case MotionEvent.ACTION_MOVE:
          break;
        case MotionEvent.ACTION_UP:
          upx = event.getX();
          upy = event.getY();
          canvas.drawLine(downx, downy, upx, upy, paint);
          imageView.invalidate();
          break;
        case MotionEvent.ACTION_CANCEL:
          break;
        default:
          break;
        }
        return true;
      }

In this coding whenever I run the application the below screen will be open.

enter image description here

Then by using add button I added the photo from my gallery. This is below screen.

enter image description here

Then whenever I click edittool button the fish imageview gone and I could draw the straight lines only like the following. But I want to draw lines on imageview along with finger like first screen.

enter image description here

Please anybody help me. I am new to android. Thanks for any help.

Marat
  • 6,142
  • 6
  • 39
  • 67
rams
  • 1,558
  • 7
  • 25
  • 48

1 Answers1

24

You should override the onDraw method of your view.

screen_drawing_room.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rlid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout   <!--set background for the bottom layout set image here. -->
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="bottom"
    android:orientation="vertical"
    android:weightSum="1.0" >

    <LinearLayout
        android:id="@+id/view_drawing_pad" <!--your drawing pad on foreground -->
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </LinearLayout>
</LinearLayout>
</RelativeLayout

In your activities onCreate()

DrawingView mDrawingView=new DrawingView(this);
setContentView(R.layout.screen_drawing_room);    
LinearLayout mDrawingPad=(LinearLayout)findViewById(R.id.view_drawing_pad);
mDrawingPad.addView(mDrawingView);

DrawingView.java

Define your DrawingView. The below can be used for freehand drawing. Modify the same to draw lines, texts and fill color( closed area). For flood Fill see the accepted answer in the link android using flood fill algorithm getting out of memory exception.

class DrawingView extends View {
    Paint       mPaint;
    //MaskFilter  mEmboss;
    //MaskFilter  mBlur;
    Bitmap  mBitmap;
    Canvas  mCanvas;
    Path    mPath;
    Paint   mBitmapPaint;

    public DrawingView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(0xFFFF0000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(20);

        mPath = new Path();
        mBitmapPaint = new Paint();
        mBitmapPaint.setColor(Color.RED);
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }
    @Override
    public void draw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.draw(canvas);
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        canvas.drawPath(mPath, mPaint);
    }
    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;
        }
    }
    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        //mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
        // kill this so we don't double draw
        mPath.reset();
       // mPath= new Path();
    }

    @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;
    }   
}

Your Drawing view is set. Study the fingerpaint.java from the sample on sdk under the graphics folder.

Resulting sanpshot. What you see in the background is a image. On the foreground I draw hi. I have draw lines to the corner. If you can make out it is red.

Draw lines which look like border. Set Stroke width for the paint to whatever you like. Similarly you can draw lines where you want by changing the x1,y1 and x2,y2 co-ordinates.

Display display = ( (Activity) mcontext).getWindowManager().getDefaultDisplay();  
float w = display.getWidth(); 
float h = display.getHeight();
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawLine(0, 0, w, 0,mBitmapPaint);
canvas.drawLine(0, 0, 0, h,mBitmapPaint);
canvas.drawLine(w,h,w,0,mBitmapPaint);
canvas.drawLine(w, h, 0,h , mBitmapPaint);

enter image description here

Edit:

To get image from gallery

File fp;
Drawable d;   

public void  setImagefrmGallery() {
    // To open up a gallery browser
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select Picture"),1);
    // To handle when an image is selected from the browser, add the following to your Activity 
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == 1) {
            // currImageURI is the global variable I�m using to hold the content:// URI of the image
            Uri currImageURI = data.getData();
            System.out.println("Hello======="+getRealPathFromURI(currImageURI));
            String s= getRealPathFromURI(currImageURI);
            File file = new File(s);

            if (file.exists()) {
                fp=file.getAbsolutePath();
                d = Drawable.createFromPath(file.getAbsolutePath());
                mDrawingPad.setBackgroundDrawable(d);
            } else {
                System.out.println("File Not Found");
            }
        }
    }
}

// And to convert the image URI to the direct file system path of the image file
public String getRealPathFromURI(Uri contentUri) {
    // can post image
    String [] proj={MediaStore.Images.Media.DATA};
    Cursor cursor = managedQuery( contentUri,
            proj, // Which columns to return
            null, // WHERE clause; which rows to return (all rows)
            null, // WHERE clause selection arguments (none)
            null); // Order-by clause (ascending by name)
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index); 
}
Community
  • 1
  • 1
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • Sorry bro I cant understand.I want to draw a line on imageview only.In my xml I have have taken imageview in relative layout.In that image view i want to draw a line along with finger. – rams Mar 29 '13 at 13:56
  • yes you can use the above. in xml set for 1st linearlayout add background that is considered to be the bottom view. Now set your another linearlayout to a drawingview. drawing view can be ised to draw lines and freehand – Raghunandan Mar 29 '13 at 13:59
  • it look will something like image in background and on top of it you see the draw. – Raghunandan Mar 29 '13 at 14:01
  • is it possible to add gallary image to linear layout programatically. – rams Mar 29 '13 at 14:26
  • bro I have taken linear layout as you said and add the fish image to that layout,now i want to draw lines only on fish image.So how can I get height and width of linear layout only.please suggest me how to do.Thanks inadvance – rams Mar 30 '13 at 05:43
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27220/discussion-between-venkataramana-and-raghunandan) – rams Mar 30 '13 at 06:52
  • @Raghunandan: Can you give me some suggestion. I want to place `DrawingView` on the existing `ImageView` . because I can surely set background to the `DrawingView` but my background image is getting stratched as there are no attribute of `scaleType` like `ImageView` – Mehul Joisar Apr 11 '14 at 11:27
  • @Raghunandan Is there an alternative of mDrawingPad.setBackgroundDrawable(d); because i don't use a layout as in this example github.com/valerio-bozzolan/AcrylicPaint/blob/master/src/anupam/… Thank you! – user3219446 Dec 04 '14 at 17:17
  • Hi, This works. The only problem is, its not smooth. It seems there is a lag between the canvas paint appearing on screen and the finger movement. Is there anyway to fix that? I mean like the default drawing tool in Decoration options when you open image in gallery on your device. Just like that. – Abhinav Raja Oct 01 '17 at 16:41
  • Not sure. Please ask a new question with relevant details. – Raghunandan Oct 02 '17 at 17:57
  • I find sometimes I have scaling issues with this. I get an image and it attempts to fill the entire background and so it stretches. Any way to avoid this? – AdamMc331 Nov 03 '17 at 00:12
  • @AdamMc331 let me try a sample. You have small image that is set as background and it is stretched? – Raghunandan Nov 03 '17 at 05:22
  • @Raghunandan What I do is I use the camera intent to let the user take a picture, and when I set it to my DrawView background it stretches, because the resolution from the camera is not the same as the DrawView. Would love to do this and simulate the `centerCrop` scale type of an ImageView, or something like it. – AdamMc331 Nov 03 '17 at 13:33
  • @AdamMc331 why not extends a imageview and apply centerCrop scale type or scale and then you can do the drawing on top of it – Raghunandan Nov 05 '17 at 06:30
  • How to save the complete drawing (the image plus the lines drawn on the top)? – Atul gupta Jul 07 '20 at 18:37