if i draw two lines using pathshape in shapedrawble that both have the same starting point, they appear to be drawn at different starting points on the screen. when i draw two lines at the same starting point but at different angles they can in the right circumstances appear to be drawn at different starting points as seen below. This is driving me crazy, any help would be appreciated.
public class drawtest extends View {
private ShapeDrawable mDrawable;
Canvas can = null;
float startx;
float starty;
float endx;
float endy;
float width = 0;
float canvasWidth = 0;
float canvasHeight = 0;
private Paint mBitmapPaint;
float height;
Bitmap bm = null;
Path p;
public drawtest(Context context) {
super(context);
endy=0;
endx=0;
startx=0;
starty=0;
width = 0;
height = 0;
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(0, 0, 0, 0);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
canvasHeight = h;
canvasWidth = w;
super.onSizeChanged(w, h, oldw, oldh);
bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
can = new Canvas(bm);
}
public void test(){
setStart(canvasWidth/2, canvasHeight/2);
double r = 125;
double tempx = 236;
double h = startx;
double k = starty;
//(x-h)^2 + (y-k)^2 = r^2
//y = sqrt(r^2 - (x-h)^2) + k
for(int i = 0; i < 2; ++i){
double tempy = Math.sqrt((r*r) - Math.pow((tempx - h),2)) + k;
setEnd((float) tempx, (float) tempy);
draw();
invalidate();
newCanvas();
tempx+=56;
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.drawBitmap(bm, 0, 0, mBitmapPaint);
mDrawable.draw(canvas);
canvas.restore();
}
void newCanvas(){
mDrawable.draw(can);
can.save();
}
public void setStart(float X, float Y){
startx = X;
starty = Y;
}
public void setEnd(float X, float Y){
endx = X;
endy = Y;
width = Math.abs(endx - startx);
height = Math.abs(endy - starty);
}
private void getnewshape() {
p = new Path();
p.moveTo(startx, starty);
p.lineTo(endx, endy);
mDrawable = new ShapeDrawable(new PathShape(p, width, height));
}
public void draw() {
getnewshape();
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.getPaint().setStyle(Paint.Style.STROKE);
mDrawable.setBounds(0, 0, (int) width, (int) height);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
test();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
}
return true;
}
}
Related
I have created a custom view so that i can draw shapes on clicks and preform some action
and i have created a method called fillOnTouch(); which is supposed to take a paint and canvas as parameters then draw colored circles on the canvas when i call this method from TouchEvent it doesn't draw on the canvas so I tried to create a path called coloredCircles and have added shapes to it on Touchevent then draw this path on onDraw method but the result is the same the shapes aren't drawen in the canvas as it's supposed to be
onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(x, y);
coloredCircles.addCircle(x, y, 20, Path.Direction.CW);
checkStrokeInRightPath(x, y);
FillLetters.fillCircleOnTouch(x, y, fillCircles, dataLists, mCanvas);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
checkStrokeInRightPath(x, y);
FillLetters.fillCircleOnTouch(x, y, fillCircles, dataLists, mCanvas);
coloredCircles.addCircle(x, y, 20, Path.Direction.CW);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp();
checkStrokeInRightPath(x, y);
FillLetters.fillCircleOnTouch(x, y, fillCircles, dataLists, mCanvas);
coloredCircles.addCircle(x, y, 20, Path.Direction.CW);
invalidate();
break;
}
return true;
}
fillOnTouch Method
public static void fillCircleOnTouch(float x, float y, Paint paint, List<List<Integer>> circleList, Canvas canvas) {
List<Integer> xPoints, yPoints, circleCount;
int r = DrawLetters.radius;
float xStart, xEnd, yStart, yEnd;
if (!circleList.isEmpty()) {
xPoints = circleList.get(0);
yPoints = circleList.get(1);
circleCount = circleList.get(2);
if (iterationCount < xPoints.size()) {
float nextCircleX = xPoints.get(iterationCount);
float nextCircleY = yPoints.get(iterationCount);
paint.setColor(blendColors("#FFFF00", "#0000FF", (circleCount.get(iterationCount)) * ((float) (1.0 / xPoints.size()))));
xStart = nextCircleX - r;
xEnd = nextCircleX + r;
yStart = nextCircleY - r;
yEnd = nextCircleY + r;
Range<Float> xRange = new Range<>(xStart, xEnd);
Range<Float> yRange = new Range<>(yStart, yEnd);
if (xRange.contains(x) && yRange.contains(y)) {
canvas.drawCircle(nextCircleX, nextCircleY, r, paint);
iterationCount++;
}
}
}
}
onDraw Method
#Override
protected void onDraw(Canvas canvas) {
// save the current state of the canvas before,
// to draw the background of the canvas
canvas.save();
// DEFAULT color of the canvas
int backgroundColor = Color.WHITE;
mCanvas.drawColor(backgroundColor);
// now, we iterate over the list of paths
// and draw each path on the canvas
for (Stroke fp : paths) {
mPaint.setColor(fp.color);
mPaint.setStrokeWidth(fp.width);
mCanvas.drawPath(fp.path, mPaint);
}
if (coloredCircles != null && !coloredCircles.isEmpty()) {
canvas.drawPath(coloredCircles, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
I can create circle on touch but can not remove the previous one. I have manage to remove the very first circle but the code is poor and it does not really work as I want. I like to draw circle every time I touch the screen and remove the previous circle . So the screen starts with a circle and as I will touch a new position the previous should be removed and there will be a new one.So how to do that part?
Here is my work:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Display display = new Display(this);
display.init();
display.backPaint.setColor(Color.WHITE);
setContentView(display);
}
static class Display extends View {
ArrayList<Point> points = new ArrayList();
int touch1_x=700;
int touch1_y=700;
Paint backPaint;
Paint circlePaint;
Paint circlePaint2;
Display(Context context) {
super(context);
}
void init() {
backPaint = new Paint();
backPaint.setColor(Color.WHITE);
backPaint.setStyle(Paint.Style.FILL);
circlePaint = new Paint();
circlePaint.setColor(Color.YELLOW);
circlePaint2 = new Paint();
circlePaint2.setColor(Color.WHITE);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getActionMasked()) {
// if (event.getX(event.getActionIndex()) > 100 && event.getX(event.getActionIndex()) < 200) {
touch1_x = (int) event.getX(event.getActionIndex());
touch1_y = (int) event.getY(event.getActionIndex());
// }
System.out.println("touch1_x ===" + touch1_x);
points.add(new Point(touch1_x, touch1_y));
points.add(new Point(touch1_x, touch1_y));
return true;
}
return false;
}
});
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), backPaint);
canvas.drawCircle(touch1_x, touch1_y, 50, circlePaint);
for(Point p: points){
canvas.drawCircle(p.x, p.y, 50, circlePaint);
}
for(Point p: points){
canvas.drawCircle(p.x, p.y, 50,circlePaint2 );
}
invalidate();
}
}
}
relevant question
You could erase canvas before drawing the next circle, using
canvas.drawColor(Color.TRANSPARENT,Mode.CLEAR);
import turtle
t=turtle.Turtle()
wn=turtle.Screen()
for count in range(360):
t.fd(3)
t.rt(1)
wn.exitonclick()
I have a customised view for photo annotate, you can use this to do your job.
1: Create a file AnnotationView.java and copy the following code
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
/**
* #author Bob Gao
* http://bobgao.net
*/
public class AnnotationView extends ImageView implements OnTouchListener {
private static final float KEY_STROKE_WIDTH = 4;
private List<Annotation> annotations = new ArrayList<Annotation>();
private Annotation mAnnotation;
private Canvas mCanvas;
private Paint mPaint;
// private Rect mOutRect;
public AnnotationView(Context context) {
super(context);
setOnTouchListener(this);
setDrawingCacheEnabled(true);
setScaleType(ScaleType.FIT_XY);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.mCanvas = canvas;
for (Annotation annotation : annotations) {
mPaint.setColor(annotation.getColor());
switch (annotation.getShape()) {
case Annotation.KEY_SHAPE_CIRCLE:
drawCircle(annotation.getX(), annotation.getY(), annotation.getRadius());
break;
case Annotation.KEY_SHAPE_ARROW:
drawAL((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
case Annotation.KEY_SHAPE_SQUARES:
drawRect((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius());
break;
case Annotation.KEY_SHAPE_TRIANGLE:
drawTriangle((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
}
}
}
/**
* Draw a triangle
*
* #param x
* #param y
* #param r
*/
public void drawTriangle(int x, int y, int r, float degree) {
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x - 2 * r, y + 2 * r);
path.lineTo(x + 2 * r, y + 2 * r);
path.lineTo(x, y);
path.close();
rotatePath(path, degree);
mCanvas.drawPath(path, mPaint);
}
public void drawRect(int x, int y, int r) {
int lenght = 4 * r;
int left = x - lenght / 2;
int top = y - lenght / 2;
int right = x + lenght / 2;
int bottom = y + lenght / 2;
Path path = new Path();
path.moveTo(left, top);
path.lineTo(right, top);
path.lineTo(right, bottom);
path.lineTo(left, bottom);
path.lineTo(left, top);
path.close();
mCanvas.drawPath(path, mPaint);
}
public void drawCircle(float x, float y, float r) {
mCanvas.drawCircle(x, y, r, mPaint);
}
/**
* Draw arrow
*
* #param sx
* #param sy
* #param ex
* #param ey
*/
public void drawAL(int sx, int sy, int r, float degree) {
int ex = (int) (sx + 2 * r);
int ey = (int) (sy + 2 * r);
switch (new Float(degree).intValue()) {
case 90:
ex = (int) (sx - 2 * r);
ey = (int) (sy + 2 * r);
break;
case 180:
ex = (int) (sx - 2 * r);
ey = (int) (sy - 2 * r);
break;
case 270:
ex = (int) (sx + 2 * r);
ey = (int) (sy - 2 * r);
break;
}
double H = 8; // the height of arrow
double L = 3.5; // half of bottom line
int x3 = 0;
int y3 = 0;
int x4 = 0;
int y4 = 0;
double awrad = Math.atan(L / H); // the rotation of arrow
double arraow_len = Math.sqrt(L * L + H * H); // the length of arrow
double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
double x_3 = ex - arrXY_1[0]; // (x3,y3) the first point
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4) the second point
double y_4 = ey - arrXY_2[1];
Double X3 = new Double(x_3);
x3 = X3.intValue();
Double Y3 = new Double(y_3);
y3 = Y3.intValue();
Double X4 = new Double(x_4);
x4 = X4.intValue();
Double Y4 = new Double(y_4);
y4 = Y4.intValue();
// draw line
mCanvas.drawLine(sx, sy, ex, ey, mPaint);
Path triangle = new Path();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.close();
mCanvas.drawPath(triangle, mPaint);
}
// Calculate
public double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen) {
double mathstr[] = new double[2];
// 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
double vx = px * Math.cos(ang) - py * Math.sin(ang);
double vy = px * Math.sin(ang) + py * Math.cos(ang);
if (isChLen) {
double d = Math.sqrt(vx * vx + vy * vy);
vx = vx / d * newLen;
vy = vy / d * newLen;
mathstr[0] = vx;
mathstr[1] = vy;
}
return mathstr;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
if (mAnnotation != null) {
float minX = 0;
float minY = 0;
float maxX = 0;
float maxY = 0;
switch (mAnnotation.getShape()) {
case Annotation.KEY_SHAPE_ARROW:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
case Annotation.KEY_SHAPE_SQUARES:
minX = getLeft() + mAnnotation.getRadius() / 2;
minY = getTop() + mAnnotation.getRadius() / 2;
maxX = getLeft() + getWidth() - mAnnotation.getRadius() / 2;
maxY = getTop() + getHeight() - mAnnotation.getRadius() / 2;
break;
case Annotation.KEY_SHAPE_CIRCLE:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
case Annotation.KEY_SHAPE_TRIANGLE:
minX = getLeft() + mAnnotation.getRadius();
minY = getTop() + mAnnotation.getRadius();
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
}
if (x > minX && x < maxX && y > minY && y < maxY) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
case MotionEvent.ACTION_MOVE:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
break;
}
}
return true;
}
return false;
}
public void startAnnotate(String pathName) {
mAnnotation = new Annotation();
mAnnotation.setMaxRadius(getWidth() / 2);
mAnnotation.setColor(Color.RED);
mAnnotation.setX(getWidth() / 2);
mAnnotation.setY(getHeight() / 2);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
annotations.add(mAnnotation);
postInvalidate();
}
public void stopAnnotate() {
if (annotations.isEmpty()) {
mPaint = null;
mAnnotation = null;
} else {
annotations.remove(annotations.size() - 1);
if (annotations.isEmpty()) {
mAnnotation = null;
mPaint = null;
} else {
mAnnotation = annotations.get(annotations.size() - 1);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mAnnotation.getColor());
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
}
}
postInvalidate();
}
public void plus() {
if (mAnnotation != null) {
mAnnotation.plus();
postInvalidate();
}
}
public void sub() {
if (mAnnotation != null) {
mAnnotation.sub();
postInvalidate();
}
}
public void rotateRight() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() >= 360) {
mAnnotation.setDegree(0);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() + 90);
}
postInvalidate();
}
}
public void rotateLeft() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() <= 0) {
mAnnotation.setDegree(270);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() - 90);
}
postInvalidate();
}
}
public void changeColor(int color) {
if (mAnnotation != null) {
mAnnotation.setColor(color);
mPaint.setColor(color);
}
postInvalidate();
}
/**
* Change the shape
*
* #param id
*/
public void changeShape(int id) {
if (mAnnotation != null) {
mAnnotation.setShape(id);
postInvalidate();
}
}
/**
* Draw line
*
* #param fromX
* start point x
* #param fromY
* start point y
* #param toX
* end point x
* #param toY
* end point y
*/
public void drawLine(float fromX, float fromY, float toX, float toY) {
Path linePath = new Path();
linePath.moveTo(fromX, fromY);
linePath.lineTo(toX, toY);
linePath.close();
mCanvas.drawPath(linePath, mPaint);
invalidate();
}
public List<Annotation> getAnnotations() {
return annotations;
}
private void rotatePath(Path path, float degree) {
Matrix mMatrix = new Matrix();
RectF bounds = new RectF();
path.computeBounds(bounds, true);
mMatrix.postRotate(degree, (bounds.right + bounds.left) / 2, (bounds.bottom + bounds.top) / 2);
path.transform(mMatrix);
}
}
2. In your activity, create the AnnotationView and assign your image to it, then append this view to your root view.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AnnotationView mPreview = (FrameLayout) findViewById(R.id.camera_preview);
AnnotationView mAnnotationView = new AnnotationView(this);
Bitmap bitmap;
try {
bitmap = CBitmapUtil.decode(mPictureFile); // Get your image as a bitmap
mAnnotationView.setImageBitmap(bitmap);
mPreview.addView(mAnnotationView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, "Photo cannot be saved, please try again later.", Toast.LENGTH_SHORT).show();
}
}
I have created a 10x10 grid for a game, and now i am trying to get the image i have for the player to display inside one of the grid squares. I have a Game, Player and Draw class. in the Game class the x and y position of the player are set, in the Player class is where i set the values for the x and y position and create the bitmap. In the Draw class I create the grid and call it in the onDraw method. I was wondering how do I call the bitmap in the onDraw so that it will display? I dont know if this makes any sense but any help or tips would be good.
public class Game {
Bitmap image;
int x;
int y;
int height;
int width;
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public int getX()
{
return x;
}
public int getY(){
return y;
}
public int getHeight(){
return height;
}
public int getWidth(){
return width;
}
}
public class Player extends Game {
public Player(Bitmap res, int w, int h, Context context){
image = res;
x = 300;
y = 300;
height = 300;
width = 300;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.sokobanplayer1);
}
}
public class Draw extends View {
Paint red = new Paint();
Paint green = new Paint();
int rectSide = 1000;
public Draw(Context context) {
super(context);
red.setColor(Color.RED);
green.setColor(Color.GREEN);
red.setStrokeWidth(8);
green.setStrokeWidth(8);
}
public void drawGrid(Canvas canvas) {
int width = canvas.getWidth();
int height = canvas.getHeight();
float startX = (width / 2) - (rectSide / 2);
float stopX = (width / 2) + (rectSide / 2);
float startY = (height / 2) - (rectSide / 2);
float stopY = (height / 2) + (rectSide / 2);
for (int i = 0; i < 1100; i += 100) {
float newY = startY + i;
canvas.drawLine(startX, newY, stopX, newY, green);
}
for (int i = 0; i < 1100; i += 100) {
float newX = startX + i;
canvas.drawLine(newX, startY, newX, stopY, green);
}
}
public void drawPlayer(Bitmap res, int w, int h, Context context){
Bitmap image = res;
int x = 300;
int y = 300;
int height = 300;
int width = 300;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.sokobanplayer1);
}
#Override
public void onDraw(Canvas canvas) {
drawGrid(canvas);
//canvas.getResources(image, x, y, null);
}
}
I am making a tictactoe android application . After making on customview called TicTacToeGFX I tried to make an onTouchEvent which (after taking into account) the coordinates of the touch , it would fill the corresponding rectangle with the bitmap circle or cross. The Problem is that in the onTouchEvent I cannot redraw the canvas with the desired Bitmap. So my question is How to I re-draw a canvas after an onTouchEvent?
public class NewGame extends Activity {
TicTacToeGFX Game;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Game = new TicTacToeGFX(this);
setContentView(Game);
}
}
public class TicTacToeGFX extends View {
int x, y;
int rectanglescounter = 0;
public Rect[] rectangles = new Rect[9];
// BitMap
Bitmap cross = BitmapFactory.decodeResource(getResources(),
R.drawable.cross1);
Bitmap circle = BitmapFactory.decodeResource(getResources(),
R.drawable.circle1);
Bitmap empty = BitmapFactory.decodeResource(getResources(),
R.drawable.empty1);
Paint paint = new Paint();
Canvas canvas = new Canvas();
public TicTacToeGFX(Context context) {
super(context);
setFocusable(true);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// -------------------------------------------calculate
// screen------------------------------------------------------
x = (int) ((getWidth()) / 3);
y = (int) ((getHeight()) / 3);
// //------------------------------------------- calculate rectangle
// positions on
// screen------------------------------------------------------
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
rectangles[rectanglescounter] = new Rect((x * j), (y * i),
((x * j) + x), ((y * i) + y));
if (rectanglescounter < 8)
rectanglescounter++;
else
break;
}
}
// ------------------------------------------- draw the canvas with
// empty Bitmap
// ------------------------------------------------------
int counter = 0;
canvas.drawRGB(0, 0, 0);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
canvas.drawBitmap(empty, null, rectangles[counter], null);
counter++;
}
}
// ------------------------------------------- draw
// LinesS------------------------------------------------------
paint.setColor(Color.WHITE);
canvas.drawLine(x, 0, x, 3 * y, paint);// 1h
canvas.drawLine(2 * x, 0, 2 * x, 3 * y, paint);// 2h
canvas.drawLine(0, y, 3 * x, y, paint);// 3h
canvas.drawLine(0, 2 * y, 3 * x, 2 * y, paint);// 4h
}
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
x = (int) event.getX();
y = (int) event.getY();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
Toast.makeText(getContext(), "Hello", 1).show();
canvas.drawRGB(0, 0, 0);
invalidate();
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
break;
}
return true;
}
}
OK,
I'm trying to make a app that has a Scratch off feature (like scratch off tickets from the loto).
I've been digging around and can not find the a way to tell how much of my canvas is covered by my parent/color. See what i want is that they have to uncover x% of the background image before they can "click" to claim.
I did find the answer to the original question. but a new one has come up dealing with the same thing.
when calculating out the percent "int percent = (trans_count / max_count) * 100;" it always returns 0 and in the my app the max_count is always 90000 (because of the picture size and my androids screen).
Here is my current code.
class TouchView extends ImageButton {
public Boolean Clickable = false;
private Bitmap bgr = null;
private Bitmap overlayDefault;
private Bitmap overlay;
private Paint pTouch;
private int X = -100;
private int Y = -100;
private Canvas c2;
public TouchView(Context context) { super(context); build();}
public TouchView(Context context, AttributeSet attrs) { super(context, attrs); build(attrs); }
public TouchView(Context context, AttributeSet attrs, Integer params) { super(context, attrs, params); build(attrs);}
private void build()
{
bgr = BitmapFactory.decodeResource(getResources(),R.drawable.loser);
overlayDefault = BitmapFactory.decodeResource(getResources(),R.drawable.over);
overlay = BitmapFactory.decodeResource(getResources(), R.drawable.over).copy(Config.ARGB_8888, true);
pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);
pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
pTouch.setColor(Color.TRANSPARENT);
pTouch.setMaskFilter(new BlurMaskFilter(2, Blur.NORMAL));
pTouch.setStrokeWidth(20);
}
private void build(AttributeSet attrs)
{
bgr = BitmapFactory.decodeResource(getResources(),R.drawable.loser);
overlayDefault = BitmapFactory.decodeResource(getResources(),R.drawable.over);
overlay = BitmapFactory.decodeResource(getResources(), R.drawable.over).copy(Config.ARGB_8888, true);
pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);
pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
pTouch.setColor(Color.TRANSPARENT);
pTouch.setMaskFilter(new BlurMaskFilter(2, Blur.NORMAL));
pTouch.setStrokeWidth(20);
}
public void setAsWinner() {
bgr = BitmapFactory.decodeResource(getResources(), R.drawable.winner);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
int sX = X;
int sY = Y;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
c2.drawCircle(X, Y, 5, pTouch);
break;
}
case MotionEvent.ACTION_MOVE: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
c2.drawLine(sX, sY, X, Y, pTouch);
break;
}
case MotionEvent.ACTION_UP:
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
c2.drawLine(sX, sY, X, Y, pTouch);
break;
}
try
{
int pixels[] = new int[(overlay.getWidth() * overlay.getHeight())];
overlay.getPixels(pixels, 0, overlay.getWidth(), 0, 0, overlay.getWidth(), overlay.getHeight());
int max_count = pixels.length;
int trans_count = 0;
for(int i = 0 ; i < max_count; i++)
{
if (pixels[i] == 0)
trans_count++;
}
int percent = (trans_count / max_count) * 100;
if (percent > 60)
{
Clickable = true;
}
}
catch (IllegalArgumentException e)
{
Log.i ("info", e.getMessage());
}
catch (ArrayIndexOutOfBoundsException e)
{
Log.i ("info", e.getMessage());
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw background
if (bgr != null)
canvas.drawBitmap(bgr, 0, 0, null);
if (c2 == null)
{
int width = overlay.getWidth();
int height = overlay.getHeight();
RectF bounds = new RectF(canvas.getClipBounds());
float scaleWidth = bounds.width() / width;
float scaleHeight = bounds.height() / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
overlay = Bitmap.createBitmap(overlay,0, 0, width, height, matrix, true);
c2 = new Canvas(overlay);
}
canvas.drawBitmap(overlay, 0, 0, null);
}
}
trans_count and max_count are integers so java performs integer division when you do trans_count/max_count and the result is 0 because trans_count is smaller than max_count. What you want is floating point division, you can force it like this:
double percentage = 100.0 * trans_count / max_count;
Basically what will happen is that 100.0 * trans_count will get executed first giving a floating point value (because one of the values is floating point), then the result will be divided by max_count again giving a floating point value.