Related
What i have: Using the below code i am able to draw a pattern(Ex: Line) in the canvas.
What i am planning to do Or How to do this: I am trying to plot dots on that pattern in a uniform distance. (Hope i am clear)
ActDrawPaintImage.java
public class ActDrawPaintImage extends AppCompatActivity implements ColorPickerDialog.OnColorChangedListener {
MyView mv;
AlertDialog dialog;
#Bind(R.id.toolbar)
Toolbar mToolbar;
#Bind(R.id.btnNxtId)
Button btnNxtId;
private Paint mPaint;
private MaskFilter mEmboss;
private MaskFilter mBlur;
LinearLayout canvasLayoutId;
boolean mDotToDraw=false;
private int BRUSHSIZE=20;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_draw_paint_image);
//Bind the views
ButterKnife.bind(this);
initToolbar();
onClickSet();
//ADD THE VIEW WHERE THE IMAGE IS DRAWN
setTheCanvasView();
//SET BRUSH PROPERTIES
setUpBrushProperties();
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
private void onClickSet() {
btnNxtId.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mDotToDraw==false){
mDotToDraw=true;
}else{
mDotToDraw=false;
}
}
});
}
private void setTheCanvasView() {
mv= new MyView(this);
mv.setDrawingCacheEnabled(true);
canvasLayoutId=(LinearLayout) findViewById(R.id.canvasLayoutId);
canvasLayoutId.addView(mv);
}
private void setUpBrushProperties() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(ContextCompat.getColor(ActDrawPaintImage.this, R.color.pattern_color));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(BRUSHSIZE);
}
private void initToolbar() {
setSupportActionBar(mToolbar);
setTitle(getString(R.string.app_name));
mToolbar.setTitleTextColor(ContextCompat.getColor(ActDrawPaintImage.this, R.color.white));
}
public void colorChanged(int color) {
mPaint.setColor(color);
}
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
Context context;
private int width;
private int height;
public MyView(Context c) {
super(c);
context=c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width=w;
height=h;
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
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);
// kill this so we don't double draw
mPath.reset();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
//mPaint.setMaskFilter(null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
//Create a pointer and log the output
Log.d("POINTS", x + "," + y);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(mDotToDraw==false){
touch_start(x, y);
}else{
touch_draw_circle(x, y);
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
if(mDotToDraw==false){
touch_move(x, y);
}else{
}
invalidate();
break;
case MotionEvent.ACTION_UP:
if(mDotToDraw==false){
touch_up();
}else{
}
invalidate();
break;
}
return true;
}
private void touch_draw_circle(float x, float y) {
/*int radius;
radius = 30;
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
mCanvas.drawPaint(paint);
// Use Color.parseColor to define HTML colors
paint.setColor(Color.parseColor("#FF0000"));
mCanvas.drawCircle(x / 2, y / 2, radius, paint);*/
// mPath.quadTo(x, y, x + 0.1f, y);
/*Paint mPaint = new Paint();*/
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(ContextCompat.getColor(ActDrawPaintImage.this, R.color.white));
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(BRUSHSIZE);
mPath.addCircle(x, y, mPaint.getStrokeWidth()/4f, Path.Direction.CW);
}
public void clear()
{
mBitmap = Bitmap.createBitmap(width,height , Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
invalidate();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.draw_paint_image, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
switch (item.getItemId()) {
case R.id.COLOR_MENU_ID:
new ColorPickerDialog(this, this, mPaint.getColor()).show();
return true;
case R.id.EMBOSS_MENU_ID:
if (mPaint.getMaskFilter() != mEmboss) {
mPaint.setMaskFilter(mEmboss);
} else {
mPaint.setMaskFilter(null);
}
return true;
case R.id.BLUR_MENU_ID:
if (mPaint.getMaskFilter() != mBlur) {
mPaint.setMaskFilter(mBlur);
} else {
mPaint.setMaskFilter(null);
}
return true;
case R.id.ERASE_MENU_ID:
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaint.setAlpha(0x80);
return true;
case R.id.Clear:
mv.clear();
return true;
case R.id.Save:
AlertDialog.Builder editalert = new AlertDialog.Builder(ActDrawPaintImage.this);
editalert.setTitle("Please Enter the name with which you want to Save");
final EditText input = new EditText(ActDrawPaintImage.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
input.setLayoutParams(lp);
editalert.setView(input);
editalert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String name= input.getText().toString();
Bitmap bitmap = mv.getDrawingCache();
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File("/sdcard/"+name+".png");
try
{
if(!file.exists())
{
file.createNewFile();
}
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 10, ostream);
ostream.close();
mv.invalidate();
}
catch (Exception e)
{
e.printStackTrace();
}finally
{
mv.setDrawingCacheEnabled(false);
}
}
});
editalert.show();
return true;
}
return super.onOptionsItemSelected(item);
}
}
EDIT
public class ActDrawPaintImage extends AppCompatActivity implements ColorPickerDialog.OnColorChangedListener {
MyView mv;
AlertDialog dialog;
#Bind(R.id.toolbar)
Toolbar mToolbar;
#Bind(R.id.btnNxtId)
Button btnNxtId;
private Paint mPaint;
private MaskFilter mEmboss;
private MaskFilter mBlur;
LinearLayout canvasLayoutId;
boolean mDotToDraw=false;
private int BRUSHSIZE=20;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_draw_paint_image);
//Bind the views
ButterKnife.bind(this);
initToolbar();
onClickSet();
//ADD THE VIEW WHERE THE IMAGE IS DRAWN
setTheCanvasView();
//SET BRUSH PROPERTIES
setUpBrushProperties();
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
private void onClickSet() {
btnNxtId.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mDotToDraw==false){
mDotToDraw=true;
}else{
mDotToDraw=false;
}
}
});
}
private void setTheCanvasView() {
mv= new MyView(this);
mv.setDrawingCacheEnabled(true);
canvasLayoutId=(LinearLayout) findViewById(R.id.canvasLayoutId);
canvasLayoutId.addView(mv);
}
private void setUpBrushProperties() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(ContextCompat.getColor(ActDrawPaintImage.this, R.color.pattern_color));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(BRUSHSIZE);
}
private void initToolbar() {
setSupportActionBar(mToolbar);
setTitle(getString(R.string.app_name));
mToolbar.setTitleTextColor(ContextCompat.getColor(ActDrawPaintImage.this, R.color.white));
}
public void colorChanged(int color) {
mPaint.setColor(color);
}
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
Context context;
private int width;
private int height;
PathMeasure pathMeasure;
float[] position = new float[2];
float[] slope = new float[2]; // slope will give you the tangent of the position on the path. Not sure if you need this.
public MyView(Context c) {
super(c);
context=c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
pathMeasure = new PathMeasure(mPath, false);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width=w;
height=h;
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
drawPlotPoints(canvas); // you should be able to implement this alone. It should draw a dot at a given x/y.
canvas.drawPath(mPath, mPaint);
}
private void drawPlotPoints(Canvas canvas) {
int amountOfPoints = (int)(pathMeasure.getLength() / 120f);
for (float distance = 0; distance <= 1; distance += 1f / amountOfPoints) {
pathMeasure.getPosTan(distance, position, slope);
touch_draw_circle(position[0], position[1]);
}
}
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;
}
//drawPlotPoints(x,y);
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
//mPaint.setMaskFilter(null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
//Create a pointer and log the output
//Log.d("POINTS", x + "," + y);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(mDotToDraw==false){
touch_start(x, y);
}else{
touch_draw_circle(x, y);
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
if(mDotToDraw==false){
touch_move(x, y);
}else{
}
invalidate();
break;
case MotionEvent.ACTION_UP:
if(mDotToDraw==false){
touch_up();
}else{
}
invalidate();
break;
}
return true;
}
private void touch_draw_circle(float x, float y) {
/*int radius;
radius = 30;
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
mCanvas.drawPaint(paint);
// Use Color.parseColor to define HTML colors
paint.setColor(Color.parseColor("#FF0000"));
mCanvas.drawCircle(x / 2, y / 2, radius, paint);*/
// mPath.quadTo(x, y, x + 0.1f, y);
/*Paint mPaint = new Paint();*/
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(ContextCompat.getColor(ActDrawPaintImage.this, R.color.white));
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(BRUSHSIZE);
mPath.addCircle(x, y, mPaint.getStrokeWidth()/4f, Path.Direction.CW);
}
public void clear()
{
mBitmap = Bitmap.createBitmap(width,height , Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
invalidate();
}
}
}
I am getting output as below:
I am trying to get output as like this:
If I understood you correctly, you're trying to discover certain positions on a given path, then draw dots on them where the distance between each dot should be the same.
You can achieve this using a PathMeasure object. Example:
boolean forceClose = false; //(set to true if you want to close the path or leave it open).
PathMeasure pathMeasure = new PathMeasure(path, forceClose);
float[] position = new float[2];
float[] slope = new float[2]; // slope will give you the tangent of the position on the path. Not sure if you need this.
for (float distance = 0; distance <= 1; distance += 1f / AMOUNT_OF_POINTS) {
pathMeasure.getPosTan(distance, position, slope);
drawDotAtPosition(position[0], position[1]); // you should be able to implement this alone. It should draw a dot at a given x/y.
}
The getPosTan method will give you the position on a given path after a certain ratio of the length has passed. This ratio is defined by AMOUNT_OF_POINTS which you can set to anything for a constant amount of points no matter what the length of the path is, or you could calculate it according to the length of the path:
// this will produce an amount of points equal to 1 point per 10 pixels along the whole path
int amountOfPoints = (int)(pathMeasure.getLength() / 10f);
Hope this helps.
I made this a while back, its not exactly my best work but it worked at the time. Maybe you can use it as a reference.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
public class line_graph extends View
{
private int padding = 0;
private int width = 0;//this is automatically
private int height = 0;
private Paint paint = new Paint();
private String[] labels;// labels for each column
private int[][] values;// values for each column
private String[] labelsHeadings;// headings for each segment of data
private float xInterval = 0;//space between x grid lines
private float yInterval = 0;//space between y grid lines
private int RowLineCount = 0; // amount of y grid lines
private float scale = 1; // this is automatically set according to the screen density
private int labelSpaceLeft = 0;// space on the left for labels
private int labelSpaceBottom = 0;// space on the bottom for labels
private int keySpace = 0;// space on the bottom for the key
private Path path = new Path();// bothe these paths are used for the shaded effect on the line graph
private Path path2 = new Path();
public line_graph(Context context)
{
this(context, null, 0);
}
public line_graph(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public line_graph(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
if(isInEditMode())
return;
scale = context.getResources().getDisplayMetrics().density;
labelSpaceLeft = (int)(40 * scale);
labelSpaceBottom = (int)(85 * scale);
keySpace = (int)(40 * scale);
}
public void setup(String[] labels, int[][] values, String[] labelsHeadings, int padding)
{
this.labels = labels;
this.values = values;
this.padding = padding;
this.labelsHeadings = labelsHeadings;
invalidate();
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
width = xNew;
height = yNew;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode())
return;
try {
paint.reset();
paint.setAntiAlias(true);
paint.setTextSize(16);
paint.setTextAlign(Paint.Align.RIGHT);
int maxValue = 0;
for (int i = 0; i < values.length; i++) {
for (int j = 0; j < values[i].length; j++) {
maxValue = Math.max(maxValue, values[i][j]);
}
}
float innerWidth = width - padding * 2 - labelSpaceLeft;
float innerHeight = height - padding * 2 - labelSpaceBottom - keySpace;
float lx = padding;
paint.setTextAlign(Paint.Align.LEFT);
for (int i = 0; i < values.length; i++) {
paint.setColor(getNextColour(i));
//calculate space for circles
lx += 15 * scale;
//calculate space key label
if (labelsHeadings.length > i) {
lx += padding + paint.measureText(labelsHeadings[i]);
if (i < values.length - 1 && lx + paint.measureText(labelsHeadings[i + 1]) > width) {
lx = padding + labelSpaceLeft;
innerHeight += paint.ascent();
}
}
}
lx = padding + labelSpaceLeft;
float ly = innerHeight + padding*2 + labelSpaceBottom;
paint.setTextAlign(Paint.Align.LEFT);
for (int i = 0; i < values.length; i++) {
paint.setColor(getNextColour(i));
//draw circles
canvas.drawOval(new RectF(lx - 5 * scale, ly - 5 * scale, lx + 5 * scale, ly + 5 * scale), paint);
lx += 15 * scale;
//draw key label
canvas.drawText(labelsHeadings[i], lx, ly - paint.ascent() / 2, paint);
if (labelsHeadings.length > i) {
lx += padding + paint.measureText(labelsHeadings[i]);
if (i < values.length - 1 && lx + paint.measureText(labelsHeadings[i + 1]) > width) {
lx = padding + labelSpaceLeft;
ly -= paint.ascent();
innerHeight += paint.ascent();
}
}
}
xInterval = innerWidth / (labels.length-1);
RowLineCount = (int) Math.min(Math.max(innerHeight / Math.ceil(40 * scale), 2), maxValue/2);
yInterval = innerHeight / RowLineCount;
int currentValue = maxValue;
float y;
paint.setTextAlign(Paint.Align.RIGHT);
for (int i = 0; i < RowLineCount+1; i++) {
//draw left label
y = yInterval * i + padding;
paint.setColor(0xffaaaaaa);
canvas.drawText(String.valueOf(currentValue), labelSpaceLeft, y - paint.ascent()/2, paint);
currentValue = Math.max(currentValue - maxValue/RowLineCount,0);
//draw x grid line
paint.setColor(0xffeeeeee);
canvas.drawLine(padding + labelSpaceLeft, y, innerWidth + padding + labelSpaceLeft, y, paint);
}
float x;
for (int i = 0; i < labels.length; i++) {
//draw bottom label rotated
x = xInterval * i + padding + labelSpaceLeft;
if(i != labels.length) {
canvas.save();
canvas.rotate(300, x, innerHeight + padding*2 - paint.ascent()/2);
paint.setColor(0xffaaaaaa);
canvas.drawText(labels[i], x, innerHeight + padding*2 - paint.ascent()/2, paint);
canvas.restore();
}
//draw y grid line
paint.setColor(0xffeeeeee);
canvas.drawLine(x, padding, x, innerHeight + padding, paint);
}
paint.setStyle(Paint.Style.FILL);
for (int i = 0; i < values.length; i++) {
paint.setColor(getNextColour(i));
path.rewind();
path2.rewind();
for (int j = 0; j < values[i].length; j++)
{
x = xInterval * j + padding + labelSpaceLeft;
y = innerHeight + padding - (innerHeight * values[i][j] / maxValue);
//draw lines
if(j == 0) {
path2.moveTo(padding + labelSpaceLeft, innerHeight + padding);
path.moveTo(x, y);
}
else
path.lineTo(x,y);
path2.lineTo(x, y);
//canvas.drawLine(xOld,yOld,x,y,paint);
//draw circles
canvas.drawOval(new RectF(x - 5 * scale, y - 5 * scale, x + 5 * scale, y + 5 * scale), paint);
}
//draw line
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
canvas.drawPath(path, paint);
//draw shaded area
path2.lineTo(innerWidth + padding + labelSpaceLeft, innerHeight + padding);
paint.setARGB(20, Color.red(paint.getColor()), Color.green(paint.getColor()), Color.blue(paint.getColor()));
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path2, paint);
}
}
catch (Exception ignored){}
}
//used to get the next color in the series
public static int getNextColour(int index)
{
int[] colours = new int[]{0xFF4CAF50,
0xFF9C27B0,
0xFFF44336,
0xFF00BCD4,
0xFFE91E63,
0xFF03A9F4,
0xFFFF9800,
//0xFFFFEB3B,//removed bright yellow
0xFF9E9E9E,
0xFF795548,
0xFF8BC34A,
0xFF607D8B,
0xFF009688,
0xFFFFC107,
0xFF673AB7,
0xFF2196F3,
0xFFCDDC39,
0xFF3F51B5,
0xFFFF5722};
return colours[index % colours.length];
}
}
its used like this:
line_graph graph = (line_graph)findViewById(R.id.lineGraph);
graph.setup(
//labels
new String[]{"heading1","heading2","heading3","heading4","heading5","heading6","heading7"},
//Values
new int[][]{new int[]{1,4,8,2,5,9,12},new int[]{2,5,2,8,5,2,6},new int[]{8,2,9,23,7,1,11}},
//Series Headings
new String[]{"Series 1", "Series 2", "Series 3"},
//Padding
20);
xml:
<line_graph
android:id="#+id/lineGraph"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
it looks like this:
And yes i do realize this could be made better and that it had poor exception handling. But its just an example.
I have an imageview which is populated using gallery pic. Now after loading the image I want the user to be able to draw over the image. How can this be achieved? I am pretty new to android any pointers will help.
Thanks
Use the fingerpaint api and set the image as background to the customview and draw.
After you get the path of image selected.
customview.setBackground(yourdrawable);
You can use the menu buton to choose options. Choose the gallery to get the image form the gallery and set it as a background to your view.
You can use color picker to choose the color of draw.
Complete Sample
public class MainActivity extends Activity
implements ColorPickerDialog.OnColorChangedListener {
MyView mv;
Drawable d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mv = new MyView(this);
setContentView(mv);
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(12);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
private Paint mPaint;
private MaskFilter mEmboss;
private MaskFilter mBlur;
public void colorChanged(int color) {
mPaint.setColor(color);
}
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath,circlePath;
private Paint mBitmapPaint,circlePaint;
public MyView(Context c) {
super(c);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#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
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(circlePath, circlePaint);
}
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;
}
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
circlePath.reset();
mPath.reset();
}
#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;
}
}
private static final int COLOR_MENU_ID = Menu.FIRST;
private static final int EMBOSS_MENU_ID = Menu.FIRST + 1;
private static final int BLUR_MENU_ID = Menu.FIRST + 2;
private static final int ERASE_MENU_ID = Menu.FIRST + 3;
private static final int SRCATOP_MENU_ID = Menu.FIRST + 4;
private static final int Image_gallery= Menu.FIRST + 5;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('3', 'c');
menu.add(0, EMBOSS_MENU_ID, 0, "Emboss").setShortcut('4', 's');
menu.add(0, BLUR_MENU_ID, 0, "Blur").setShortcut('5', 'z');
menu.add(0, ERASE_MENU_ID, 0, "Erase").setShortcut('5', 'z');
menu.add(0, SRCATOP_MENU_ID, 0, "SrcATop").setShortcut('5', 'z');
menu.add(0, Image_gallery, 0, "Gallery").setShortcut('5', 'z');
/**** Is this the mechanism to extend with filter effects?
Intent intent = new Intent(null, getIntent().getData());
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
menu.addIntentOptions(
Menu.ALTERNATIVE, 0,
new ComponentName(this, NotesList.class),
null, intent, 0, null);
*****/
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
switch (item.getItemId()) {
case COLOR_MENU_ID:
new ColorPickerDialog(this, this, mPaint.getColor()).show();
return true;
case EMBOSS_MENU_ID:
if (mPaint.getMaskFilter() != mEmboss) {
mPaint.setMaskFilter(mEmboss);
} else {
mPaint.setMaskFilter(null);
}
return true;
case BLUR_MENU_ID:
if (mPaint.getMaskFilter() != mBlur) {
mPaint.setMaskFilter(mBlur);
} else {
mPaint.setMaskFilter(null);
}
return true;
case ERASE_MENU_ID:
mPaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.CLEAR));
return true;
case SRCATOP_MENU_ID:
mPaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.SRC_ATOP));
mPaint.setAlpha(0x80);
return true;
case Image_gallery:
setDrawingThemefrmGallery();
return true;
}
return super.onOptionsItemSelected(item);
}
public void setDrawingThemefrmGallery()
{
// 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()) {
d = Drawable.createFromPath(file.getAbsolutePath());
//mv.setBackgroundDrawable(d);
mv.setBackground(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[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(contentUri,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
return picturePath ;
}
}
ColorPickerDialog
public class ColorPickerDialog extends Dialog {
public interface OnColorChangedListener {
void colorChanged(int color);
}
private OnColorChangedListener mListener;
private int mInitialColor;
private static class ColorPickerView extends View {
private Paint mPaint;
private Paint mCenterPaint;
private final int[] mColors;
private OnColorChangedListener mListener;
ColorPickerView(Context c, OnColorChangedListener l, int color) {
super(c);
mListener = l;
mColors = new int[] {
0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, 0xFF00FF00,
0xFFFFFF00, 0xFFFF0000
};
Shader s = new SweepGradient(0, 0, mColors, null);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(s);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(32);
mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCenterPaint.setColor(color);
mCenterPaint.setStrokeWidth(5);
}
private boolean mTrackingCenter;
private boolean mHighlightCenter;
#Override
protected void onDraw(Canvas canvas) {
float r = CENTER_X - mPaint.getStrokeWidth()*0.5f;
canvas.translate(CENTER_X, CENTER_X);
canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint);
if (mTrackingCenter) {
int c = mCenterPaint.getColor();
mCenterPaint.setStyle(Paint.Style.STROKE);
if (mHighlightCenter) {
mCenterPaint.setAlpha(0xFF);
} else {
mCenterPaint.setAlpha(0x80);
}
canvas.drawCircle(0, 0,
CENTER_RADIUS + mCenterPaint.getStrokeWidth(),
mCenterPaint);
mCenterPaint.setStyle(Paint.Style.FILL);
mCenterPaint.setColor(c);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
}
private static final int CENTER_X = 100;
private static final int CENTER_Y = 100;
private static final int CENTER_RADIUS = 32;
private int floatToByte(float x) {
int n = java.lang.Math.round(x);
return n;
}
private int pinToByte(int n) {
if (n < 0) {
n = 0;
} else if (n > 255) {
n = 255;
}
return n;
}
private int ave(int s, int d, float p) {
return s + java.lang.Math.round(p * (d - s));
}
private int interpColor(int colors[], float unit) {
if (unit <= 0) {
return colors[0];
}
if (unit >= 1) {
return colors[colors.length - 1];
}
float p = unit * (colors.length - 1);
int i = (int)p;
p -= i;
// now p is just the fractional part [0...1) and i is the index
int c0 = colors[i];
int c1 = colors[i+1];
int a = ave(Color.alpha(c0), Color.alpha(c1), p);
int r = ave(Color.red(c0), Color.red(c1), p);
int g = ave(Color.green(c0), Color.green(c1), p);
int b = ave(Color.blue(c0), Color.blue(c1), p);
return Color.argb(a, r, g, b);
}
private int rotateColor(int color, float rad) {
float deg = rad * 180 / 3.1415927f;
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
ColorMatrix cm = new ColorMatrix();
ColorMatrix tmp = new ColorMatrix();
cm.setRGB2YUV();
tmp.setRotate(0, deg);
cm.postConcat(tmp);
tmp.setYUV2RGB();
cm.postConcat(tmp);
final float[] a = cm.getArray();
int ir = floatToByte(a[0] * r + a[1] * g + a[2] * b);
int ig = floatToByte(a[5] * r + a[6] * g + a[7] * b);
int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b);
return Color.argb(Color.alpha(color), pinToByte(ir),
pinToByte(ig), pinToByte(ib));
}
private static final float PI = 3.1415926f;
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX() - CENTER_X;
float y = event.getY() - CENTER_Y;
boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTrackingCenter = inCenter;
if (inCenter) {
mHighlightCenter = true;
invalidate();
break;
}
case MotionEvent.ACTION_MOVE:
if (mTrackingCenter) {
if (mHighlightCenter != inCenter) {
mHighlightCenter = inCenter;
invalidate();
}
} else {
float angle = (float)java.lang.Math.atan2(y, x);
// need to turn angle [-PI ... PI] into unit [0....1]
float unit = angle/(2*PI);
if (unit < 0) {
unit += 1;
}
mCenterPaint.setColor(interpColor(mColors, unit));
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (mTrackingCenter) {
if (inCenter) {
mListener.colorChanged(mCenterPaint.getColor());
}
mTrackingCenter = false; // so we draw w/o halo
invalidate();
}
break;
}
return true;
}
}
public ColorPickerDialog(Context context,
OnColorChangedListener listener,
int initialColor) {
super(context);
mListener = listener;
mInitialColor = initialColor;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnColorChangedListener l = new OnColorChangedListener() {
public void colorChanged(int color) {
mListener.colorChanged(color);
dismiss();
}
};
setContentView(new ColorPickerView(getContext(), l, mInitialColor));
setTitle("Pick a Color");
}
}
After you finish draw you can save the draw also.
Snap shot
Edit
You can also extend ImageView and override onDraw and draw over the image.
One way to do this is to make a custom view extending the ImageView class to allow it to be drawn over. You would override the onTouchEvent to read touch input and store it into an data structure (perhaps a Path if you just want to draw simple lines). You would override onDraw to first call onDraw in the parent class (to draw the image) and then to draw the user input from your stored data.
Here are some things you might want to read that discuss how you would implement my suggestions.
Custom components
Canvas and Drawables
Good luck!
I am making an application I am unable to one issue last 3 days doing google as much possible.I make a circle on canvas and want to crop image that part and show that image in zoom mode.My first step is like in screen here:-
in this I am selecting area.here is my code used by me for this.
private float x, y;
private boolean zooming = false;
private Paint mPaint;
private Matrix mmatrix;
private Shader mShader;
private Bitmap mBitmap;
private List<Point> mpoints;
private List<MyPoints> mpointlist;
private Path mpath;
private Canvas mcanvas;
private Bitmap mresult_bitmap, resultingImage,finalbitmap;
private Context mcontext;
private boolean bfirstpoint = false;
private Point mfirstpoint = null;
private Point mlastpoint = null;
public CircularZoomView(Context context) {
super(context);
mcontext = context;
mpath = new Path();
mpoints = new ArrayList<Point>();
setBackgroundResource(R.drawable.testing);
mPaint = new Paint();
mresult_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.testing);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (zooming && resultingImage!=null) {
zooming = false;
ShowImage(resultingImage);
canvas.drawBitmap(resultingImage,mmatrix, null);
}
boolean first = true;
for (int i = 0; i < mpoints.size(); i += 2) {
Point point = mpoints.get(i);
if (first) {
first = false;
mpath.moveTo(point.x, point.y);
} else if (i < mpoints.size() - 1) {
Point next = mpoints.get(i + 1);
mpath.quadTo(point.x, point.y, next.x, next.y);
} else {
mlastpoint = mpoints.get(i);
mpath.lineTo(point.x, point.y);
}
}
canvas.drawPath(mpath, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
x = event.getX();
y = event.getY();
Point point = new Point();
point.x = (int) event.getX();
point.y = (int) event.getY();
if (bfirstpoint) {
if (comparepoint(mfirstpoint, point)) {
mpoints.add(mfirstpoint);
addCircleFromPath(mpath);
} else {
mpoints.add(point);
}
} else {
mpoints.add(point);
}
if (!(bfirstpoint)) {
mfirstpoint = point;
bfirstpoint = true;
}
invalidate();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
zooming = false;
this.invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
zooming = true;
mlastpoint = point;
if (mpoints.size() > 12) {
if (!comparepoint(mfirstpoint, mlastpoint)) {
mpoints.add(mfirstpoint);
addCircleFromPath(mpath);
}
}
this.invalidate();
break;
default:
break;
}
return true;
}
public Bitmap getCroppedBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
bitmap.getWidth() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
void ShowImage(Bitmap mbitmap) {
Display display = ((MainActivity) mcontext).getWindowManager().getDefaultDisplay();
int screenWidth = display.getWidth();
float imageWidth = (float)mbitmap.getWidth();
float imageHeight = (float)mbitmap.getHeight();
float newHeight = imageHeight / (imageWidth / screenWidth);
float newWidth = screenWidth;
float scaleWidth = screenWidth / imageWidth;
float scaleHeight = newHeight / imageHeight;
SetImageMatrix(mbitmap,scaleWidth,scaleHeight);
}
void SetImageMatrix(Bitmap image,float scaleWidth, float scaleHeight) {
mmatrix = new Matrix();
mmatrix.setTranslate(40,40);
mmatrix.postScale(scaleWidth/2, scaleHeight/2);
/*image.setImageMatrix(mmatrix);
image.setScaleType(ScaleType.MATRIX);
image.invalidate();*/
}
private boolean comparepoint(Point first, Point current) {
int left_range_x = (int) (current.x - 3);
int left_range_y = (int) (current.y - 3);
int right_range_x = (int) (current.x + 3);
int right_range_y = (int) (current.y + 3);
if ((left_range_x < first.x && first.x < right_range_x)
&& (left_range_y < first.y && first.y < right_range_y)) {
if (mpoints.size() < 10) {
return false;
} else {
return true;
}
} else {
return false;
}
}
private void addCircleFromPath(Path path){
RectF bounds = new RectF();
path.computeBounds(bounds, true);
int width = (int) (bounds.right-bounds.left);
int height = (int) (bounds.bottom-bounds.top);
if(width<20 && height<20){
path.reset();
return;
}
int radius ;
if(width>=height)
radius = Math.round(((width/2)));
else radius = Math.round((int) ((height/2)));
/*CircleTagObject circle = new CircleTagObject((int)bounds.left+width/2, (int)bounds.top+height/2, radius, crossBitmap, tagBitmap,circleArray.size(),
ImageEditorView.this);
circleArray.add(circle);
tagBallID = circleArray.size() - 1;
dragEnable = true;*/
resultingImage = getCroppedBitmap(Bitmap.createBitmap(mresult_bitmap,0,0,200,200));
mcanvas = new Canvas(resultingImage);
path.reset();
resetView();
invalidate();
}
public void resetView() {
mpoints.clear();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
invalidate();
}
If I create hard coded bitmap like above its showing good but not crop bitmap of selected part.Like this image.
but when add exact coordinate of selected area Like as:-
resultingImage = getCroppedBitmap(Bitmap.createBitmap(mresult_bitmap,(int)bounds.left,(int)bounds.top,width,height));
Then exception occure:-
07-12 10:58:56.700: E/MessageQueue-JNI(12310): java.lang.IllegalArgumentException: y + height must be <= bitmap.height()
07-12 10:58:56.700: E/MessageQueue-JNI(12310): at android.graphics.Bitmap.createBitmap(Bitmap.java:565)
07-12 10:58:56.700: E/MessageQueue-JNI(12310): at android.graphics.Bitmap.createBitmap(Bitmap.java:530)
07-12 10:58:56.700: E/MessageQueue-JNI(12310): at com.intel.view.CircularZoomView.addCircleFromPath(CircularZoomView.java:237)
I know why This exception occurs but unable to find solution how crop image of selected part.Thanks in advance.
I know its too late for your solution but this may help to others Use of this code
help you to come out from this problem.
please tell me how can i remove the exception. or give me idea to implement zoom view with curlview.....
my xml file is like this,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/relat">
<com.example.image.ZoomView
>
<com.example.image.PageCurlView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/dcgpagecurlPageCurlView1"
>
</com.example.image.PageCurlView>
my java file is
package com.example.image;
public class StandaloneExample extends Activity {
Button bt;LinearLayout lr;
/** Decoded bitmap image */
private Bitmap mBitmap;
private ZoomView zoomview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.standalone_example);
View v1 = ((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.standalone_example, null, false);
v1.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
zoomview.addView(v1);
lr = (LinearLayout) findViewById(R.id.relat);
lr.addView(zoomview);
}
#Override
public void onDestroy(){
super.onDestroy();
System.gc();
finish();
}
public void lockOrientationLandscape() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
public void lockOrientationPortrait() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
public void lockOrientation( int orientation ) {
setRequestedOrientation(orientation);
}
}
i have implemented zoomView.java as described in a link
pagecurlview.java class is
public class PageCurlView extends View {
private final static String TAG = "PageCurlView";
private Paint mTextPaint;
private TextPaint mTextPaintShadow;
private int mCurlSpeed;
private int mUpdateRate;
private int mInitialEdgeOffset;
private int mCurlMode;
public static final int CURLMODE_SIMPLE = 0;
public static final int CURLMODE_DYNAMIC = 1;
private boolean bEnableDebugMode = false;
private WeakReference<Context> mContext;
private FlipAnimationHandler mAnimationHandler;
private float mFlipRadius;
private Vector2D mMovement;
private Vector2D mFinger;
private Vector2D mOldMovement;
private Paint mCurlEdgePaint;
private Vector2D mA, mB, mC, mD, mE, mF, mOldF, mOrigin;
private int mCurrentLeft, mCurrentTop;
private boolean bViewDrawn;
private boolean bFlipRight;
private boolean bFlipping;
private boolean bUserMoves;
private boolean bBlockTouchInput = false;
private boolean bEnableInputAfterDraw = false;
private Bitmap mForeground;
private Bitmap mBackground;
private ArrayList<Bitmap> mPages;
private int mIndex = 0;
private class Vector2D
{
public float x,y;
public Vector2D(float x, float y)
{
this.x = x;
this.y = y;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "("+this.x+","+this.y+")";
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public float lengthSquared() {
return (x * x) + (y * y);
}
public boolean equals(Object o) {
if (o instanceof Vector2D) {
Vector2D p = (Vector2D) o;
return p.x == x && p.y == y;
}
return false;
}
public Vector2D reverse() {
return new Vector2D(-x,-y);
}
public Vector2D sum(Vector2D b) {
return new Vector2D(x+b.x,y+b.y);
}
public Vector2D sub(Vector2D b) {
return new Vector2D(x-b.x,y-b.y);
}
public float dot(Vector2D vec) {
return (x * vec.x) + (y * vec.y);
}
public float cross(Vector2D a, Vector2D b) {
return a.cross(b);
}
public float cross(Vector2D vec) {
return x * vec.y - y * vec.x;
}
public float distanceSquared(Vector2D other) {
float dx = other.x - x;
float dy = other.y - y;
return (dx * dx) + (dy * dy);
}
public float distance(Vector2D other) {
return (float) Math.sqrt(distanceSquared(other));
}
public float dotProduct(Vector2D other) {
return other.x * x + other.y * y;
}
public Vector2D normalize() {
float magnitude = (float) Math.sqrt(dotProduct(this));
return new Vector2D(x / magnitude, y / magnitude);
}
public Vector2D mult(float scalar) {
return new Vector2D(x*scalar,y*scalar);
}
}
class FlipAnimationHandler extends Handler {
#Override
public void handleMessage(Message msg) {
PageCurlView.this.FlipAnimationStep();
}
public void sleep(long millis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), millis);
}
}
public PageCurlView(Context context) {
super(context);
init(context);
ResetClipEdge();
}
public PageCurlView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
// Get the data from the XML AttributeSet
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PageCurlView);
// Get data
bEnableDebugMode = a.getBoolean(R.styleable.PageCurlView_enableDebugMode, bEnableDebugMode);
mCurlSpeed = a.getInt(R.styleable.PageCurlView_curlSpeed, mCurlSpeed);
mUpdateRate = a.getInt(R.styleable.PageCurlView_updateRate, mUpdateRate);
mInitialEdgeOffset = a.getInt(R.styleable.PageCurlView_initialEdgeOffset, mInitialEdgeOffset);
mCurlMode = a.getInt(R.styleable.PageCurlView_curlMode, mCurlMode);
Log.i(TAG, "mCurlSpeed: " + mCurlSpeed);
Log.i(TAG, "mUpdateRate: " + mUpdateRate);
Log.i(TAG, "mInitialEdgeOffset: " + mInitialEdgeOffset);
Log.i(TAG, "mCurlMode: " + mCurlMode);
// recycle object (so it can be used by others)
a.recycle();
}
ResetClipEdge();
}
private final void init(Context context) {
// Foreground text paint
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(16);
mTextPaint.setColor(0xFF000000);
// The shadow
mTextPaintShadow = new TextPaint();
mTextPaintShadow.setAntiAlias(true);
mTextPaintShadow.setTextSize(16);
mTextPaintShadow.setColor(0x00000000);
// Cache the context
mContext = new WeakReference<Context>(context);
// Base padding
setPadding(3, 3, 3, 3);
// The focus flags are needed
setFocusable(true);
setFocusableInTouchMode(true);
mMovement = new Vector2D(0,0);
mFinger = new Vector2D(0,0);
mOldMovement = new Vector2D(0,0);
// Create our curl animation handler
mAnimationHandler = new FlipAnimationHandler();
// Create our edge paint
mCurlEdgePaint = new Paint();
mCurlEdgePaint.setColor(Color.WHITE);
mCurlEdgePaint.setAntiAlias(true);
mCurlEdgePaint.setStyle(Paint.Style.FILL);
mCurlEdgePaint.setShadowLayer(10, -5, 5, 0x99000000);
// Set the default props, those come from an XML :D
mCurlSpeed = 30;
mUpdateRate = 33;
mInitialEdgeOffset = 20;
mCurlMode = 1;
// LEGACY PAGE HANDLING!
// Create pages
mPages = new ArrayList<Bitmap>();
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.princess));
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.temp));
// Create some sample images
mForeground = mPages.get(0);
mBackground = mPages.get(1);
}
public void ResetClipEdge()
{
// Set our base movement
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
mOldMovement.x = 0;
mOldMovement.y = 0;
// Now set the points
// TODO: OK, those points MUST come from our measures and
// the actual bounds of the view!
mA = new Vector2D(mInitialEdgeOffset, 0);
mB = new Vector2D(this.getWidth(), this.getHeight());
mC = new Vector2D(this.getWidth(), 0);
mD = new Vector2D(0, 0);
mE = new Vector2D(0, 0);
mF = new Vector2D(0, 0);
mOldF = new Vector2D(0, 0);
// The movement origin point
mOrigin = new Vector2D(this.getWidth(), 0);
}
private Context GetContext() {
return mContext.get();
}
public boolean IsCurlModeDynamic()
{
return mCurlMode == CURLMODE_DYNAMIC;
}
public void SetCurlSpeed(int curlSpeed)
{
if ( curlSpeed < 1 )
throw new IllegalArgumentException("curlSpeed must be greated than 0");
mCurlSpeed = curlSpeed;
}
public int GetCurlSpeed()
{
return mCurlSpeed;
}
public void SetUpdateRate(int updateRate)
{
if ( updateRate < 1 )
throw new IllegalArgumentException("updateRate must be greated than 0");
mUpdateRate = updateRate;
}
public int GetUpdateRate()
{
return mUpdateRate;
}
public void SetInitialEdgeOffset(int initialEdgeOffset)
{
if ( initialEdgeOffset < 0 )
throw new IllegalArgumentException("initialEdgeOffset can not negative");
mInitialEdgeOffset = initialEdgeOffset;
}
public int GetInitialEdgeOffset()
{
return mInitialEdgeOffset;
}
public void SetCurlMode(int curlMode)
{
if ( curlMode != CURLMODE_SIMPLE &&
curlMode != CURLMODE_DYNAMIC )
throw new IllegalArgumentException("Invalid curlMode");
mCurlMode = curlMode;
}
public int GetCurlMode()
{
return mCurlMode;
}
public void SetEnableDebugMode(boolean bFlag)
{
bEnableDebugMode = bFlag;
}
public boolean IsDebugModeEnabled()
{
return bEnableDebugMode;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int finalWidth, finalHeight;
finalWidth = measureWidth(widthMeasureSpec);
finalHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension(finalWidth, finalHeight);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = specSize;
}
return result;
}
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = specSize;
}
return result;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!bBlockTouchInput) {
// Get our finger position
mFinger.x = event.getX();
mFinger.y = event.getY();
int width = getWidth();
// Depending on the action do what we need to
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// If we moved over the half of the display flip to next
if (mOldMovement.x > (width >> 1)) {
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
// Set the right movement flag
bFlipRight = true;
} else {
// Set the left movement flag
bFlipRight = false;
// go to next previous page
previousView();
// Set new movement
mMovement.x = IsCurlModeDynamic()?width<<1:width;
mMovement.y = mInitialEdgeOffset;
}
break;
case MotionEvent.ACTION_UP:
bUserMoves=false;
bFlipping=true;
FlipAnimationStep();
break;
case MotionEvent.ACTION_MOVE:
bUserMoves=true;
// Get movement
mMovement.x -= mFinger.x - mOldMovement.x;
mMovement.y -= mFinger.y - mOldMovement.y;
mMovement = CapMovement(mMovement, true);
// Make sure the y value get's locked at a nice level
if ( mMovement.y <= 1 )
mMovement.y = 1;
// Get movement direction
if (mFinger.x < mOldMovement.x ) {
bFlipRight = true;
} else {
bFlipRight = false;
}
// Save old movement values
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// Force a new draw call
DoPageCurl();
this.invalidate();
break;
}
}
// TODO: Only consume event if we need to.
return true;
}
private Vector2D CapMovement(Vector2D point, boolean bMaintainMoveDir)
{
// Make sure we never ever move too much
if (point.distance(mOrigin) > mFlipRadius)
{
if ( bMaintainMoveDir )
{
// Maintain the direction
point = mOrigin.sum(point.sub(mOrigin).normalize().mult(mFlipRadius));
}
else
{
// Change direction
if ( point.x > (mOrigin.x+mFlipRadius))
point.x = (mOrigin.x+mFlipRadius);
else if ( point.x < (mOrigin.x-mFlipRadius) )
point.x = (mOrigin.x-mFlipRadius);
point.y = (float) (Math.sin(Math.acos(Math.abs(point.x-mOrigin.x)/mFlipRadius))*mFlipRadius);
}
}
return point;
}
public void FlipAnimationStep() {
if ( !bFlipping )
return;
int width = getWidth();
// No input when flipping
bBlockTouchInput = true;
// Handle speed
float curlSpeed = mCurlSpeed;
if ( !bFlipRight )
curlSpeed *= -1;
// Move us
mMovement.x += curlSpeed;
mMovement = CapMovement(mMovement, false);
// Create values
DoPageCurl();
// Check for endings :D
if (mA.x < 1 || mA.x > width - 1) {
bFlipping = false;
if (bFlipRight) {
//SwapViews();
nextView();
}
ResetClipEdge();
// Create values
DoPageCurl();
// Enable touch input after the next draw event
bEnableInputAfterDraw = true;
}
else
{
mAnimationHandler.sleep(mUpdateRate);
}
// Force a new draw call
this.invalidate();
}
private void DoPageCurl()
{
if(bFlipping){
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
} else {
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
}
}
private void doSimpleCurl() {
int width = getWidth();
int height = getHeight();
// Calculate point A
mA.x = width - mMovement.x;
mA.y = height;
// Calculate point D
mD.x = 0;
mD.y = 0;
if (mA.x > width / 2) {
mD.x = width;
mD.y = height - (width - mA.x) * height / mA.x;
} else {
mD.x = 2 * mA.x;
mD.y = 0;
}
double angle = Math.atan((height - mD.y) / (mD.x + mMovement.x - width));
double _cos = Math.cos(2 * angle);
double _sin = Math.sin(2 * angle);
mF.x = (float) (width - mMovement.x + _cos * mMovement.x);
mF.y = (float) (height - _sin * mMovement.x);
// If the x position of A is above half of the page we are still not
// folding the upper-right edge and so E and D are equal.
if (mA.x > width / 2) {
mE.x = mD.x;
mE.y = mD.y;
}
else
{
// So get E
mE.x = (float) (mD.x + _cos * (width - mD.x));
mE.y = (float) -(_sin * (width - mD.x));
}
}
private void doDynamicCurl() {
int width = getWidth();
int height = getHeight();
mF.x = width - mMovement.x+0.1f;
mF.y = height - mMovement.y+0.1f;
if(mA.x==0) {
mF.x= Math.min(mF.x, mOldF.x);
mF.y= Math.max(mF.y, mOldF.y);
}
// Get diffs
float deltaX = width-mF.x;
float deltaY = height-mF.y;
float BH = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2);
double tangAlpha = deltaY / deltaX;
double alpha = Math.atan(deltaY / deltaX);
double _cos = Math.cos(alpha);
double _sin = Math.sin(alpha);
mA.x = (float) (width - (BH / _cos));
mA.y = height;
mD.y = (float) (height - (BH / _sin));
mD.x = width;
mA.x = Math.max(0,mA.x);
if(mA.x==0) {
mOldF.x = mF.x;
mOldF.y = mF.y;
}
// Get W
mE.x = mD.x;
mE.y = mD.y;
// Correct
if (mD.y < 0) {
mD.x = width + (float) (tangAlpha * mD.y);
mE.y = 0;
mE.x = width + (float) (Math.tan(2 * alpha) * mD.y);
}
}
#Deprecated
private void SwapViews() {
Bitmap temp = mForeground;
mForeground = mBackground;
mBackground = temp;
}
private void nextView() {
int foreIndex = mIndex + 1;
if(foreIndex >= mPages.size()) {
foreIndex = 0;
}
int backIndex = foreIndex + 1;
if(backIndex >= mPages.size()) {
backIndex = 0;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void previousView() {
int backIndex = mIndex;
int foreIndex = backIndex - 1;
if(foreIndex < 0) {
foreIndex = mPages.size()-1;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void setViews(int foreground, int background) {
mForeground = mPages.get(foreground);
mBackground = mPages.get(background);
}
#Override
protected void onDraw(Canvas canvas) {
mCurrentLeft = getLeft();
mCurrentTop = getTop();
if ( !bViewDrawn ) {
bViewDrawn = true;
onFirstDrawEvent(canvas);
}
canvas.drawColor(Color.WHITE);
Rect rect = new Rect();
rect.left = 0;
rect.top = 0;
rect.bottom = getHeight();
rect.right = getWidth();
// First Page render
Paint paint = new Paint();
// Draw our elements
drawForeground(canvas, rect, paint);
drawBackground(canvas, rect, paint);
drawCurlEdge(canvas);
// Draw any debug info once we are done
if ( bEnableDebugMode )
drawDebug(canvas);
// Check if we can re-enable input
if ( bEnableInputAfterDraw )
{
bBlockTouchInput = false;
bEnableInputAfterDraw = false;
}
// Restore canvas
//canvas.restore();
}
protected void onFirstDrawEvent(Canvas canvas) {
mFlipRadius = getWidth();
ResetClipEdge();
DoPageCurl();
}
private void drawForeground( Canvas canvas, Rect rect, Paint paint ) {
canvas.drawBitmap(mForeground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
}
private Path createBackgroundPath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mB.x, mB.y);
path.lineTo(mC.x, mC.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawBackground( Canvas canvas, Rect rect, Paint paint ) {
Path mask = createBackgroundPath();
// Save current canvas so we do not mess it up
canvas.save();
canvas.clipPath(mask);
canvas.drawBitmap(mBackground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
canvas.restore();
}
private Path createCurlEdgePath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mE.x, mE.y);
path.lineTo(mF.x, mF.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawCurlEdge( Canvas canvas )
{
Path path = createCurlEdgePath();
canvas.drawPath(path, mCurlEdgePaint);
}
private void drawPageNum(Canvas canvas, int pageNum)
{
mTextPaint.setColor(Color.WHITE);
String pageNumText = "- "+pageNum+" -";
drawCentered(canvas, pageNumText,canvas.getHeight()-mTextPaint.getTextSize()-5,mTextPaint,mTextPaintShadow);
}
public static void drawTextShadowed(Canvas canvas, String text, float x, float y, Paint textPain, Paint shadowPaint) {
canvas.drawText(text, x-1, y, shadowPaint);
canvas.drawText(text, x, y+1, shadowPaint);
canvas.drawText(text, x+1, y, shadowPaint);
canvas.drawText(text, x, y-1, shadowPaint);
canvas.drawText(text, x, y, textPain);
}
public static void drawCentered(Canvas canvas, String text, float y, Paint textPain, Paint shadowPaint)
{
float posx = (canvas.getWidth() - textPain.measureText(text))/2;
drawTextShadowed(canvas, text, posx, y, textPain, shadowPaint);
}
private void drawDebug(Canvas canvas)
{
float posX = 10;
float posY = 20;
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setStyle(Style.STROKE);
paint.setColor(Color.BLACK);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
posY = debugDrawPoint(canvas,"A",mA,Color.RED,posX,posY);
posY = debugDrawPoint(canvas,"B",mB,Color.GREEN,posX,posY);
posY = debugDrawPoint(canvas,"C",mC,Color.BLUE,posX,posY);
posY = debugDrawPoint(canvas,"D",mD,Color.CYAN,posX,posY);
posY = debugDrawPoint(canvas,"E",mE,Color.YELLOW,posX,posY);
posY = debugDrawPoint(canvas,"F",mF,Color.LTGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Mov",mMovement,Color.DKGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Origin",mOrigin,Color.MAGENTA,posX,posY);
posY = debugDrawPoint(canvas,"Finger",mFinger,Color.GREEN,posX,posY);
}
private float debugDrawPoint(Canvas canvas, String name, Vector2D point, int color, float posX, float posY) {
return debugDrawPoint(canvas,name+" "+point.toString(),point.x, point.y, color, posX, posY);
}
private float debugDrawPoint(Canvas canvas, String name, float X, float Y, int color, float posX, float posY) {
mTextPaint.setColor(color);
drawTextShadowed(canvas,name,posX , posY, mTextPaint,mTextPaintShadow);
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setColor(color);
canvas.drawPoint(X, Y, paint);
return posY+15;
}
}
Am not performing Undo/Redo operation canvas in this code. When am use the array list for removing the postion then it not work and during changing the color of paint from color picker the previous drawing color has been also change.
I am not understanding that how to perform UNDO/REDO for this.
So plz help
//This is main class
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView (mView = new MyView(this));
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(4);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
//And MyView class is
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
ArrayList<Path> paths = new ArrayList<Path>();
ArrayList<Path> undonePaths = new ArrayList<Path>();
public MyView(Context c)
{
super(c);
mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
// mCanvas.setBackgroundResource(0xFFFFFFFF);
mCanvas.drawColor (0xFFFFFFFF);
paths.add(mPath);
}
public MyView (Context c, int color)
{
super(c);
mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mCanvas.drawColor (color);
paths.add(mPath);
}
#Override protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
}
#Override protected void onDraw(Canvas canvas)
{
canvas.drawColor(0xFF000000);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for(Path p: paths)
{
canvas.drawPath(p, 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);
mCanvas.drawPath(mPath, mPaint);
paths.add(mPath);
mPath.reset();
}
#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;
}
public void clear ()
{
Paint p = new Paint();
p.setAntiAlias(true);
p.setDither(true);
p.setColor(0xFFFFFFFF);
mCanvas.drawPaint (p);
}
public void drawImage (int resourceId)
{
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), resourceId);
mCanvas.drawBitmap(_scratch, 0, 0, null);
}
public void undo() {
// TODO Auto-generated method stub
mCanvas.drawCircle(posX, posY, 100, mPaint);
Toast.makeText(getApplicationContext(), "Hello", 1000).show();
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
mView.invalidate();
Toast.makeText(getApplicationContext(), "Undo", 1000).show();
}
else
{
Toast.makeText(getApplicationContext(), "Not", 1000).show();
}
}
public void redo() {
// TODO Auto-generated method stub
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
else
{
}
}
public void saveAsJpg (File f)
{
String fname = f.getAbsolutePath ();
FileOutputStream fos = null;
try {
fos = new FileOutputStream (f);
mBitmap.compress (CompressFormat.JPEG, 95, fos);
} catch (Throwable ex) {
ex.printStackTrace ();
}
} // end saveAsJpg
} // end MyView
} // end class FingerPaint
this working code .I test it on my own app and it is working very good.
May be it help u.Please comment on it.
public class Main extends Activity implements OnColorChangedListener {
//public static int selectedColor = Color.BLACK;
public static ArrayList<Path> mMaindialog;
// private ArrayList<Path> undonePaths;
// public int selectedcolor;
private static final String COLOR_PREFERENCE_KEY = "color";
private FrameLayout relativelayout;
static String sdpath,location;
Boolean i;
// Instance variables
private Bitmap mBitmap=null;
Bitmap bitmap;
private Paint mPaint, mBitmapPaint, mPaint1;
private MyView mView;
ImageView idd;
// private Path mPath;
int slll = Color.BLACK;
Bitmap map=ListView5.bMap;
private Button ClearPaint, Colorpaint;
Ghostdatabase gost;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
idd=(ImageView)findViewById(R.id.imageView1);
relativelayout = (FrameLayout) findViewById(R.id.frameLayout);
DisplayMetrics metrics = getBaseContext().getResources()
.getDisplayMetrics();
int w = metrics.widthPixels;
int h = metrics.heightPixels;
System.out.println(" width " + w);
System.out.println(" height " + h);
mView = new MyView(this, w, h);
mView.setDrawingCacheEnabled(true);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
ClearPaint = (Button) findViewById(R.id.ne);
ClearPaint.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// mBitmap.eraseColor(Color.TRANSPARENT);
// mPath.reset();
// mView.invalidate();
mView.onClickUndo();
}
});
Button save22 = (Button) findViewById(R.id.save);
save22.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
File cacheDir;
Toast.makeText(Main.this, "Photo", 500).show();
Bitmap icon;
relativelayout.setDrawingCacheEnabled(true);
icon = Bitmap.createBitmap(relativelayout.getDrawingCache());
Bitmap bitmap = icon;
relativelayout.setDrawingCacheEnabled(false);
// File mFile1 = Environment.getExternalStorageDirectory();
Date d = new Date();
String fileName = d.getTime() + "mg1.jpg";
File storagePath = (Environment.getExternalStorageDirectory());
File dest = new File(storagePath + "/CityAppImages");
if (!dest.exists()) {
dest.mkdirs();
}
File mFile2 = new File(dest, fileName);
sdpath = mFile2.getAbsolutePath();
Log.d("qqqqqqqqqqqqqqqqqqqqqqq", "zzzzzzzz" + sdpath);
try {
FileOutputStream outStream;
outStream = new FileOutputStream(mFile2);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
Toast.makeText(Main.this, "Photo Saved Sucessfully", 500)
.show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(Main.this, "Photo Not Saved Sucessfully",
500).show();
}
gost = new Ghostdatabase(Main.this);
gost.open();
gost.insertTitle(sdpath);
}
});
Button view = (Button) findViewById(R.id.listtt);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent ii = new Intent(Main.this, ListView5.class);
startActivity(ii);
}
});
Button Colorpaint = (Button) findViewById(R.id.Color);
Colorpaint.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int color = PreferenceManager.getDefaultSharedPreferences(
Main.this).getInt(COLOR_PREFERENCE_KEY, Color.WHITE);
// int _color = R.color.red;
new ColorPickerDialog(v.getContext(),
new OnColorChangedListener() {
public void colorChanged(int color) {
mPaint.setColor(color);
slll = color;
Log.i("TAG", "mpaint one" + mPaint);
}
}, mPaint.getColor()).show();
Log.i("TAG", "mpaint two" + mPaint);
}
});
relativelayout.addView(mView);
}
// //////////******************* Pinting view
// *******************///////////////////
public class MyView extends View implements OnTouchListener {
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
private ArrayList<Path> mMaindialog = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
int colorPicked = slll;
// Paint mPaint1;
private Canvas mCanvas;
private Path mPath;
public MyView(Context c, int w, int h) {
super(c);
if(GlobalVariable.impath==1)
{
Log.d("","111111"+GlobalVariable.impath);
System.out.println(GlobalVariable.impath);
Intent ii = getIntent();
location = ii.getStringExtra("IMAGE");
// bitmap.recycle();
Log.d("","location"+location);
bitmap = BitmapFactory.decodeFile(location);
mBitmap = Bitmap.createScaledBitmap(bitmap,300, 300,false);
Log.d("hhhhhhhhhhhhhhhssssssss","mBitmap"+mBitmap);
//mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
// idd.setImageBitmap(mBitmap);
Log.d("hhhhhhhhhhhhhhhssssssss","GlobalVariable.impath"+GlobalVariable.impath);
}
else if(GlobalVariable.impath==2){
//bitmap.recycle();
Log.d("","22222222222222222222222"+GlobalVariable.impath);
bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.base);
mBitmap = Bitmap.createScaledBitmap(bitmap,100, 100, false);
//mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Log.d("hhhhhhhhhhhhhhhssssssss1111111","mBitmap"+mBitmap);
}
//
mCanvas = new Canvas(mBitmap);
mPath = new Path();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : mMaindialog) {
mPaint.setColor(colorsMap.get(p));
canvas.drawPath(p, mPaint);
}
mPaint.setColor(slll);
canvas.drawPath(mPath, mPaint);
}
// //////************touching evants for painting**************///////
private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
undonePaths.clear();
}
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);
// kill this so we don't double draw
mPath = new Path();
mPath.reset();
mMaindialog.add(mPath);
}
#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();
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// touch_move(x, y);
// invalidate();
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;
}
invalidate();
break;
case MotionEvent.ACTION_UP:
// touch_up();
// invalidate();
mPath.lineTo(mX, mY);
mMaindialog.add(mPath);
colorsMap.put(mPath, slll);
mPath = new Path();
mPath.reset();
invalidate();
break;
}
return true;
} // end of touch events for image
private Paint createPen(int colorPicked) {
// TODO Auto-generated method stub
mPaint1 = new Paint();
mPaint1.setColor(colorPicked);
mPaint1.setAntiAlias(true);
mPaint1.setDither(true);
mPaint1.setStyle(Paint.Style.STROKE);
mPaint1.setStrokeJoin(Paint.Join.ROUND);
mPaint1.setStrokeCap(Paint.Cap.ROUND);
// mPaint1.setStrokeWidth(3);
return mPaint1;
}
public void onClickRedo() {
if (undonePaths.size() > 0) {
mMaindialog.add(undonePaths.remove(undonePaths.size() - 1));
mView.invalidate();
} else {
}
// toast the user
}
public void onClickUndo() {
if (mMaindialog.size() > 0) {
undonePaths.add(mView.mMaindialog.remove(mView.mMaindialog
.size() - 1));
mView.invalidate();
}
else {
}
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}// end MyView
#Override
public void colorChanged(int color) {
// TODO Auto-generated method stub
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putInt(COLOR_PREFERENCE_KEY, color).commit();
slll = color;
}
}