Yauraw Gadav
Yauraw Gadav

Reputation: 1746

Drawing a rectangle using a move gesture

I am trying to create a rectangle, but this is what happens when I move from starting coordinates towards the end coordinates

is what happens

, actually I want to show the progress when the user moves from one point to other as well.This is what I would like to have. I would like to have.

Code:-

public boolean onTouch(View v, MotionEvent event) {

    int action = event.getAction();
    switch (action) {
    case MotionEvent.ACTION_DOWN:
        downx = event.getX();
        downy = event.getY();

    //v.invalidate();
        break;
    case MotionEvent.ACTION_MOVE:
        upx = event.getX();
        upy = event.getY();

         canvas.drawRect(downx, downy, upx, upy, paint);

         }
        choosenImageView.invalidate();
        break;
    case MotionEvent.ACTION_UP:
        upx = event.getX();
        upy = event.getY();
            canvas.drawRect(downx, downy, upx, upy, paint);
            }
        } 

        // v.invalidate();
        break;
    }
    return true;
}

Edit What I would like to do is to show the progress i.e. as the user moves his finger, shape should be drawn.

Suggestions/Samples/links anything will be appreciated.

Upvotes: 7

Views: 7736

Answers (6)

Robin
Robin

Reputation: 943

This is Vegers answer converted to Kotlin.

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    if (startedDrawing) {
        canvas.drawRect(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y, mPaint)
    }
    
}

override fun onTouchEvent(event: MotionEvent): Boolean {
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            startedDrawing = true
            startPoint.x = event.x
            startPoint.y = event.y
            currentPoint.x = event.x
            currentPoint.y = event.y
            invalidate()
        }
        MotionEvent.ACTION_MOVE -> {
            currentPoint.x = event.x
            currentPoint.y = event.y
            invalidate()
        }
        MotionEvent.ACTION_UP -> {
            startedDrawing = false
            invalidate()
        }
    }
    return true
}

Upvotes: 0

Veger
Veger

Reputation: 37905

You are directly updating the canvas in the onTouch() event without clearing it first. This is not the supposed way of drawing something in a View (assuming this is what you want).

Instead you are supposed to store the begin and current coordinates of the rectangle and use them in the onDraw() event to draw the actual rectangle (after Adnroid cleared the invalidated part of the Canvas for you). Android will issue this event if the canvas needs to be redrawn, so you need to tell that this is required in the onTouch() event, by using the invalidate() method:

class myView extends View { // or some other View-based class
   boolean drawRectangle = false;
   PointF beginCoordinate;
   PointF endCoordinate;

   public boolean onTouch(View v, MotionEvent event) {
      switch(event.getAction()) {
         case MotionEvent.ACTION_DOWN:
            drawRectangle = true; // Start drawing the rectangle
            beginCoordinate.x = event.getX();
            beginCoordinate.y = event.getY();
            endCoordinate.x = event.getX();
            endCoordinate.y = event.getY();
            invalidate(); // Tell View that the canvas needs to be redrawn
            break;
         case MotionEvent.ACTION_MOVE:
            endCoordinate.x = event.getX();
            endCoordinate.y = event.getY();
            invalidate(); // Tell View that the canvas needs to be redrawn
            break;
         case MotionEvent.ACTION_UP:
            // Do something with the beginCoordinate and endCoordinate, like creating the 'final' object
            drawRectangle = false; // Stop drawing the rectangle
            invalidate(); // Tell View that the canvas needs to be redrawn
            break;
      }
      return true;
   }

   protected void onDraw(Canvas canvas) {
      if(drawRectangle) {
         // Note: I assume you have the paint object defined in your class
         canvas.drawRect(beginCoordinate.x, beginCoordinate.y, endCoordinate.x, endCoordinate.y, paint);
      }
   }
}

Upvotes: 9

Zala Janaksinh
Zala Janaksinh

Reputation: 2927

Sorry Dear i give you whole activity witch i use and draw rect on canvas.

public class CanvasExample extends Activity 
    {
        /** Called when the activity is first created. */

        RelativeLayout relMainOperationLayout;
        RelativeLayout relTabHeader;
        //RelativeLayout relMidalLayout;
        RelativeLayout relBelowLayout;
        Context myContext;
        DrawCanvas drawCanvas;
        static boolean loadFlage=true;
        BibleHelper bibleHelper;

         Bitmap mainBitmap;




        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            myContext=CanvasExample.this;
            bibleHelper=new BibleHelper(CanvasExample.this,myContext);
            bibleHelper.setFullScreen();

            LayoutInflater layoutInflater=(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);   

            int layoutId = myContext.getResources().getIdentifier("main","layout",getPackageName());

            relMainOperationLayout = (RelativeLayout) layoutInflater.inflate(layoutId,null);

            relTabHeader=(RelativeLayout) relMainOperationLayout.findViewById(R.id.relHeadLayout);

            //relMidalLayout=(RelativeLayout) relMainOperationLayout.findViewById(R.id.relmidalLayout);

            relBelowLayout=(RelativeLayout) relMainOperationLayout.findViewById(R.id.relBelowLayout);



            mainBitmap=getIconDrawable(R.drawable.splash);


            drawCanvas=new DrawCanvas(CanvasExample.this,myContext);

            //drawCanvas.setBackgroundColor(Color.YELLOW);

            //drawCanvas.setBackgroundDrawable(CanvasExample.this.getResources().getDrawable(R.drawable.splash));

            drawCanvas.setBackgroundDrawable(new BitmapDrawable(mainBitmap));



            RelativeLayout.LayoutParams drawParams=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

            drawParams.addRule(RelativeLayout.BELOW, relTabHeader.getId());

            //relMidalLayout.addView(drawCanvas,drawParams);

            relMainOperationLayout.addView(drawCanvas,drawParams);


//          mainImageView=new ImageView(CanvasExample.this);
//          
//          RelativeLayout.LayoutParams mainParams=new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,200);
//          relMainOperationLayout.addView(mainImageView,mainParams);
//          mainImageView.setBackgroundDrawable(CanvasExample.this.getResources().getDrawable(R.drawable.ic_launcher));





            setContentView(relMainOperationLayout);



        }




        class DrawCanvas extends View
        {

            Context drawContext;
            Activity drawActivity;
            ImageView image;
            Paint mPaint;
            int left=0,right=0,top=0,bottom=0;
            Canvas passCanvas;

            //Bitmap bitmapOrg;
            // bitmapOrg;

            public DrawCanvas(Activity activity,Context context)
            {
                super(activity);

                this.drawActivity=activity;

                this.drawContext=context;

                //bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.splash);

                    mPaint = new Paint();

                    mPaint.setDither(true);

                    mPaint.setColor(Color.RED);

                    mPaint.setStyle(Paint.Style.STROKE);

                    mPaint.setStrokeJoin(Paint.Join.ROUND);

                    mPaint.setStrokeCap(Paint.Cap.ROUND);

                    mPaint.setStrokeWidth(3);

                    mPaint.setFilterBitmap(true);

                this.setOnTouchListener(new View.OnTouchListener() {

                    //@Override
                    public boolean onTouch(View v, MotionEvent event)
                    {

                        switch (event.getActionMasked()) 
                        {
                        case MotionEvent.ACTION_DOWN:

                            invalidate();

                            left=(int) event.getX();
                            right=left+1;
                            top=(int) event.getY();
                            bottom=top+1;               
                            mPaint.setColor(Color.BLACK);
                            onDraw(passCanvas=new Canvas());
                        break;

                        case MotionEvent.ACTION_MOVE:                   
                            invalidate();
                            int tempX=(int) event.getX();

                            //System.err.println("Get X->"+event.getX());
                            if(tempX>right)
                            {
                                right=right+1;
                            }
                            else
                            {
                                right=right-1;

                            }
                            //System.err.println("Get Y->"+event.getY());
                            int tempY=(int) event.getY();

                            if(tempY>bottom)
                            {
                                bottom=bottom+1;                

                            }else
                            {
                                bottom=bottom-1;                

                            }

                            mPaint.setColor(Color.GREEN);
                            onDraw(passCanvas=new Canvas());
                        break;

                        case MotionEvent.ACTION_UP:
                            invalidate();
                            mPaint.setColor(Color.RED);
                            onDraw(passCanvas=new Canvas());
                            System.err.println("After Touch Up");
                            CanvasExample.loadFlage=false;
                            onDraw(passCanvas=new Canvas());


                            /*
                            bibleHelper.showErrorLog("Start X -->"+left);

                            bibleHelper.showErrorLog("Real  X -->"+event.getX());

                            bibleHelper.showErrorLog("End X-->"+right);

                            bibleHelper.showErrorLog("Start Y-->"+top);

                            bibleHelper.showErrorLog("Real Y-->"+top);


                            bibleHelper.showErrorLog("End Y-->"+bottom);
                            */

                            Bitmap croppedBmp = Bitmap.createBitmap(mainBitmap,left,top,right,bottom);


                            final Dialog dialog = new Dialog(CanvasExample.this);

                            dialog.setContentView(R.layout.custom_dialog);
                            dialog.setTitle("Title...");
                            dialog.setCancelable(true);

                            ImageView image = (ImageView) dialog.findViewById(R.id.main);
                            image.setImageBitmap(croppedBmp);
                            Button btnClose=(Button) dialog.findViewById(R.id.btnClose);

                            btnClose.setOnClickListener(new View.OnClickListener() 
                            {

                                public void onClick(View v) 
                                {
                                    dialog.dismiss();
                                }
                            });

                            dialog.show();

                        break;

                        default:

                            break;
                        }
                        return true;
                    }
                });     

            }

            @Override
            protected void onDraw(Canvas canvas) 
            {

                canvas.drawRect(left, top, right, bottom, mPaint);
            }

        }
        private Bitmap getIconDrawable(int imageId)
        {
            //Drawable rtnDrawable = null;
            Bitmap imageBitmap=null;
            try 
            {
                int getImageWH[];
                imageBitmap = BitmapFactory.decodeResource(getResources(),imageId);
                int IW = imageBitmap.getWidth();
                int IH = imageBitmap.getHeight();

                bibleHelper.showErrorLog("Icon Width->" + IW);
                bibleHelper.showErrorLog("Icon Height->" + IH);

                WindowManager winManager = (WindowManager) CanvasExample.this.getSystemService(Context.WINDOW_SERVICE);
                int screenwidth = winManager.getDefaultDisplay().getWidth();
                int screenheight = winManager.getDefaultDisplay().getHeight();  

                getImageWH = bibleHelper.getObjectWidthHeight(screenwidth,screenheight, IW, IH);

                bibleHelper.showErrorLog("Get Icon Width->" + getImageWH[0]);
                 bibleHelper.showErrorLog("Get Icon Height->" + getImageWH[1]);

                imageBitmap = Bitmap.createScaledBitmap(imageBitmap, getImageWH[0],getImageWH[1], false);

                bibleHelper.showErrorLog("New Width-->"+imageBitmap.getWidth());
                bibleHelper.showErrorLog("New Height-->"+imageBitmap.getHeight());

                //rtnDrawable = (Drawable) new BitmapDrawable(imageBitmap);
            } catch (Exception ex) {
                bibleHelper.showErrorLog("Convert Icon Exception-->"+ ex.toString());
            }
            //return rtnDrawable;
            return imageBitmap;
        }


}

In this BibleHelper is Helper class witch use for display some message and log .

Upvotes: 3

Marcio Covre
Marcio Covre

Reputation: 4556

If I understand you correct you want the user to draw the rectangle on the screen and you would then draw it on the display.

I think you could just paint a point where the user presses, just to give a feedback to the user, and when he finishes drawing you substitute by the rectangle

Or draw the lines of the rectangle, so user starts drawing and you have a line from the start to his finger, when user changes direction you start a new line from where the user changed direction and the finger, then when the user returns to start you have a rectangle draw as 4 lines

Upvotes: 2

Melki
Melki

Reputation: 619

Do you clean the canvas between two rectangle ? Add a function like this one :

 void clearCanvas()
  {
     canvas.drawRect(0,0, width, height, paint);

  }

Upvotes: 6

Vinay
Vinay

Reputation: 6881

case MotionEvent.ACTION_MOVE:
   upx = event.getX();
   upy = event.getY();

   canvas.drawRect(downx, downy, upx, upy, paint);

   }
   choosenImageView.invalidate();
break;

This code is causing it. Because you are creating many rectangles here. Instead, in onDraw(Canvas canvas) have drawRect method and use invalidate on all events. Hope this helps.

Upvotes: 3

Related Questions