I try to draw on ImageView from a file resource. Here is my code:
private Bitmap myBitmap;
private Bitmap mutableBitmap;
private Canvas canvas;
private Paint paint;
private ImageView img;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.layout_imagefullscreen);
paint = new Paint();
paint.setStrokeWidth(11);
paint.setColor(Color.YELLOW);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;
decorView.setSystemUiVisibility(uiOptions);
...
if (imageFileFullPathName != null) {
try {
File imgFile = new File (imageFileFullPathName);
if (imgFile.exists ()) {
myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
mutableBitmap = myBitmap.copy(Bitmap.Config.ARGB_8888, true);
canvas = new Canvas(mutableBitmap);
img.setImageBitmap(mutableBitmap);
Matrix m = img.getImageMatrix();
canvas.setMatrix(m);
}
} catch (Exception e) {
e.printStackTrace ();
}
}
img.setOnTouchListener (new OnTouchListener() {
float startX, startY;
float stopX, stopY;
#Override
public boolean onTouch (View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
Log.i("---> DOWN X", String.valueOf(startX));
Log.i("---> DOWN Y", String.valueOf(startY));
break;
case MotionEvent.ACTION_MOVE:
stopX = event.getRawX();
stopY = event.getRawY();
Log.i("---> MOVE X", String.valueOf(stopX));
Log.i("---> MOVE Y", String.valueOf(stopY));
canvas.drawLine(startX, startY, stopX, stopY, paint);
img.invalidate();
startX = event.getRawX();
startY = event.getRawY();
img.setImageBitmap(mutableBitmap);
break;
case MotionEvent.ACTION_UP:
stopX = event.getRawX();
stopY = event.getRawY();
Log.i("---> UP X", String.valueOf(stopX));
Log.i("---> UP Y", String.valueOf(stopY));
canvas.drawLine(startX, startY, stopX, stopY, paint);
img.invalidate();
break;
default:
break;
}
v.performClick();
return true;
}
});
}
}'
But when I move my finger on the ImageView, the line does not follow my finger, it limits only on the top left of the screen instead. I also try to change getRawX() to getX(), but this issue persists. I believe the problem is something about coordinates transformation, but could not figure how to solve it. Please help, thanks!
Layout xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#color/Black">
<ImageView
android:id="#+id/imagefullscreenview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
From your code, it looks like you are trying to drawing following the touched finger. So here is how you draw...
public class MainActivity extends Activity implements SurfaceHolder.Callback, OnClickListener, OnTouchListener {
SurfaceView sv;
SurfaceHolder sh;
RenderingThread thread;
Canvas canvas = null;
int Width = 0, Height = 0;
Button btnClear;
Path path = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
try{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
sv = (SurfaceView)findViewById(R.id.sv);
sv.setOnTouchListener(this);
btnClear = (Button)findViewById(R.id.btnClear);
path = new Path();
sh = sv.getHolder();
if(sh != null)
{
sh.addCallback(this);
}
else
{
Toast.makeText(getApplicationContext(), "Failed to initialize", Toast.LENGTH_SHORT).show();
finish();
}
}catch(Throwable ex)
{
ex.printStackTrace();
Toast.makeText(getApplicationContext(), "Failed to start", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
try{
Width = width;
Height = height;
thread = new RenderingThread(holder, width, height);
canvas = new Canvas(thread.drawingBitmap);
thread.start();
}catch(Throwable ex) {
ex.printStackTrace();
Toast.makeText(getApplicationContext(), "Failed to initialize", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
sv.setWillNotDraw(false);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
thread.RequestStop();
}
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
path.moveTo(event.getRawX(), event.getRawY());
break;
case MotionEvent.ACTION_MOVE:
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5);
CornerPathEffect pathEffect = new CornerPathEffect(45);
paint.setPathEffect(pathEffect);
path.lineTo(event.getRawX(), event.getRawY());
canvas.drawPath(path, paint);
//
Log.i("minor",""+event.getTouchMinor());
Log.i("major",""+event.getTouchMajor());
break;
case MotionEvent.ACTION_UP:
path.reset();
break;
}
return true;
}
#Override
public void onClick(View v) {
switch(v.getId())
{
case R.id.btnClear:
canvas.drawColor(Color.WHITE);
break;
}
}
}
Here btnClear is a button in XML from which you can clear the canvas.
Here is the XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<SurfaceView
android:id="#+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="#+id/btnClear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clear"
android:textSize="18sp"
android:textColor="#ffffff"
android:background="#555555"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:onClick="onClick" />
</RelativeLayout>
And here is the rendering thread...
public class RenderingThread extends Thread {
private boolean keepRunning = true;
private SurfaceHolder holder = null;
public Bitmap drawingBitmap = null;
private int width = 0, height = 0;
public RenderingThread(SurfaceHolder holder, int width, int height)
{
this.holder = holder;
this.width = width;
this.height = height;
drawingBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
}
public void RequestStop()
{
keepRunning = false;
interrupt();
}
#Override
public void run() {
while(keepRunning)
{
try{
Thread.sleep(30);
//
if(holder != null && drawingBitmap != null)
{
Canvas canvas = holder.lockCanvas();
if(canvas != null)
{
canvas.drawColor(Color.WHITE);
Rect src = new Rect(0, 0, drawingBitmap.getWidth(), drawingBitmap.getHeight());
Rect dst = new Rect(0, 0, width, height);
canvas.drawBitmap(drawingBitmap, src, dst, new Paint());
//
holder.unlockCanvasAndPost(canvas);
}
}
}catch(Throwable ex) {
ex.printStackTrace();
}
}
}
}
Good Luck. :)
Related
I want to obtain the height of a custom View so the animation can cover all the size of the layout, no matter what device is being used. The problem is, the View needs to be static, so when I try to get its height, it says I can't call a non-static method from a static class.
private static class EjemploView extends View {
private Path path = new Path();
private static float Last_X = 0;
private static float Last_Y = 0;
public EjemploView (Context context) {
super(context);
new Thread(new Runnable() {
public void run() {
y=30;
while(true){
try {
Thread.sleep(sleeptime);
if(!direction)
{
y=y+StepY_Figura;
}
else
{
y=y-StepY_Figura;
}
if(y<30)
{
direction=false;
paint.setColor(Color.BLACK);
Thread.sleep(350);
}
if(y>260)
{
direction=true;
paint.setColor(Color.WHITE);
Thread.sleep(350);
}
postInvalidate();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
protected void onDraw(Canvas canvas) {
float x = canvas.getWidth() / 4;
float x2=x;
if(Unaprueba==true)
{
canvas.drawColor(Color.BLACK);
}
else
{
canvas.drawColor(Color.WHITE);
}
canvas.drawCircle(x, y, 30, paint);
x =x+x2+4;
canvas.drawCircle(x, y, 30, paint);
x =x+x2+4;
canvas.drawCircle(x, y, 30, paint);
String s =Integer.toString(sleeptime);
canvas.drawText("RITHM: "+s, 10, 20, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
int Change_coordY=10;
int Change_Delay=5;
int Minimum_Delay=5;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//path.moveTo(eventX, eventY);
Last_X=eventX;
Last_Y=eventY;
return true;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if(eventY>Last_Y+Cambio_coordY)
{
sleeptime=sleeptime-Change_Delay;
if(sleeptime<=Minimum_Delay)
{
sleeptime=Minimum_Delay;
}
}
else if(eventY<Last_Y-Change_coordY)
{
sleeptime=sleeptime+Change_Delay;
}
break;
default:
return false;
}
invalidate();
return true;
}
}
Do you know if there is any way I can get the size of the layout if the View is static? Thanks in advance.
I'm developing a paint activity please take a look on the code I'm working on below:
public class MyTouchEventView extends LinearLayout {
private Paint paint = new Paint();
private Path path = new Path();
private Paint circlePaint = new Paint();
private Path circlePath = new Path();
public Button btnReset;
public Button btnSave;
public LinearLayout.LayoutParams params;
public MyTouchEventView(Context context) {
super(context);
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(15f);
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
btnReset = new Button(context);
btnReset.setText("Clear Screen");
btnSave = new Button(context);
btnSave.setText("Save Image");
params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
btnReset.setLayoutParams(params);
btnSave.setLayoutParams(params);
addView(btnReset);
addView(btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// resets the screen
path.reset();
// Calls the onDraw() method
postInvalidate();
}
});
btnReset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// resets the screen
path.reset();
// Calls the onDraw() method
postInvalidate();
}
});
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, paint);
canvas.drawPath(circlePath, circlePaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Gives you x and y coordinates on the Event.
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX, pointY);
circlePath.reset();
// (circle's center x-coordinate, y-coordinate, radius of the
// circle, direction to wind the shape)
circlePath.addCircle(pointX, pointY, 30, Path.Direction.CW);
//circlePath.addRect(pointX - 25, pointY - 25, pointX + 25, pointY + 25, Path.Direction.CW);
/* RectF rect = new RectF(pointX - 25, pointY - 25, pointX + 25, pointY + 25);
circlePath.addRoundRect(rect, 0, 0, Path.Direction.CW);
*/
break;
case MotionEvent.ACTION_UP:
circlePath.reset();
break;
default:
return false;
}
// Schedules a repaint.
// Force a view to draw.
postInvalidate();
return true;
}
But the problem is, I can't draw on canvas. What am I missing in here? Any help and response are truly appreciated. Thanks.
I only made few changes to your code. Check the snap shot
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/button1"
android:id="#+id/rl"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" >
</RelativeLayout>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="14dp"
android:text="Clear" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="32dp"
android:text="Save" />
</RelativeLayout>
MainActivity
public class MainActivity extends Activity {
DrawingView dv ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new DrawingView(this);
setContentView(R.layout.activity_main);
RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl);
rl.addView(dv);
Button b = (Button) findViewById(R.id.button1);
Button b1 = (Button) findViewById(R.id.button2);
b.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
dv.clear(); // on button click clear the draw
}
});
// similarly you can save the draw. i have not added.
// if you have trouble let me know
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public class DrawingView extends View {
private Paint paint = new Paint();
private Path path = new Path();
private Paint circlePaint = new Paint();
private Path circlePath = new Path();
public Button btnReset;
public Button btnSave;
public LinearLayout.LayoutParams params;
public DrawingView (Context context) {
super(context);
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(15f);
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
}
public void clear()
{
path.reset();
// Calls the onDraw() method
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, paint);
canvas.drawPath(circlePath, circlePaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Gives you x and y coordinates on the Event.
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX, pointY);
circlePath.reset();
// (circle's center x-coordinate, y-coordinate, radius of the
// circle, direction to wind the shape)
circlePath.addCircle(pointX, pointY, 30, Path.Direction.CW);
//circlePath.addRect(pointX - 25, pointY - 25, pointX + 25, pointY + 25, Path.Direction.CW);
/* RectF rect = new RectF(pointX - 25, pointY - 25, pointX + 25, pointY + 25);
circlePath.addRoundRect(rect, 0, 0, Path.Direction.CW);
*/
break;
case MotionEvent.ACTION_UP:
circlePath.reset();
break;
default:
return false;
}
// Schedules a repaint.
// Force a view to draw.
invalidate();
return true;
}
}
}
Snap Shot
Explanation
I used a Relative layout and placed buttons accordingly.
I used another relative layout with id rl. Added custom view to the same.
I extended a view rather than Linear Layout.
I defined a method clear to clear the draw which is called onClick of clear.
I used invalidate to refresh the draw.
Edit 2:
Save:
Note: Only the draw is saved. You can save the entire screen if you want to.
Add permission in Manifest File
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Use the below to save
Button b1 = (Button) findViewById(R.id.button2);
b1.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
AlertDialog.Builder editalert = new AlertDialog.Builder(MainActivity.this);
editalert.setTitle("Please Enter the name with which you want to Save");
final EditText input = new EditText(MainActivity.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) {
rl.setDrawingCacheEnabled(true);
String name= input.getText().toString();
Bitmap bitmap =rl.getDrawingCache();
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/MyDraw");
myDir.mkdirs();
File file = new File (myDir, name+".png");
if (file.exists ()) file.delete ();
try
{
if(!file.exists())
{
file.createNewFile();
}
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 10, ostream);
// System.out.println("saving......................................................"+path);
ostream.close();
rl.invalidate();
}
catch (Exception e)
{
e.printStackTrace();
}finally
{
rl.setDrawingCacheEnabled(false);
}
}
});
editalert.show();
}
});
I'm making an application to create signature on file image. Here, I will load the image file from the memory card to the application and use Canvas Paint can create a signature by hand through the draw.
The problem here is the application requirements for customers to sign in a specific location. My code allows customers can sign in anywhere the customer wants, like paint on the windows. Now, I want to be signed in a specific area only... Help me...
This my code
Main.java
public class Longvan extends Activity implements OnClickListener, OnTouchListener {
ImageView choosenImageView;
Button choosePicture;
Button savePicture;
Bitmap bmp;
Bitmap alteredBitmap;
Canvas canvas;
Paint paint;
Matrix matrix;
float downx = 0;
float downy = 0;
float upx = 0;
float upy = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_longvan);
int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
choosenImageView = (ImageView) this.findViewById(R.id.ChoosenImageView);
choosePicture = (Button) this.findViewById(R.id.ChoosePictureButton);
savePicture = (Button) this.findViewById(R.id.SavePictureButton);
savePicture.setOnClickListener(this);
choosePicture.setOnClickListener(this);
choosenImageView.setOnTouchListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_longvan, menu);
return true;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downx = event.getX();
downy = event.getY();
break;
case MotionEvent.ACTION_MOVE:
upx = event.getX();
upy = event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
choosenImageView.invalidate();
downx = upx;
downy = upy;
break;
case MotionEvent.ACTION_UP:
upx = event.getX();
upy = event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
choosenImageView.invalidate();
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v == choosePicture) {
Intent choosePictureIntent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(choosePictureIntent, 0);
} else if (v == savePicture) {
if (alteredBitmap != null) {
ContentValues contentValues = new ContentValues(3);
contentValues.put(Media.DISPLAY_NAME, "Draw On Me");
Uri imageFileUri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, contentValues);
try {
OutputStream imageFileOS = getContentResolver().openOutputStream(imageFileUri);
alteredBitmap.compress(CompressFormat.JPEG, 90, imageFileOS);
Toast t = Toast.makeText(this, "Thank you! Image Saved!", Toast.LENGTH_LONG);
t.show();
} catch (Exception e) {
Log.v("EXCEPTION", e.getMessage());
}
}
}
}
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK) {
Uri imageFileUri = intent.getData();
try {
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(
imageFileUri), null, bmpFactoryOptions);
bmpFactoryOptions.inJustDecodeBounds = false;
bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(
imageFileUri), null, bmpFactoryOptions);
alteredBitmap = Bitmap.createBitmap(bmp.getWidth(),bmp.getHeight(),bmp.getConfig());
canvas = new Canvas(alteredBitmap);
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(2);
matrix = new Matrix();
canvas.drawBitmap(bmp, matrix, paint);
choosenImageView.setImageBitmap(alteredBitmap);
choosenImageView.setOnTouchListener(this);
} catch (Exception e) {
Log.v("ERROR", e.toString());
}
}
}
}
How about a specific View for inputting Signatures? Something like this: https://github.com/CoatedMoose/CustomViews/tree/master/library/src/com/coatedmoose/customviews
Then, add this setter for the Bitmap:
public void setImage(Bitmap bitmap) {
this.mBitmap = bitmap;
this.invalidate();
}
Or, if you dont want the applied bitmap as part of your signatureview (use it as background, and not as canvas), replace the onDraw method with this:
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
canvas.drawPath(mPath, mPaint);
}
and then just use mSignatureView.setBackgroundResource(R.drawable.background);
Edit:
Just create a Class with the code from coatedMoose, and use it in your layout XML:
<com.example.myapp.gui.views.SignatureView
android:id="#+id/signature"
android:layout_width="match_parent"
android:layout_height="80dp"/>
Somewhere in your code, or even as an XML attribute, you can set the background.
Edit: signatureView class:
package me.other;
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.os.SystemClock;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* A simple view to capture a path traced onto the screen. Initially intended to be used to captures signatures.
*
* #author Andrew Crichton
* #version 0.1
*/
public class SignatureView extends View {
#SuppressWarnings("unused")
private Path mPath;
private Paint mPaint;
private Paint bgPaint = new Paint(Color.TRANSPARENT);
private Bitmap mBitmap;
private Canvas mCanvas;
private float curX, curY;
private static final int TOUCH_TOLERANCE = 4;
private static final int STROKE_WIDTH = 4;
public SignatureView(Context context) {
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SignatureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setFocusable(true);
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(STROKE_WIDTH);
}
public void setSigColor(int color) {
mPaint.setColor(color);
}
public void setSigColor(int a, int red, int green, int blue) {
mPaint.setARGB(a, red, green, blue);
}
public boolean clearSignature() {
if (mBitmap != null)
createFakeMotionEvents();
if (mCanvas != null) {
mCanvas.drawColor(Color.TRANSPARENT);
mCanvas.drawPaint(bgPaint);
mPath.reset();
invalidate();
}
else {
return false;
}
return true;
}
public Bitmap getImage() {
return this.mBitmap;
}
public void setImage(Bitmap bitmap) {
this.mBitmap = bitmap;
this.invalidate();
}
#Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
int bitmapWidth = mBitmap != null ? mBitmap.getWidth() : 0;
int bitmapHeight = mBitmap != null ? mBitmap.getWidth() : 0;
if (bitmapWidth >= width && bitmapHeight >= height)
return;
if (bitmapWidth < width)
bitmapWidth = width;
if (bitmapHeight < height)
bitmapHeight = height;
Bitmap newBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
Canvas newCanvas = new Canvas();
newCanvas.setBitmap(newBitmap);
if (mBitmap != null)
newCanvas.drawBitmap(mBitmap, 0, 0, null);
mBitmap = newBitmap;
mCanvas = newCanvas;
}
private void createFakeMotionEvents() {
MotionEvent downEvent = MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis()+100, MotionEvent.ACTION_DOWN, 1f, 1f ,0);
MotionEvent upEvent = MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis()+100, MotionEvent.ACTION_UP, 1f, 1f ,0);
onTouchEvent(downEvent);
onTouchEvent(upEvent);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
canvas.drawPath(mPath, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(x, y);
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
break;
case MotionEvent.ACTION_UP:
touchUp();
break;
}
invalidate();
return true;
}
/**----------------------------------------------------------
* Private methods
**---------------------------------------------------------*/
private void touchDown(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
curX = x;
curY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - curX);
float dy = Math.abs(y - curY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(curX, curY, (x + curX)/2, (y + curY)/2);
curX = x;
curY = y;
}
}
private void touchUp() {
mPath.lineTo(curX, curY);
if (mCanvas == null) {
mCanvas = new Canvas();
mCanvas.setBitmap(mBitmap);
}
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
}
Some random layout XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.mysignatureviewapp.views.SignatureView
android:id="#+id/sign"
android:layout_width="match_parent"
android:layout_height="204dp">
</com.example.mysignatureviewapp.views.SignatureView>
</RelativeLayout>
In the onCreate() method:
private SignatureView sign;
//
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mysignatureviewlayout);
sign = (SignatureView) findViewById(R.id.sign);
sign.setBackgroundResource(R.drawable.mybackgrounddrawable);
}
//get your signature when you press, say, the back button
#Override
public void onBackPressed() {
Bitmap mySignature = sign.getImage();
//do something with bitmap
}
Getting both the background and the signature:
BitmapDrawable mySignature = new BitmapDrawable(sign.getImage());
Drawable background = sign.getBackground();
LayerDrawable ld = new LayerDrawable(new Drawable[] { mySignature, background});
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Bitmap recycle with largeHeap enabled
hi am doing one app here i am displying images using bitmaps,that images is displaying well,but becz this class i am getting out of memory exception in another class.pls see once my code and how to solve this issue any suhhest me...
public class DesignofatozActivity extends Activity {
BitmapDrawable sounddrawable,erasedrawable,backdrwable,fwddrwable,captiondrwable;
Bitmap soundbitmap,eraseBitmap,backbitmap,fwdbitmap,captionbitmap;
bitmapOrg,bitmapOrg1,bitmapOrg2,bitmapOrg3,bitmapOrg4,bitmapOrg5,bitmapOrg6;
MyView myview;
File f;
ImageView d1,d2,d3,d4,d5,d6;
public boolean action=false;
RelativeLayout relativeLayout,layout,relativeLayout2;
Button c1,c2,c3,c4,c5,c6,c7,c8;
MediaPlayer player;
MediaPlayer mediay2;
ImageView horn;
float screenHeight,screenWidth,screendensity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setNoTitle();
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
screenHeight = displaymetrics.heightPixels;
screenWidth = displaymetrics.widthPixels;
screendensity = displaymetrics.densityDpi;
Log.i("screenHeight",""+screenHeight);
Log.i("screenWidth",""+screenWidth);
Log.i("screendensity",""+screendensity);
setContentView(R.layout.line);
relativeLayout=(RelativeLayout)findViewById(R.id.relative);
relativeLayout.setBackgroundColor(Color.WHITE);
relativeLayout2=(RelativeLayout)findViewById(R.id.relative2);
RelativeLayout.LayoutParams layoutrel2= (RelativeLayout.LayoutParams) relativeLayout2.getLayoutParams();
layoutrel2.height=(int)(25*(screenHeight/600));
int toplay=(int)(90*(screenHeight/600));
layout=new RelativeLayout(this);
RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.setMargins(0, toplay, 0,0);
layout.setLayoutParams(lp);
relativeLayout.addView(layout,lp);
int topmyvi=(int)(45*(screenHeight/600));
myview = new MyView(this);
myview.setId(004);
RelativeLayout.LayoutParams lp6 = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
myview.setLayoutParams(lp6);
lp6.setMargins(0, topmyvi, 0,0);
relativeLayout.addView(myview,lp6);
ImageView I2=new ImageView(this);
if(captiondrwable!= null) {
captionbitmap.recycle();
captiondrwable= null;
}
captionbitmap=BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.caption22_1));
captiondrwable = new BitmapDrawable(captionbitmap);
I2.setBackgroundDrawable(captiondrwable);
int left2=(int)(15*(screenWidth/1024));
int widthhh2=(int)(100*(screenWidth/1024));
int hifhtttt2=(int)(50*(screenHeight/600));
RelativeLayout.LayoutParams rlp2=new RelativeLayout.LayoutParams(widthhh2,hifhtttt2);
rlp2.setMargins(left2, topmyvi, 0, 0);
relativeLayout.addView(I2,rlp2);
ImageView b1=new ImageView(this);
if(erasedrawable!= null) {
eraseBitmap.recycle();
erasedrawable= null;
}
eraseBitmap=BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.eraser_501));
erasedrawable = new BitmapDrawable(eraseBitmap);
b1.setBackgroundDrawable(erasedrawable);
int leftb1=(int)(650*(screenWidth/1024));
int topb1=(int)(10*(screenHeight/600));
int widtb1=(int)(100*(screenWidth/1024));
int hightb1=(int)(100*(screenHeight/600));
RelativeLayout.LayoutParams rlp3=new RelativeLayout.LayoutParams(widtb1,hightb1);
rlp3.setMargins(leftb1, topb1, 0, 0);
relativeLayout.addView(b1,rlp3);
b1.setOnClickListener(new OnClickListener() {
// #Override
public void onClick(View v) {
// TODO Auto-generated method stub
try{
mBitmap.eraseColor(android.graphics.Color.TRANSPARENT);
Canvas Canvas=new Canvas(mBitmap);
action=true;
myview.onDraw(Canvas);
}catch(IllegalStateException ie){
ie.printStackTrace();
}
}
});
int lefth1=(int)(830*(screenWidth/1024));
int toph1=(int)(35*(screenHeight/600));
int width1=(int)(60*(screenWidth/1024));
int highth1=(int)(60*(screenHeight/600));
horn=new ImageView(this);
if(sounddrawable!= null) {
soundbitmap.recycle();
sounddrawable= null;
}
soundbitmap=BitmapFactory.decodeStream(getResources().openRawResource( R.drawable.horn));
sounddrawable = new BitmapDrawable(soundbitmap);
horn.setBackgroundDrawable(sounddrawable);
RelativeLayout.LayoutParams hn=new RelativeLayout.LayoutParams(width1,highth1);
hn.setMargins(lefth1,toph1,0,0);
relativeLayout.addView(horn,hn);
horn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if(mediay2==null)
{
mediay2 = MediaPlayer.create(DesignofatozActivity.this, R.raw.hwprepsheets);
}
mediay2.start();
if(mediay2!=null)
{
}
}
});
ImageView next=(ImageView)findViewById(R.id.imv1a);
if(fwddrwable!= null) {
fwdbitmap.recycle();
fwddrwable= null;
}
fwdbitmap=BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.next_50));
fwddrwable = new BitmapDrawable(fwdbitmap);
next.setBackgroundDrawable(fwddrwable);
RelativeLayout.LayoutParams layoutnxt= (RelativeLayout.LayoutParams) next.getLayoutParams();
layoutnxt.height=(int)(30*(screenHeight/600));
layoutnxt.width=(int)(50*(screenWidth/1024));
next.setOnClickListener(new OnClickListener() {
// #Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Log.i("next","next");
Intent i =new Intent(DesignofatozActivity.this,Dots.class);
startActivity(i);
}
});
ImageView back=(ImageView)findViewById(R.id.back);
if(backdrwable!= null) {
backbitmap.recycle();
backdrwable= null;
}
backbitmap=BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.back1_50));
backdrwable = new BitmapDrawable(backbitmap);
back.setBackgroundDrawable(backdrwable);
RelativeLayout.LayoutParams layoutbak= (RelativeLayout.LayoutParams) back.getLayoutParams();
layoutbak.height=(int)(30*(screenHeight/600));
layoutbak.width=(int)(50*(screenWidth/1024));
back.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent i =new Intent(DesignofatozActivity.this,Slantlines.class);
startActivity(i);
}
});
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
//mPaint.setColor(0xFFFF0000);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
}
private void setNoTitle() {
// TODO Auto-generated method stub
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
private Paint mPaint;
private Bitmap mBitmap;
public void colorChanged(int color) {
mPaint.setColor(color);
}
public class MyView extends View
{
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
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);
if (mBitmap != null) {
mBitmap.recycle();
mBitmap=null;
}
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mCanvas.setBitmap(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
if(action)
{
invalidate();
}
Paint painto = new Paint();
painto.setAntiAlias(true);
painto.setStrokeWidth(3);
painto.setStyle(Paint.Style.FILL);
int leftx1=(int)(15*(screenWidth/1024));
int leftx2=(int)(1010*(screenWidth/1024));
int topy1=(int)(60*(screenHeight/600));
int topy2=(int)(530*(screenHeight/600));
canvas.drawLine(leftx1, topy1, leftx2, topy1, painto);
canvas.drawLine(leftx1, topy1, leftx1, topy2, painto);
canvas.drawLine(15, topy2, leftx2, topy2, painto);
canvas.drawLine(leftx2, topy1, leftx2, topy2, painto);
bitmapOrg = BitmapFactory.decodeResource(getResources(),
R.drawable.circles1_4);
int leftorg=(int)(150*(screenWidth/1024));
int toporg=(int)(110*(screenHeight/600));
canvas.drawBitmap(bitmapOrg, leftorg, toporg, painto);
bitmapOrg.recycle();
bitmapOrg=null;
bitmapOrg1 = BitmapFactory.decodeResource(getResources(),
R.drawable.circles1_5);
int leftorg1=(int)(430*(screenWidth/1024));
int toporg1=(int)(130*(screenHeight/600));
canvas.drawBitmap(bitmapOrg1, leftorg1,toporg1, painto);
bitmapOrg1.recycle();
bitmapOrg1=null;
bitmapOrg2 = BitmapFactory.decodeResource(getResources(),
R.drawable.circles1_6);
int leftorg2=(int)(650*(screenWidth/1024));
canvas.drawBitmap(bitmapOrg2, leftorg2,toporg, painto);
bitmapOrg2.recycle();
bitmapOrg2=null;
bitmapOrg3 = BitmapFactory.decodeResource(getResources(),
R.drawable.circles1_1);
int leftorg3=(int)(170*(screenWidth/1024));
int toporg3=(int)(350*(screenHeight/600));
canvas.drawBitmap(bitmapOrg3, leftorg3,toporg3, painto);
bitmapOrg3.recycle();
bitmapOrg3=null;
bitmapOrg4 = BitmapFactory.decodeResource(getResources(),
R.drawable.circles1_3);
int leftorg4=(int)(680*(screenWidth/1024));
canvas.drawBitmap(bitmapOrg4, leftorg4,toporg3, painto);
bitmapOrg4.recycle();
bitmapOrg4=null;
bitmapOrg5 = BitmapFactory.decodeResource(getResources(),
R.drawable.circles1_2);
int leftorg5=(int)(400*(screenWidth/1024));
int toporg5=(int)(300*(screenHeight/600));
canvas.drawBitmap(bitmapOrg5, leftorg5,toporg5, painto);
bitmapOrg5.recycle();
bitmapOrg5=null;
Paint paint1 = new Paint();
paint1.setAntiAlias(true);
paint1.setColor(Color.BLACK);
paint1.setStrokeWidth(3);
paint1.setStyle(Paint.Style.FILL);
paint1.setTextSize(13);
canvas.drawText("Get ready to write place your pen on the dot and follow direction ", 120, 20, paint1);
canvas.drawText("indicated by the arrow . ", 120, 38, paint1);
Paint p = new Paint();
p.setAntiAlias(true);
p.setTextSize(120);
p.setColor(Color.LTGRAY);
Typeface font = Typeface.createFromAsset(getAssets(), "font/KINDTRG.TTF");
p.setTypeface(font);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
} private float mX, mY;
private final float TOUCH_TOLERANCE = 2;
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();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
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 clearAllResources() {
// Set related variables null
System.gc();
Runtime.getRuntime().gc();
}
#Override
protected void onPause() {
if (mediay2 != null){
mediay2.stop();
mediay2.release();
mediay2=null;
}
clearAllResources();
super.onPause();
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.gc();
Runtime.getRuntime().gc();
unbindDrawables(findViewById(R.id.relative));
}
private void unbindDrawables(View view) {
// TODO Auto-generated method stub
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
}
You use memory heap more than gcc allowed size. You must use slaced bitmaps
or
+3.0 in manifest add application
android:largeHeap="true" to allocate more heap size.
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
android:largeHeap="true">...
Try This
After you get bitmap then recycle bitmap after use this will solve some issue.
Bitmap finalImage;
finalImage.recycle();
Or try in onResume()
System.gc();
I suggest you have a look at this thread: Strange out of memory issue while loading an image to a Bitmap object
This was answer on the thread:
public Bitmap readAssetsBitmap(String filename) throws IOException {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeStream(assets.open(filename), null, options);
if(bitmap == null) {
throw new IOException("File cannot be opened: It's value is null");
}
else {
return bitmap;
}
} catch (IOException e) {
throw new IOException("File cannot be opened: " + e.getMessage());
}
}
Remember to recycle bitmaps and set them to null once they have been used to ensure the get GCed.
Note: You shouldn't call System.gc();
I hope this helps.
/I got the following code:
public class SketchActivity extends Activity implements OnClickListener, OnSeekBarChangeListener {
private MyView myView;
private Button clearBtn;
private ToggleButton embossBtn, blurBtn, eraseBtn, srcaBtn;
private RelativeLayout layout, layout2;
private TextView penSizeTxt;
SharedPreferences pref;
private Preview preview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
init();
preview = new Preview(this);
layout2 = (RelativeLayout) findViewById(R.id.paint_layout2);
layout = (RelativeLayout) findViewById(R.id.paint_layout);
layout.addView(preview);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
myView = new MyView(SketchActivity.this, layout.getWidth(), layout.getHeight());
layout2.addView(myView);
layout2.bringToFront();
}
}, 50);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFF000000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
private void init() {
clearBtn = (Button) findViewById(R.id.clearBtn);
embossBtn = (ToggleButton) findViewById(R.id.embossBtn);
blurBtn = (ToggleButton) findViewById(R.id.blurBtn);
eraseBtn = (ToggleButton) findViewById(R.id.eraseBtn);
srcaBtn = (ToggleButton) findViewById(R.id.srcatopBtn);
clearBtn.setOnClickListener(this);
embossBtn.setOnClickListener(this);
blurBtn.setOnClickListener(this);
eraseBtn.setOnClickListener(this);
srcaBtn.setOnClickListener(this);
}
private static Paint mPaint;
private MaskFilter mEmboss;
private MaskFilter mBlur;
public void colorChanged(int color) {
mPaint.setColor(color);
}
private void setToggleOf() {
embossBtn.setChecked(false);
eraseBtn.setChecked(false);
blurBtn.setChecked(false);
srcaBtn.setChecked(false);
}
#Override
public void onClick(View v) {
if (v.getId() == embossBtn.getId()) {
if (mPaint.getMaskFilter() != mEmboss) {
setToggleOf();
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
mPaint.setMaskFilter(mEmboss);
embossBtn.setChecked(true);
} else {
mPaint.setMaskFilter(null);
embossBtn.setChecked(false);
}
} else if (v.getId() == blurBtn.getId()) {
if (mPaint.getMaskFilter() != mBlur) {
setToggleOf();
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
mPaint.setMaskFilter(mBlur);
blurBtn.setChecked(true);
} else {
mPaint.setMaskFilter(null);
blurBtn.setChecked(false);
}
} else if (v.getId() == eraseBtn.getId()) {
if (eraseBtn.isChecked()) {
setToggleOf();
eraseBtn.setChecked(true);
mPaint.setMaskFilter(null);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
} else {
mPaint.setMaskFilter(null);
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
}
} else if (v.getId() == srcaBtn.getId()) {
if (srcaBtn.isChecked()) {
setToggleOf();
mPaint.setMaskFilter(null);
srcaBtn.setChecked(true);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
mPaint.setAlpha(0x80);
} else {
mPaint.setMaskFilter(null);
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
}
}
else if (v.getId() == clearBtn.getId()) {
layout2.removeAllViews();
myView = new MyView(SketchActivity.this, layout.getWidth(), layout.getHeight());
layout2.addView(myView);
}
}
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;
Bitmap bitmap;
int x = 0;
int y = 0;
int r = 0;
public MyView(Context c, int width, int height) {
super(c);
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int w = display.getWidth(); // deprecated
int h = display.getHeight();
// setFocusable(true);
// setBackgroundResource(R.drawable.download);
// setting paint
mPath = new Path();
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.smoke);
Bitmap bm2 = getResizedBitmap(bm, h, w);
// converting image bitmap into mutable bitmap
bitmap = bm2.createBitmap(w, h, Config.ARGB_8888);
mCanvas = new Canvas();
mCanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
mCanvas.drawBitmap(bm2, 0, 0, null);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
//mCanvas.drawCircle(x, y, r, mPaint);
// canvas.drawBitmap(bitmap, 0, 0, null);
canvas.drawBitmap(bitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
super.onDraw(canvas);
}
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);
// mPath.lineTo(x, y);
// mCanvas.drawPoint(x, y, mPaint);
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;
}
// invalidate();
}
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();
}
#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 Bitmap getImage() {
return mBitmap;
}
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
penSizeTxt.setText(String.valueOf(progress + 2));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
}
I want it to clear the second layout and show the content of the camera, on touch. So that if i make a curved line with my finger on the screen it would set those pixels to alpha, and see the camera from the back layout. The problem is that if for example, i make a curved line, the app erases the content of that curve too. So that if i would make a circle with my finger it would erase the content of the circle too, not only the margin.
A screenshot with how it looks: http://imgur.com/5gjNB
onCreate i had:
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFF000000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);
And then on my View i had:
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
Overriding the mPaint, and that's what made it not work properly. By deleting the second:
mPaint = new Paint();
I made it work