Draw Circle Using Path in Android
Overview
Let's take a await at building a custom view that allows the user to paint on the screen past pressing downwardly their finger. This volition illustrate how to build custom components, how to draw shapes and paths on a view and too how to handle user touch interactions.
Creating our Custom View
Create a simple form for cartoon that extends View called SimpleDrawingView
:
public grade SimpleDrawingView extends View { public SimpleDrawingView ( Context context , AttributeSet attrs ) { super ( context , attrs ); } }
Add this to the XML layout for action so our custom view is embedded inside:
<RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "match_parent" android:layout_height= "match_parent" tools:context= ".MainActivity" > <com.codepath.example.simpledrawapp.SimpleDrawingView android:id= "@+id/simpleDrawingView1" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_alignParentBottom= "true" android:layout_alignParentLeft= "true" android:layout_alignParentRight= "true" android:layout_alignParentTop= "true" /> </RelativeLayout>
Simple Drawing with Canvass
Allow's try cartoon a couple of circles on screen. This requires the states to ascertain a Paint
object which controls the styling and color of what is drawn. Let'due south start past preparing the paint:
public class SimpleDrawingView extends View { // setup initial color private final int paintColor = Color . Black ; // defines paint and sheet private Paint drawPaint ; public SimpleDrawingView ( Context context , AttributeSet attrs ) { super ( context , attrs ); setFocusable ( true ); setFocusableInTouchMode ( true ); setupPaint (); } // Setup paint with color and stroke styles private void setupPaint () { drawPaint = new Paint (); drawPaint . setColor ( paintColor ); drawPaint . setAntiAlias ( true ); drawPaint . setStrokeWidth ( 5 ); drawPaint . setStyle ( Pigment . Fashion . STROKE ); drawPaint . setStrokeJoin ( Paint . Join . ROUND ); drawPaint . setStrokeCap ( Paint . Cap . Circular ); } }
Now that nosotros have the paint setup to have a black color and configured a particular stroke style, let's try to draw a few circles with dissimilar colors. All drawing that happens in a view should take identify within the onDraw
method which is automatically called when a view is rendered:
public class SimpleDrawingView extends View { // ...variables and setting up paint... // Let's draw three circles @Override protected void onDraw ( Canvas canvas ) { canvas . drawCircle ( 50 , 50 , 20 , drawPaint ); drawPaint . setColor ( Colour . GREEN ); canvas . drawCircle ( fifty , 150 , twenty , drawPaint ); drawPaint . setColor ( Color . BLUE ); canvass . drawCircle ( 50 , 250 , xx , drawPaint ); } }
Observe that onDraw
passes us a canvas
object which we use to draw leveraging the Pigment
nosotros divers earlier. The drawCircle
method accepts the x, y and radius of the circle in addition to the paint. This renders the following:
Handling Touch Interactions
Suppose now we wanted to draw a circle every time the user touches down on the drawing view. This would require u.s. to go on runway of an assortment of points for our circles so append a point for each onTouch
outcome triggered:
public form SimpleDrawingView extends View { // setup initial color individual final int paintColor = Colour . Blackness ; // defines pigment and sheet individual Paint drawPaint ; // Shop circles to describe each time the user touches down individual List < Indicate > circlePoints ; public SimpleDrawingView ( Context context , AttributeSet attrs ) { super ( context , attrs ); setupPaint (); // same equally before circlePoints = new ArrayList < Point >(); } // Draw each circle onto the view @Override protected void onDraw ( Sheet canvas ) { for ( Point p : circlePoints ) { sheet . drawCircle ( p . x , p . y , 5 , drawPaint ); } } // Append new circle each time user presses on screen @Override public boolean onTouchEvent ( MotionEvent effect ) { float touchX = consequence . getX (); float touchY = consequence . getY (); circlePoints . add together ( new Point ( Math . round ( touchX ), Math . circular ( touchY ))); // indicate view should be redrawn postInvalidate (); render true ; } private void setupPaint () { // same equally earlier drawPaint . setStyle ( Paint . Style . Fill ); // change to make full // ... } }
with this, a blackness circumvolve is drawn each time nosotros press down:
Drawing with Paths
And so far we have explored the onDraw
method of a view and we were able to depict circles onto the view based on impact interactions with the view. Adjacent, allow's meliorate our drawing application by removing the list of circles and instead cartoon with paths. The Path class is platonic for allowing the user to draw on screen. A path can contain many lines, contours and even other shapes. Offset, allow's add together a Path
variable to track our cartoon:
public class SimpleDrawingView extends View { // ... individual Path path = new Path (); // ... }
Next, allow's suspend points to the path every bit the user touches the screen. When the user presses down, let's start a path and then when they drag let's connect the points together. To exercise this, we need alter the onTouchEvent
to append these points to our Path object:
public course SimpleDrawingView extends View { private Path path = new Path (); // Become 10 and y and suspend them to the path public boolean onTouchEvent ( MotionEvent outcome ) { bladder pointX = event . getX (); float pointY = upshot . getY (); // Checks for the effect that occurs switch ( event . getAction ()) { example MotionEvent . ACTION_DOWN : // Starts a new line in the path path . moveTo ( pointX , pointY ); interruption ; case MotionEvent . ACTION_MOVE : // Draws line between last point and this point path . lineTo ( pointX , pointY ); intermission ; default : return false ; } postInvalidate (); // Signal view should be redrawn return true ; // Indicate we've consumed the affect } // ... }
and and then let'southward alter the onDraw
to remove the circles and instead to render the lines we have plotted in our path:
public class SimpleDrawingView extends View { // ... onTouchEvent ... // Draws the path created during the affect events @Override protected void onDraw ( Canvas canvas ) { canvas . drawPath ( path , drawPaint ); } private void setupPaint () { // same as earlier drawPaint . setStyle ( Paint . Style . STROKE ); // modify back to stroke // ... } }
and with that, nosotros have a very basic painting app that looks like:
Efficient Drawing with Bitmap Cache
When drawing onto a canvas, you lot tin oftentimes significantly improve return times past caching the image into a bitmap as outlined in this stackoverflow postal service.
Bitmap mField = nix ; public void init () { mField = new Bitmap (... dimensions ...); Canvas c = new Canvas ( mField ); c . drawRect (...); ... } public void onDraw ( Canvass c ) { c . drawBitmap ( mField ); }
This is a common design for improving drawing operation.
Reference for SimpleDrawingView
The full source code for our SimpleDrawingView
:
package com . codepath . instance . simpledrawapp ; import android.content.Context ; import android.graphics.Sail ; import android.graphics.Color ; import android.graphics.Pigment ; import android.graphics.Path ; import android.util.AttributeSet ; import android.view.MotionEvent ; import android.view.View ; public class SimpleDrawingView extends View { // setup initial color individual final int paintColor = Color . BLACK ; // defines paint and canvas individual Paint drawPaint ; // stores side by side circle private Path path = new Path (); public SimpleDrawingView ( Context context , AttributeSet attrs ) { super ( context , attrs ); setFocusable ( truthful ); setFocusableInTouchMode ( true ); setupPaint (); } private void setupPaint () { // Setup pigment with color and stroke styles drawPaint = new Paint (); drawPaint . setColor ( paintColor ); drawPaint . setAntiAlias ( truthful ); drawPaint . setStrokeWidth ( five ); drawPaint . setStyle ( Pigment . Style . STROKE ); drawPaint . setStrokeJoin ( Paint . Bring together . Circular ); drawPaint . setStrokeCap ( Paint . Cap . ROUND ); } @Override protected void onDraw ( Canvass canvas ) { canvas . drawPath ( path , drawPaint ); } @Override public boolean onTouchEvent ( MotionEvent event ) { bladder pointX = effect . getX (); bladder pointY = event . getY (); // Checks for the event that occurs switch ( event . getAction ()) { case MotionEvent . ACTION_DOWN : path . moveTo ( pointX , pointY ); return true ; case MotionEvent . ACTION_MOVE : path . lineTo ( pointX , pointY ); break ; default : return simulated ; } // Strength a view to draw again postInvalidate (); return true ; } }
Drawing with Density Independent Pixels
When drawing or animating, you oft want to draw using density independent pixels in order to be robust to different device sizes and densities. You may besides want to determine the device pinnacle or width in guild to draw intelligently. Copy this DeviceDimensionsHelper.java utility grade to DeviceDimensionsHelper.java
in your project and utilise anywhere that yous take a context to decide screen dimensions or practise translations between dp
and px
:
// Go height or width of screen int screenHeight = DeviceDimensionsHelper . getDisplayHeight ( this ); int screenWidth = DeviceDimensionsHelper . getDisplayWidth ( this ); // Convert dp to pixels float px = DeviceDimensionsHelper . convertDpToPixel ( 25 f , this ); // Convert pixels to dp bladder dp = DeviceDimensionsHelper . convertPixelsToDp ( 25 f , this );
You can then use this to practise smarter drawing for more responsive custom views.
Source: https://guides.codepath.com/android/Basic-Painting-with-Views
0 Response to "Draw Circle Using Path in Android"
Post a Comment