There are multiple scribble apps on here that have an undo button. I haven't implemented those because my code is different, but I have looked at the concepts. I.E storing points in an array.
When the program detects touch events:
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX(); //Gets the fingers x position
float touchY = event.getY(); //gets the fingers y position
PointF points = new PointF(); //init a new PointF
points.x = touchX; //store the coordinates in the Point object
points.y = touchY;
_pointList.add(points); //add this to the list of Points (array)
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
_path.moveTo(touchX, touchY); //Set the beginning of the next contour to the point (x,y)
//will start drawing from where the last point was
break;
case MotionEvent.ACTION_MOVE:
_path.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();
return true;
}
In theory the _pointList Array should capture all the touch inputs in order. And this is evident, since the console displays the size of the array.
In the onDraw method, it should loop through all of the points in the a_pointList List. Since it contains all of the points that the user has interacted on the screen, then in theory it should draw the lines from memory.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (PointF points : _pointList) {
_path.moveTo(points.x, points.y);
_path.lineTo(points.x, points.y);
_canvas.drawPath(_path, _paint);
}
canvas.drawBitmap(_bitmap, 0, 0, _paint);
}
When the application runs I am able to draw on the screen, and due to the clear method the screen clears.
public void clear(){
_pointList.clear();// empty the list that stores the points
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
//empties the screen
invalidate();
}
However, in my undo method, it should drop one of the points (that contains the users X and Y touch inputs) from the _pointList List. After dropping the point, the screen should redraw all of the lines from memory.
public void undo() {
Log.d("Number", "undo:" + _pointList.size() );
if (_pointList.size()>0){
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
_pointList.remove(_pointList.size() - 1);
invalidate();
}
}
This method has the same effect as the 'clear' method and does not redraw the lines,
My other alternatives to the undo button was putting the bitmaps into an array, but I'm sure that would cause memory issues since it's a dynamic program.
Question: Why doesn't the 'invalidate' call from the 'undo' method update the screen?
Update:
The whole code:
--Draw--
package com.example.moynul.myapplication;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by moynu on 10/12/2015.
*/
public class Draw extends View {
private Paint _paint = new Paint();
private Path _path = new Path();
private Bitmap _bitmap;
private Canvas _canvas;
private List<PointF> _pointList = new ArrayList<PointF>();
public Draw(Context context) {
super(context);
init(null, 0);
}
public Draw(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs,0);
}
public Draw(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr);
}
private void init(AttributeSet attrs, int defStyleAttr) {
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
_bitmap = Bitmap.createBitmap (1080, 1920, Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX(); //Gets the fingers x position
float touchY = event.getY(); //gets the fingers y position
PointF points = new PointF(); //init a new PointF
points.x = touchX; //store the coordinates in the Point object
points.y = touchY;
_pointList.add(points); //add this to the list of Points (array)
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
_path.moveTo(touchX, touchY); //Set the beginning of the next contour to the point (x,y)
//will start drawing from where the last point was
break;
case MotionEvent.ACTION_MOVE:
_path.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (PointF points : _pointList) {
_path.moveTo(points.x, points.y);
_path.lineTo(points.x, points.y);
_canvas.drawPath(_path, _paint);
}
canvas.drawBitmap(_bitmap, 0, 0, _paint);
}
public void clear(){
_pointList.clear();// empty the list that stores the points
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
//empties the screen
invalidate();
}
public void undo() {
Log.d("Number", "undo:" + _pointList.size());
if (_pointList.size()>0){
_pointList.remove(_pointList.size() - 1);
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
invalidate();
}
}
}
Change following inside onDraw() for loop
canvas.drawPath(_path, _paint);
Hope it will work
You have an issue in your onDraw method, you are always drawing the _bitmap on the same positions (0,0) not on the path. Replace your onDraw code with my code below:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (PointF points : _pointList) {
_path.moveTo(points.x, points.y);
_path.lineTo(points.x, points.y);
_canvas.drawPath(_path, _paint);
canvas.drawBitmap(_bitmap, points.x, points.y, _paint);
}
}
Related
I make a puzzle in android and for find the words the user need cross to word. For drawing I think I need use canvas. But I would only right, left, above or below line.
How can I make line in android?
I need your help.
You just need to handle the drawing inside your View onTouchEvent. Whenever you touch the screen, draw the line until you untouch the screen.
public class DrawingView extends View {
private Paint mPaint;
private Path mPath;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(10);
mPath = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(mPath, mPaint);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(event.getX(), event.getY());
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
The above is a running sample of a basic drawing line in a View. You need to customize it further according to your own need.
I write the following code in SOF editor, so you'd probably need to shape it up a bit in your Android Studio.
The main idea is: use the Path to track the move path of finger. Then draw the path in onDraw.
In your view:
Paint paint = new Paint(Paint.Style.ANTI_ALIAS);
Path path = new Path();
#Override
public boolean onTouch(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(event.getX(), event.getY());
invalidate();
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
canvas.draw(path, paint);
}
If you need support multi fingers, let me know I can post more codes.
UPDATE
Code sample for multiple finger move to draw lines:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
import com.chinalwb.multitouchview.Utils;
import androidx.annotation.Nullable;
public class MultiTouchView3 extends View {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private SparseArray<Path> paths = new SparseArray<>(5);
public MultiTouchView3(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
{
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(Utils.dp2px(5));
paint.setColor(Color.RED);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < paths.size(); i++) {
canvas.drawPath(paths.valueAt(i), paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int actionIndex = event.getActionIndex();
int pointerId = event.getPointerId(actionIndex);
Log.e("XX", "pointer id == " + pointerId);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
Path path = new Path();
path.moveTo(event.getX(actionIndex), event.getY(actionIndex));
paths.put(pointerId, path);
Log.e("XX", "paths size == " + paths.size());
break;
case MotionEvent.ACTION_MOVE:
for (int i = 0; i < event.getPointerCount(); i++) {
pointerId = event.getPointerId(i);
Path pointerPath = paths.get(pointerId);
pointerPath.lineTo(event.getX(i), event.getY(i));
}
invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
path = paths.get(pointerId);
if (null != path) {
paths.remove(pointerId);
invalidate();
}
break;
}
return true;
}
}
You can comment out case MotionEvent.ACTION_POINTER_DOWN: and case MotionEvent.ACTION_POINTER_UP: if you only want to support single finger.
Here is the Kotlin version of LiuWenbin_NO.'s answer, to save time :)
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
class DrawingView #JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: View(context, attrs, defStyleAttr) {
private val mPaint: Paint = Paint()
private val mPath: Path = Path()
init
{
mPaint.apply {
color = Color.RED
style = Paint.Style.STROKE
strokeJoin = Paint.Join.ROUND
strokeCap = Paint.Cap.ROUND
strokeWidth = 10f
}
}
// Called when the view should render its content.
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas!!.drawPath(mPath, mPaint)
}
#SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent?): Boolean
{
when(event?.action) {
MotionEvent.ACTION_DOWN -> {
mPath.moveTo(event.x, event.y)
}
MotionEvent.ACTION_MOVE -> {
mPath.lineTo(event.x, event.y)
invalidate()
}
}
return true
}
}
I am working on an application similar to Amaziograph of iPhone also known as kaleidoscope or mandala.
Till now I have tried and have made one particular layout of that app
I have extended the canvas and have made a custom canvas, where I have divided canvas in 9 parts similar to image and in draw method I have rotated the canvas and copied its content in for loop. Here is my canvas class code for above circular division shape
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.madala.mandaladrawing.R;
import com.madala.mandaladrawing.model.DrawingEvent;
import com.madala.mandaladrawing.utils.Common;
public class CanvasView extends View {
private final Context context;
private Bitmap bitmap;
private Canvas bitmapCanvas;
private Paint bitmapPaint;
private Path path = new Path();
private Paint brushPaint;
private int numberOfMirror = 5;
private int cx, cy;
public CanvasView(Context context) {
super(context);
this.context = context;
init();
}
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
private void init() {
brushPaint = createPaint();
brushPaint.setColor(0xffffffff);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
canvas.drawPath(path, brushPaint);
for (int i = 1; i < numberOfMirror; i++) {
canvas.rotate(360f / numberOfMirror, cx, cy);
canvas.drawPath(path, brushPaint);
}
}
public void clearCanvas(){
bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
bitmapPaint = new Paint(Paint.DITHER_FLAG);
cx = w / 2;
cy = h / 2;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
path.lineTo(x, y);
drawToCanvas(path, brushPaint);
path.reset();
break;
default:
return false;
}
invalidate();
return true;
}
private void drawToCanvas(Path path, Paint brushPaint) {
bitmapCanvas.drawPath(path, brushPaint);
for (int i = 1; i < numberOfMirror; i++) {
bitmapCanvas.rotate(360f / numberOfMirror, cx, cy);
bitmapCanvas.drawPath(path, brushPaint);
}
}
public int getCurrentBrushColor() {
return brushPaint.getColor();
}
public void setCurrentBrushColor(int color) {
brushPaint.setColor(color);
}
private Paint createPaint() {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setStrokeWidth(8f);
p.setStyle(Paint.Style.STROKE);
p.setStrokeJoin(Paint.Join.ROUND);
p.setStrokeCap(Paint.Cap.ROUND);
return p;
}
}
I am not able to achieve the functionality for below figure
I want to draw in one box and it should be copied in the other boxes. How could this be achieved a small guide will also be helpful?
Maybe you can save traces into array, and paste it to other drawing views
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//save initial x,y into array or send it to other canvas
/*public general variable*/
String Drawing +="[[x,y]";
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
//save middle x,y into array or send it to other canvas
String Drawing +=",[x,y]";
path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
//save last point into array or send it to other canvas
String Drawing +=",[x,y]]";
path.lineTo(x, y);
drawToCanvas(path, brushPaint);
path.reset();
break;
default:
return false;
}
invalidate();
return true;
}
the string resultant should be all user traces
[[x,y],[x,y],[x,y],[x,y],[x,y]], trace 1
[[x,y],[x,y],[x,y],[x,y],[x,y]], trace 2
[[x,y],[x,y],[x,y],[x,y],[x,y]], trace 3
etc..
trace1 + trace2 +trace 3 = thing drawed by user.
when you want or maybe in real time, you can send the points drawed on this view to other view... or when users end writing send the string and extract the points...
Well it's just an idea, Hope i helped ;)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- this has changed from first answer -->
<dimen name="translation_size">30dp</dimen>
</resources>
...
int size = getResources().getDimensionPixelSize(R.dimen.translation_size);
...
private void drawToCanvas(Path path, Paint brushPaint) {
bitmapCanvas.drawPath(path, brushPaint); // just render normally
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, brushPaint);
int xMax = getWidth() / size;
int yMax = getHeight() / size;
int xMin = -xMax;
int yMin = -yMax;
for (int x = xMin; x <= xMax; x++) {
for (int y = yMin; y <= yMax; y++) {
if ((Math.abs(x % 6) == 0 && Math.abs(y % 4) == 0) ||
(Math.abs(x % 6) == 3 && Math.abs(y % 4) == 2)) {
int xs = x * size;
int ys = y * size;
canvas.translate(xs, ys);
canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
canvas.translate(-xs, -ys);
}
}
}
}
You don't have to use resources like I did, but if you hard-code a size into your app, make sure you multiply by the screen density to get the correct pixel offsets.
I'm having problem with undo and redo operations on a canvas.
I noticed the below code works if I don't use canvas.drawbitmap in the Ondraw() method but I need to draw to bitmap so I can save canvas image and as well load image. Kindly help me.
Below is my code.
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.akinslove.drawingapp.activities.DrawingCanvasActivity;
public class DrawView extends View {
// for bitmap
private Bitmap mainBitmap;
private Canvas mainCanvas;
private Paint mainbitmapPaint;
// for canvas
private Path currentPath;
private Paint currentpathPaint;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialiseMyComponents();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
initialiseMyComponents();
}
public DrawView(Context context) {
super(context);
initialiseMyComponents();
}
private void initialiseMyComponents() {
currentPath = new Path();
currentpathPaint = new Paint();
currentpathPaint.setColor(Color.BLACK);
currentpathPaint.setStrokeWidth(10);
currentpathPaint.setStyle(Style.STROKE);
currentpathPaint.setStrokeJoin(Join.ROUND);
currentpathPaint.setStrokeCap(Cap.ROUND);
currentpathPaint.setAntiAlias(true);
mainbitmapPaint = new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
for (Path p : paths){
canvas.drawPath(p, currentpathPaint);
}
canvas.drawPath(currentPath, currentpathPaint);
**//I wish to use the below line of code
canvas.drawBitmap(mainBitmap, 0, 0, mainbitmapPaint);**
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (mainBitmap == null) {
mainBitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
mainCanvas = new Canvas(mainBitmap);
mainCanvas.drawColor(Color.WHITE);
}
}
float lastX;
float lastY;
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
float x = event.getX();
float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
undonePaths.clear();
DrawingCanvasActivity.IMAGEDRAWN = true;
currentPath.moveTo(x, y);
lastX = x;
lastY = y;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
currentPath.quadTo(lastX, lastY, (lastX + x) / 2, (lastY + y) / 2);
mainCanvas.drawPath(currentPath, currentpathPaint);
lastX = x;
lastY = y;
invalidate();
break;
case MotionEvent.ACTION_UP:
currentPath.lineTo(x, y);
mainCanvas.drawPath(currentPath, currentpathPaint);
// kill this so we don't double draw
paths.add(currentPath);
currentPath = new Path();
currentPath.rewind();
invalidate();
break;
}
return true;
}
// method to get bitmap
public Bitmap getMainBitmap() {
return mainBitmap;
}
// method to set bitmap
public void setMainBitmap(Bitmap mpt) {
mainBitmap = mpt;
mainCanvas = new Canvas(mainBitmap);
postInvalidate();
}
public void onClickUndo () {
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
}
public void onClickRedo (){
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
}
}
I just found out that the line mainCanvas.drawPath(currentPath, currentpathPaint); at both case MotionEvent.ACTION_UP: and case MotionEvent.ACTION_MOVE: should not be there. It seems to redraw the path to bitmap and onto the canvas. Not sure if I speak the right android terms.
I am new to 2d graphics..
I create a text using drawText method.
I have to paint over the drawtext area..
how can i clip the area of the text and paint over the surface
package com.example.testingcanvas;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends Activity {
class MyCustomView extends View {
private float x = 0, y = 0;
Path path = new Path();
Paint paint = new Paint();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ii);
private Rect m_ImageRect;
private Rect m_TextRect;
Context m_Context;
// you need these constructor
// you can init paint object or anything on them
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
m_Context = context;
}
public MyCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
m_Context = context;
}
public MyCustomView(Context context) {
super(context);
m_Context = context;
}
// then override on draw method
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(3);
paint.setTextSize(100);
// here frist create two rectangle
// one for your image and two for text you want draw on it
m_ImageRect = canvas.getClipBounds();
m_TextRect = canvas.getClipBounds();
// it gives you an area that can draw on it,
// the width and height of your rect depend on your screen size
// device
canvas.save();
canvas.drawBitmap(bm, null, m_ImageRect, paint);
canvas.drawPath(path, paint);
canvas.restore();
canvas.save();
canvas.clipRect(m_TextRect);
canvas.drawText("A", 100, 300, paint);
// canvas.drawText("A", 20, 20,50,50, paint);
// canvas.restore();
}
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
path.lineTo(x, y);
break;
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_UP: {
}
default:
}
invalidate();
return true;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyCustomView(this));
}
public void onBackPressed() {
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
finish();
onDestroy();
}
}
i am trying to draw over the text area.but i cant get it.
i m trying to implement freehand crop in android using canvas. i use drawPath and store it in List and draw it in canvas path drawing ok,
like this
but now i want to make all pixel in that path in side area with this code but i dont no how to do it..
public Bitmap getBitmapWithTransparentBG(Bitmap srcBitmap)
{
Bitmap result = srcBitmap.copy(Bitmap.Config.ARGB_8888, true);
int nWidth = result.getWidth();
int nHeight = result.getHeight();
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
for (int i = 0; i < points.size() ; i++)
{
}
result.setPixel(x, y, Color.TRANSPARENT);
}
}
return result;
}
points is list of path coordinate hear is code for draw path
package com.org;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class SomeView extends View implements OnTouchListener {
private Paint paint;
List<Point> points;
int DIST = 2;
boolean flgPathDraw = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.waterlilies);
public SomeView(Context c ) {
super(c);
setFocusable(true);
setFocusableInTouchMode(true);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
this.setOnTouchListener(this);
points = new ArrayList<Point>();
}
public SomeView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
this.setOnTouchListener(this);
points = new ArrayList<Point>();
}
public void onDraw(Canvas canvas)
{
canvas.drawBitmap(bitmap, 0, 0, null);
Path path = new Path();
boolean first = true;
for (int i = 0; i < points.size(); i += 2)
{
Point point = points.get(i);
if (first) {
first = false;
path.moveTo(point.x, point.y);
} else if (i < points.size() - 1) {
Point next = points.get(i + 1);
path.quadTo(point.x, point.y, next.x, next.y);
} else {
path.lineTo(point.x, point.y);
}
}
canvas.drawPath(path, paint);
}
public boolean onTouch(View view, MotionEvent event) {
// if(event.getAction() != MotionEvent.ACTION_DOWN)
// return super.onTouchEvent(event);
Point point = new Point();
point.x = (int) event.getX();
point.y = (int) event.getY();
if (flgPathDraw) {
points.add(point);
}
invalidate();
Log.e("Hi ==>", "Size: " + points.size());
return true;
}
public void fillinPartofPath()
{
Point point = new Point();
point.x = points.get(0).x;
point.y = points.get(0).y;
points.add(point);
invalidate();
}
public void resetView()
{
points.clear();
paint.setColor(Color.WHITE);
paint.setStyle(Style.STROKE);
flgPathDraw=true;
invalidate();
}
}
class Point {
public float dy;
public float dx;
float x, y;
#Override
public String toString() {
return x + ", " + y;
}
}
Hi i think below link for your exact solution, what u try?
Android: Free Croping of Image
Don't forget to put your vote and feedback here.
Lets look at a bit more complex example:
The red point is the point you want to test. You have to find the edges that cross the y coordinate of the red point. In this example 4 edges cross the y coordinate (the blue points).
Now test how much intersections you get on the left side and on the right side of the point you want to check. If there is an odd number of intersections on both sides the point is inside the shape.
update: you can find a more detailed description of this algorithm here
You can use Canvas.clipPath to draw only cropped region. But be awared that this method doesn't work with hardware acceleration so you have to turn it off and use software rendering.