Scratch Card Effect in Android - android

I want to design a Scratch Card-like effect in android. Is It possible to do this with a Framelayout or RelativeLayout by stacking the coupon at the back of the bitmap and setting the colour of CustomCanvas to gray or something. I've tried doing this but I wasn't able to get the stacked image from the back. The background was just turning white and nothing else. I then tried to the COLOR.TRANSPARENT and there was no Scratch at all. How can I do this?
Below is my CustomCanvas Class extending the View class:
public class CanvasView extends View {
public int width,height;
private Bitmap bitmap;
private Canvas canvas;
Context context;
private Path mPath;
private Paint paint;
private float mX, mY;
private static final float TOLERANCE = 5;
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
mPath = new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(100f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap,0,0,paint);
canvas.drawPath(mPath, paint);
}
private void startTouch(float x, float y){
mPath.moveTo(x,y);
mX = x;
mY = y;
}
private void moveTouch(float x, float y){
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if(dx >= TOLERANCE || dy >= TOLERANCE){
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
public void clearCanvas(){
mPath.reset();
invalidate();
}
private void upTouch(){
mPath.lineTo(mX,mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
startTouch(x,y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x,y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
float r = calculatingPercentage(bitmap.getWidth(),bitmap.getHeight());
if(calculatingPercentage(bitmap.getWidth(),bitmap.getHeight()) >= 50.00){
Toast.makeText(getContext(),"Done 50%",Toast.LENGTH_SHORT).show();
}
invalidate();
break;
}
return true;
}
//FUNCTION I WAS USING TO CALCULATE THE SCRATCHED AREA'S PERCENTAGE
private float calculatingPercentage(int width,int height){
int[] xArray = new int[100];
int[] yArray = new int[100];
float percentTransparent;
Random r = new Random();
for(int i = 0; i<100;i++){
xArray[i] = r.nextInt(width - 10) +10;
}
for(int i = 0; i<100;i++){
yArray[i] = r.nextInt(height - 10) +10;
}
int pixelCount = 0;
for(int i = 0; i<100;i++){
int x = xArray[i];
int y = yArray[i];
int color = Color.WHITE;
int black = Color.BLACK;
if(bitmap.getPixel(xArray[i],yArray[i]) == Color.WHITE){
pixelCount++;
}
}
percentTransparent = (pixelCount/100);
return percentTransparent;
}
}
ActivityB which is calling the Canvasview class:
public class ActivityB extends Activity {
private CanvasView customCanvas;
private Button bt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_a);
customCanvas = (CanvasView) findViewById(R.id.signature_canvas);
bt = (Button) findViewById(R.id.buttonAgain);
bt.setVisibility(View.VISIBLE);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clearCanvas();
}
});
}
public void clearCanvas(){
customCanvas.clearCanvas();
}
}
And here is my fragment_a.xml layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/firstFrame"
android:background="#F07818"
tools:context="com.example.dremer.fragmentspractice.FragmentA">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="40dp"
android:src="#drawable/benz"/>
<com.example.dremer.fragmentspractice.CanvasView
android:id="#+id/signature_canvas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#FFFFFF"
android:background="#FFFFFF"/>
<Button
android:id="#+id/buttonAgain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scratch Again"
android:layout_gravity="bottom|center"
android:paddingBottom="20dp"/>
</FrameLayout>
Can you guys please help me with this?
Thanks!

Related

Draw on canvas wherever view is dragged

I am trying to create a simple paint app using canvas. The end product would be for the user to select a tool of choice (pen, marker, eraser, etc) and draw or erase accordingly anywhere the tool is dragged on the canvas.
As of now, I only have a pen and I am trying to draw a line wherever the pen is dragged in the canvas. However, I am finding this task challenging. I can drag the pen and I can draw lines, but I can't draw while I am dragging the pen. I am reaching out to the SO community to bridge these two features.
Below is what I have:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private ImageView w1;
private boolean clicked1 = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CanvasView canvasView = new CanvasView(MainActivity.this);
w1 = (ImageView) findViewById(R.id.wand1);
pl = (RelativeLayout) findViewById(R.id.coordAct);
RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.coordAct);
rootLayout.addView(canvasView);
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
canvasView.setLayoutParams(layoutParams1w2);
w1.setOnTouchListener(new ChoiceTouchListener());
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
public class ChoiceTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent event) {
if (!clicked1){
rootLayout = (ViewGroup) w1.getParent();
if (rootLayout != null) {
// detach the child from parent
rootLayout.removeView(w1);
}
RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
pl.addView(w1);
w1.setLayoutParams(layoutParams1);
clicked1 = true;
}
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
break;
}
rootLayout.invalidate();
return true;
}
}
CanvasView.java
public class CanvasView extends View{
Context context;
int width, height;
Bitmap bitmap;
Path path;
Canvas canvas;
Paint paint;
float mX, mY;
static final float TOLERANCE=4;
public CanvasView(Context context) {
super(context);
this.context=context;
path=new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(50);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w,h,oldw,oldh);
bitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
canvas=new Canvas(bitmap);
}
public void startTouch(float x, float y) {
path.moveTo(x, y);
mX = x;
mY = y;
}
public void moveTouch(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if(dx>=TOLERANCE || dy>= TOLERANCE) {
path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
mX=x;
mY=y;
}
}
//To clear canvas
public void clearCanvas() {
path.reset();
invalidate();
}
public void upTouch() {
path.lineTo(mX,mY);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
startTouch(x,y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x,y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
default:
return false;
}
invalidate();
return true;
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/coordAct"
tools:context="com.simplepaintapp.MainActivity">
<RelativeLayout
android:id="#+id/parLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3"
android:background="#0000ff">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="28dp"
android:background="#BA9DF7"
android:gravity="bottom"
android:orientation="vertical">
<HorizontalScrollView
android:id="#+id/backgd"
android:layout_width="match_parent"
android:layout_height="100dp"
android:weightSum="1">
<LinearLayout
android:id="#+id/parentLL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="5">
<ImageView
android:id="#+id/wand1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/pen" />
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
</RelativeLayout>
Current bug after implementing the dispatchTouchEvent() method inside onTouch()
An update to MainActivity and CanvasView is required. See the new source code below:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private ImageView w1;
private boolean clicked1 = false;
CanvasView canvasView;
public static int X;
public static int Y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
canvasView = new CanvasView(MainActivity.this);
w1 = (ImageView) findViewById(R.id.wand1);
pl = (RelativeLayout) findViewById(R.id.coordAct);
RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.coordAct);
rootLayout.addView(canvasView);
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
canvasView.setLayoutParams(layoutParams1w2);
w1.setOnTouchListener(new ChoiceTouchListener());
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
public class ChoiceTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent event) {
if (!clicked1){
rootLayout = (ViewGroup) w1.getParent();
if (rootLayout != null) {
// detach the child from parent
rootLayout.removeView(w1);
}
RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
pl.addView(w1);
w1.setLayoutParams(layoutParams1);
clicked1 = true;
}
X = (int) event.getRawX();
Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
canvasView.dispatchTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
canvasView.dispatchTouchEvent(event);
break;
}
rootLayout.invalidate();
return true;
}
}
CanvasView.java:
public class CanvasView extends View{
Context context;
int width, height;
Bitmap bitmap;
Path path;
public Canvas canvas;
Paint paint;
float mX, mY;
static final float TOLERANCE=4;
public static float x;
public static float y;
public CanvasView(Context context) {
super(context);
this.context=context;
path=new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(50);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w,h,oldw,oldh);
bitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
canvas=new Canvas(bitmap);
}
public void startTouch(float x, float y) {
path.moveTo(x, y);
mX = x;
mY = y;
}
public void moveTouch(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if(dx>=TOLERANCE || dy>= TOLERANCE) {
path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
mX=x;
mY=y;
}
}
//To clear canvas
public void clearCanvas() {
path.reset();
invalidate();
}
public void upTouch() {
path.lineTo(mX,mY);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
startTouch(MainActivity.X,MainActivity.Y-380);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(MainActivity.X,MainActivity.Y-380);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
default:
return false;
}
invalidate();
return true;
}

Android: How to make a canvas on only part of the screen dynamically?

In android, how can I make a drawable canvas appear on only part of the screen when a user does an action?
My end-goal is to dynamically insert into the layout a bar that, when the user touches it, a particular text will be drawn on the bar.
I've searched, and I've only seen ways where a canvas is handled as a layout itself; not as a View that can be added to an activity. And my understanding is that to make it only part of the screen, I'd somehow have to handle it as a View that can be added to a layout. How do I do this?
For creating a canvas create the custom view like as below:
public class CanvasView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
Context context;
private Paint mPaint;
private float mX, mY;
private static final float TOLERANCE = 5;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
context = c;
// we set a new Path
mPath = new Path();
// and we set a new Paint with the desired attributes
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(4f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// your Canvas will draw onto the defined Bitmap
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
// override onDraw
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw the mPath with the mPaint on the canvas when onDraw
canvas.drawPath(mPath, mPaint);
}
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
}
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
public void clearCanvas() {
mPath.reset();
invalidate();
}
// when ACTION_UP stop touch
private void upTouch() {
mPath.lineTo(mX, mY);
}
//override the onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
}
return true;
}
}
After that use this canvasView into the xml file:
<com.example.canvasdemo.CanvasView
android:id="#+id/signature_canvas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/colorWhite" />
And last into your main activity :
public class MainActivity extends AppCompatActivity {
Button btnClear;
private CanvasView customCanvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customCanvas = (CanvasView) findViewById(R.id.signature_canvas);
btnClear = (Button) findViewById(R.id.button1);
btnClear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customCanvas.clearCanvas(); // to clear canvas
}
});
}

Draw paint over image not blank space using canvas

I am trying to draw line over image, it works fine but i faced some problem. The problem is I want to draw line over image only, not blank space. This the code here the sizechanged method i declare like this.
class DrawingPaint extends View implements View.OnTouchListener {
private Canvas mCanvas;
private Path mPath;
private Paint mPaint, mBitmapPaint;
public ArrayList<PathPoints> paths = new ArrayList<PathPoints>();
private ArrayList<PathPoints> undonePaths = new ArrayList<PathPoints>();
private Bitmap mBitmap;
private int color;
private int x, y;
private String textToDraw = null;
private boolean isTextModeOn = false;
int lastColor = 0xFFFF0000;
static final float STROKE_WIDTH = 15f;
Matrix m;
int imageHeight,imageWidth;
public DrawingPaint(Context context/*, int color*/) {
super(context);
//this.color = color;
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
/*mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(STROKE_WIDTH);
mPaint.setTextSize(30);
mPath = new Path();
paths.add(new PathPoints(mPath, color, false));
mCanvas = new Canvas();*/
}
public void colorChanged(int color) {
this.color = color;
mPaint.setColor(color);
}
public void setColor(int color) {
mPaint = new Paint();
this.color = color;
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(color);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(STROKE_WIDTH);
mPaint.setTextSize(30);
mPath = new Path();
paths.add(new PathPoints(mPath, color, false));
mCanvas = new Canvas();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// mBitmap = AddReportItemActivity.mPhoto;
mBitmap = CustomGalleryHandler.getmInstance().getBitmapSend();
float xscale = (float) w / (float) mBitmap.getWidth();
float yscale = (float) h / (float) mBitmap.getHeight();
if (xscale > yscale) // make sure both dimensions fit (use the
// smaller scale)
xscale = yscale;
float newx = (float) w * xscale;
float newy = (float) h * xscale; // use the same scale for both
// dimensions
// if you want it centered on the display (black borders)
/*mBitmap = Bitmap.createScaledBitmap(mBitmap, this.getWidth(),
this.getHeight(), true);*/
// mCanvas = new Canvas(mBitmap);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(PreferenceForCustomCamera.getInstance().getImagePathForGalleryFullScreen()).getAbsolutePath(), options);
imageHeight = options.outHeight;
imageWidth = options.outWidth;
m = new Matrix();
RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
//onMeasure(imageWidth,imageHeight);
RectF viewRect = new RectF(0, 0, w, h);
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
mBitmap = Bitmap.createBitmap(mBitmap,0,0,imageWidth,
imageHeight, m,true);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
//setMeasuredDimension(this.getWidth(), this.getHeight());
//setMeasuredDimension(560, 100);even though give a ensured size, it can't //anyway.
}
#Override
protected void onDraw(Canvas canvas) {
float[] pts = {0, 0};
m.mapPoints(pts);
canvas.drawBitmap(mBitmap, pts[0], pts[1], mBitmapPaint);
// canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (PathPoints p : paths) {
mPaint.setColor(p.getColor());
Log.v("", "Color code : " + p.getColor());
if (p.isTextToDraw()) {
canvas.drawText(p.textToDraw, p.x, p.y, mPaint);
} else {
canvas.drawPath(p.getPath(), mPaint);
}
}
}
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;
}
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();
paths.add(new PathPoints(mPath, color, false));
}
private void drawText(int x, int y) {
this.x = x;
this.y = y;
paths.add(new PathPoints(color, textToDraw, true, x, y));
// mCanvas.drawText(textToDraw, x, y, mPaint);
}
#Override
public boolean onTouch(View arg0, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!isTextModeOn) {
touch_start(x, y);
invalidate();
}
break;
case MotionEvent.ACTION_MOVE:
if (!isTextModeOn) {
touch_move(x, y);
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (isTextModeOn) {
drawText((int) x, (int) y);
invalidate();
} else {
touch_up();
invalidate();
}
break;
}
return true;
}
public void onClickUndo() {
try {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
}
} catch (Exception e) {
e.toString();
}
}
public void onClickRedo() {
try {
if (undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
invalidate();
} else {
}
} catch (Exception e) {
e.toString();
}
}
/*class PathPoints {
private Path path;
// private Paint mPaint;
private int color;
private String textToDraw;
private boolean isTextToDraw;
private int x, y;
public PathPoints(Path path, int color, boolean isTextToDraw) {
this.path = path;
this.color = color;
this.isTextToDraw = isTextToDraw;
}
public PathPoints(int color, String textToDraw, boolean isTextToDraw,
int x, int y) {
this.color = color;
this.textToDraw = textToDraw;
this.isTextToDraw = isTextToDraw;
this.x = x;
this.y = y;
}
public Path getPath() {
return path;
}
public void setPath(Path path) {
this.path = path;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public String getTextToDraw() {
return textToDraw;
}
public void setTextToDraw(String textToDraw) {
this.textToDraw = textToDraw;
}
public boolean isTextToDraw() {
return isTextToDraw;
}
public void setTextToDraw(boolean isTextToDraw) {
this.isTextToDraw = isTextToDraw;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}*/
}
Perhaps you'd want to extend your customized view from ImageView it self.
public class Line extends ImageView {
private static final String TAG = "Line";
private Paint lineDraw = null;
private int mStartX = 0;
private int mStartY = 0;
private int mEndX = 0;
private int mEndY = 0;
private float mStrokeWidth = 0;
public Line(Context context) {
super(context);
init_Paint();
}
public Line(Context context, AttributeSet attrs) {
super(context, attrs);
init_Attributes(context, attrs);
init_Paint();
}
public Line(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init_Attributes(context, attrs);
init_Paint();
}
private void init_Paint()
{
lineDraw = new Paint(Paint.ANTI_ALIAS_FLAG);
lineDraw.setStyle(Paint.Style.FILL);
lineDraw.setColor(Color.BLACK);
lineDraw.setStrokeWidth(mStrokeWidth);
}
private void init_Attributes(Context context, AttributeSet attrs)
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Line);
mStartX = a.getInteger(R.styleable.Line_startX, 0);
mStartY = a.getInteger(R.styleable.Line_startY, 0);
mEndX = a.getInteger(R.styleable.Line_endX, 0);
mEndY = a.getInteger(R.styleable.Line_endY, 0);
mStrokeWidth = a.getDimension(R.styleable.Line_strokeWidth, 0);
a.recycle();
}
public void setStartX(int startX)
{
this.mStartX = startX;
}
public void setStartY(int startY)
{
this.mStartY = startY;
}
public void setEndX(int endX)
{
this.mEndX = endX;
}
public void setEndY(int endY)
{
this.mEndY = endY;
}
public void setStrokeWidth(float strokeWidth)
{
this.mStrokeWidth = strokeWidth;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
#Override
public void onDraw(Canvas canvas)
{
//Call ImageView's default onDraw() method.
super.onDraw(canvas);
// You can instead use canvas.drawPath();
canvas.drawLine(mStartX, mStartY, mEndX, mEndY, lineDraw);
}
}
In your attr.xml add the following.
<resources>
<declare-styleable name="Line">
<attr name="startX" format="integer" />
<attr name="endX" format="integer" />
<attr name="startY" format="integer" />
<attr name="endY" format="integer" />
<attr name="strokeWidth" format="dimension" />
</declare-styleable>
</resources>
and you can use this like so.
<views.customview.Line
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:startX="5"
app:startY="5"
app:endX="500"
app:endY="500"
app:strokeWidth="15dp"
android:src="#drawable/add_bookmark"
/>

How can I implement Pencil Shades like hb, 2b, 4b, etc. to draw anything in Canvas of my Android Application?

I need to implement the pencil shades from 9b to 9h with the list showing the shades on pencil button Click() and after clicking the list item, the pencil should change to its new shade. Also need the eraser implementation on erase button click to erase the path drawn by pencil.
This is the code for drawing with a fixed size pen on a canvas without a button click. And the clearCanvas() method is called on button click that clears the whole Canvas.
Any help would be appreciated.
public class MainActivity extends AppCompatActivity {
private CanvasView customCanvas;
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customCanvas = (CanvasView) findViewById(R.id.custom_canvas);
toolbar = (Toolbar) findViewById(R.id.actionBar);
setSupportActionBar(toolbar);
assert getSupportActionBar()!=null;
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
public void onClick(View view){
customCanvas.clearCanvas();
}
}
public class CanvasView extends View{
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
Context context;
private Paint mPaint, mErase;
private float mX, mY;
private static final float TOLERANCE = 5;
private boolean erase=false;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
// we set a new Path
mPath = new Path();
// and we set a new Paint with the desired attributes
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4f);
}
// override onSizeChanged
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// your Canvas will draw onto the defined Bitmap
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
// override onDraw
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw the mPath with the mPaint on the canvas when onDraw
canvas.drawPath(mPath, mPaint);
}
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
}
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
// Clear Canvas
public void clearCanvas(){
mPath.reset();
invalidate();
}
// when ACTION_UP stop touch
private void upTouch() {
mPath.lineTo(mX, mY);
}
//override the onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
}
return true;
}
}
XML file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/actionBar"
layout="#layout/action_bar" />
<View
android:layout_below="#+id/actionBar"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#2084AF" />
<com.admin.mainactivity.CanvasView
android:layout_below="#+id/actionBar"
android:id="#+id/custom_canvas"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

creating scratch card android

I'm trying to implement a simple "scratch card". The java code is taken by an android demo about painting (WHERE to find Android "Fingerpaint" demo? (Android Studio era)) and what i want is simply to show the image below the surfaceview.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/android"
android:scaleType="fitXY"
/>
<com.example.jammtup.ErasableView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/></RelativeLayout>
the java code :
public class ErasableView extends SurfaceView {
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mPaint;
private Path mPath;
private Paint mBitmapPaint;
public ErasableView(Context context) {
super(context);
mPaint = new Paint();
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
public void init() {
setFocusableInTouchMode(true);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(64);
mPaint.setColor(0xFFFF0000);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
#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.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, 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);
// 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;
} }
what i get is a black view not erasable. That does not allow to show the image below.
i need your help !!
Try to use this instead of your view If you want the whole project just check out my Github repository https://github.com/amarvadla/ScratchCoupon
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.support.v4.content.ContextCompat;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.TextView;
public class ScratchTextView extends TextView {
Bitmap scratchBitmap;
public interface IRevealListener {
public void onRevealed(ScratchTextView tv);
public void onRevealPercentChangedListener(ScratchTextView stv, float percent);
}
public static final float STROKE_WIDTH = 12f;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
/**
* Bitmap holding the scratch region.
*/
private Bitmap mScratchBitmap;
/**
* Drawable canvas area through which the scratchable area is drawn.
*/
public static Canvas mCanvas;
/**
* Path holding the erasing path done by the user.
*/
private Path mErasePath;
/**
* Path to indicate where the user have touched.
*/
private Path mTouchPath;
/**
* Paint properties for drawing the scratch area.
*/
private Paint mBitmapPaint;
/**
* Paint properties for erasing the scratch region.
*/
private Paint mErasePaint;
/**
* Gradient paint properties that lies as a background for scratch region.
*/
private Paint mGradientBgPaint;
/**
* Sample Drawable bitmap having the scratch pattern.
*/
private BitmapDrawable mDrawable;
/**
* Listener object callback reference to send back the callback when the text has been revealed.
*/
private IRevealListener mRevealListener;
/**
* Reveal percent value.
*/
private float mRevealPercent;
/**
* Thread Count
*/
private int mThreadCount = 0;
public ScratchTextView(Context context) {
super(context);
init();
}
public ScratchTextView(Context context, AttributeSet set) {
super(context, set);
init();
}
public ScratchTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* Set the strokes width based on the parameter multiplier.
* #param multiplier can be 1,2,3 and so on to set the stroke width of the paint.
*/
public void setStrokeWidth(int multiplier) {
mErasePaint.setStrokeWidth(multiplier * STROKE_WIDTH);
}
/**
* Initialises the paint drawing elements.
*/
private void init() {
mTouchPath = new Path();
mErasePaint = new Paint();
mErasePaint.setAntiAlias(true);
mErasePaint.setDither(true);
mErasePaint.setColor(0xFFFF0000);
mErasePaint.setStyle(Paint.Style.STROKE);
mErasePaint.setStrokeJoin(Paint.Join.BEVEL);
mErasePaint.setStrokeCap(Paint.Cap.ROUND);
mErasePaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.CLEAR));
setStrokeWidth(6);
mGradientBgPaint = new Paint();
mErasePath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
scratchBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.spiderman);
mDrawable = new BitmapDrawable(getResources(), scratchBitmap);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mScratchBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mScratchBitmap);
Rect rect = new Rect(0, 0, mScratchBitmap.getWidth(), mScratchBitmap.getHeight());
mDrawable.setBounds(rect);
int startGradientColor = ContextCompat.getColor(getContext(), R.color.colorPrimary);
int endGradientColor = ContextCompat.getColor(getContext(), R.color.colorAccent);
mCanvas.drawRect(rect, mGradientBgPaint);
mDrawable.draw(mCanvas);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mScratchBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mErasePath, mErasePaint);
}
private void touch_start(float x, float y) {
mErasePath.reset();
mErasePath.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) {
mErasePath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
drawPath();
}
mTouchPath.reset();
mTouchPath.addCircle(mX, mY, 30, Path.Direction.CW);
}
private void drawPath() {
mErasePath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mErasePath, mErasePaint);
// kill this so we don't double draw
mTouchPath.reset();
mErasePath.reset();
mErasePath.moveTo(mX, mY);
checkRevealed();
}
/**
* Reveals the hidden text by erasing the scratch area.
*/
public void reveal() {
int[] bounds = getTextBounds(1.5f);
int left = bounds[0];
int top = bounds[1];
int right = bounds[2];
int bottom = bounds[3];
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.CLEAR));
mCanvas.drawRect(left, top, right, bottom, paint);
checkRevealed();
invalidate();
}
#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:
drawPath();
invalidate();
break;
default:
break;
}
return true;
}
public int getColor() {
return mErasePaint.getColor();
}
public void setRevealListener(IRevealListener listener) {
this.mRevealListener = listener;
}
public boolean isRevealed() {
return mRevealPercent == 1;
}
private void checkRevealed() {
if(! isRevealed() && mRevealListener != null) {
int[] bounds = getTextBounds();
int left = bounds[0];
int top = bounds[1];
int width = bounds[2] - left;
int height = bounds[3] - top;
// Do not create multiple calls to compare.
if(mThreadCount > 1) {
return;
}
mThreadCount++;
new AsyncTask<Integer, Void, Float>() {
#Override
protected Float doInBackground(Integer... params) {
try {
int left = params[0];
int top = params[1];
int width = params[2];
int height = params[3];
Bitmap croppedBitmap = Bitmap.createBitmap(mScratchBitmap, left, top, width, height);
return BitmapUtils.getTransparentPixelPercent(croppedBitmap);
} finally {
mThreadCount--;
}
}
public void onPostExecute(Float percentRevealed) {
// check if not revealed before.
if( ! isRevealed()) {
float oldValue = mRevealPercent;
mRevealPercent = percentRevealed;
if(oldValue != percentRevealed) {
mRevealListener.onRevealPercentChangedListener(ScratchTextView.this, percentRevealed);
}
// if now revealed.
if( isRevealed()) {
mRevealListener.onRevealed(ScratchTextView.this);
}
}
}
}.execute(left, top, width, height);
}
}
private static int[] getTextDimens(String text, Paint paint) {
int end = text.length();
Rect bounds = new Rect();
paint.getTextBounds(text, 0, end, bounds);
int width = bounds.left + bounds.width();
int height = bounds.bottom + bounds.height();
return new int[] { width, height};
}
private int[] getTextBounds() {
return getTextBounds(1f);
}
private int[] getTextBounds(float scale) {
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
int vwidth = getWidth();
int vheight = getHeight();
int centerX = vwidth/2;
int centerY = vheight/2;
TextPaint paint = getPaint();
String text = getText().toString();
int[] dimens = getTextDimens(text, paint);
int width = dimens[0];
int height = dimens[1];
int lines = getLineCount();
height = height * lines;
width = width / lines;
int left = 0;
int top = 0;
if(height > vheight) {
height = vheight - ( paddingBottom + paddingTop);
}
else {
height = (int) (height * scale);
}
if(width > vwidth) {
width = vwidth - (paddingLeft + paddingRight);
}
else {
width = (int) (width * scale);
}
int gravity = getGravity();
//todo Gravity.START
if((gravity & Gravity.LEFT) == Gravity.LEFT) {
left = paddingLeft;
}
//todo Gravity.END
else if((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
left = (vwidth - paddingRight) - width;
}
else if((gravity & Gravity.CENTER_HORIZONTAL) == Gravity.CENTER_HORIZONTAL) {
left = centerX - width / 2;
}
if((gravity & Gravity.TOP) == Gravity.TOP) {
top = paddingTop;
}
else if((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
top = (vheight - paddingBottom) - height;
}
else if((gravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL) {
top = centerY - height / 2;
}
return new int[] {left, top, left + width, top + height};
}

Categories

Resources