Saving bitmaps to ArrayList makes Bitmaps whole black - java

I am trying to save bitmaps in an ArrayList. I generate 2 types of bitmaps, they are basically identical - drawn with a finger by the user.
The first bitmap is fully visible in activity
The second is stored dynamically in the ArrayList - it is a slice of the last x milliseconds from the visible bitmap - It will be further converting and sending by BT.
The problem is that the last bitmap in the ArrayList is well saved, while each previous bitmap turns into a black rectangle when you add another one.
Relevant code snippets:
private ArrayList<Bitmap> bitmapsListToSend = new ArrayList<>();
private ArrayList<Canvas> canvasListToSend = new ArrayList<>();
mBitmapToShow = Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565);
mCanvasToShow = new Canvas(mBitmapToShow);
bitmapsListToSend.add(Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565))
//mCanvasToSend = new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1));
canvasListToSend.add(new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));;
I tried to make separate Canvas to each bitmap without success
public class PaintView extends View {
private final Paint mPaintToShow = new Paint();
private Bitmap mBitmapToShow;
private Canvas mCanvasToShow;
private final Paint mPaintToSend = new Paint();
//private Canvas mCanvasToSend;
private TouchPoint startPoint;
#Nullable
private ArrayList<Bitmap> bitmapsListToSend = new ArrayList<>();
private ArrayList<Canvas> canvasListToSend = new ArrayList<>();
private int bitmapCounter = 0;
private int alpha = 1;
/* debug */
Stopwatch watch = Stopwatch.createUnstarted();
public PaintView(Context c) {
super(c);
setFocusable(true);
mPaintToShow.setAntiAlias(true);
mPaintToShow.setColor(BLACK);
mPaintToShow.setAlpha(alpha);
mPaintToShow.setStrokeJoin(Paint.Join.ROUND);
mPaintToShow.setStrokeCap(Paint.Cap.ROUND);
mPaintToSend.setAntiAlias(true);
mPaintToSend.setColor(BLACK);
mPaintToSend.setStrokeJoin(Paint.Join.ROUND);
mPaintToSend.setStrokeCap(Paint.Cap.ROUND);
mBitmapToShow = Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565);
mCanvasToShow = new Canvas(mBitmapToShow);
bitmapsListToSend.add(Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565));
//mCanvasToSend = new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1));
canvasListToSend.add(new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCanvasToShow.drawColor(Color.WHITE);
//mCanvasToSend.drawColor(Color.WHITE);
canvasListToSend.get(canvasListToSend.size()-1).drawColor(WHITE);
}
public void clear() {
if (mCanvasToShow != null) {
mPaintToShow.setColor(Color.WHITE);
mCanvasToShow.drawPaint(mPaintToShow);
//mCanvasToSend.drawPaint(mPaintToShow);
bitmapCounter=0;
alpha=1;
bitmapsListToSend.clear();
canvasListToSend.clear();
mPaintToShow.setColor(BLACK);
watch.reset();
invalidate();
}
}
#Override
protected void onDraw(Canvas canvas) {
if (mBitmapToShow != null) {
canvas.drawBitmap(mBitmapToShow, 0, 0, null);
//mCanvasToSend.drawBitmap(bitmapsListToSend.get(bitmapsListToSend.size()-1), 0, 0, null);
}
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
return onTouchOrHoverEvent(event, true /*isTouch*/);
}
private boolean onTouchOrHoverEvent(MotionEvent event, boolean isTouch) {
/*if (SENDING_NOW)
return true;*/
final int action = event.getActionMasked();
mPaintToShow.setStrokeWidth((float) ( getBrushSize() ));
if (action == MotionEvent.ACTION_DOWN) {
startPoint = new TouchPoint(event, 0);
runnableSaveBitmaps.run();
runnableChangeAlpha.run();
watch.start();
}else if(action == MotionEvent.ACTION_MOVE){
runnableChangeAlpha.run();
}else if (action == MotionEvent.ACTION_UP) {
startPoint = new TouchPoint(event, 0);
handlerSaveBitmaps.removeCallbacks(runnableSaveBitmaps);
handlerChangeAlpha.removeCallbacks(runnableChangeAlpha);
watch.stop();
}
//make drawings//
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
paintLines(mTouchPoints);
break;
case MotionEvent.ACTION_DOWN:
mCanvasToShow.drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToShow);
//mCanvasToSend.drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToSend);
canvasListToSend.get(canvasListToSend.size()-1).drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToSend);
break;
}
invalidate();
}
return true;
}
//drawing methods//
Handler handlerSaveBitmaps = new Handler();
Runnable runnableSaveBitmaps = new Runnable() {
public void run() {
handlerSaveBitmaps.postDelayed(runnableSaveBitmaps, 10);
Log.v("B", "Bitmap added " + bitmapCounter + " " + (watch.toString()));
bitmapsListToSend.add(bitmapCounter, Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565));
canvasListToSend.add(bitmapCounter++, new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));
}
};
Handler handlerChangeAlpha = new Handler();
Runnable runnableChangeAlpha = new Runnable() {
#Override
public void run() {
handlerChangeAlpha.postDelayed(runnableChangeAlpha, 635);
if(alpha < 255)
mPaintToShow.setAlpha(alpha++);
else {
handlerChangeAlpha.removeCallbacks(runnableChangeAlpha);
Log.v("A", "ALPHA MAX" + (watch.toString()));
}
}
};
}
If Runnable saves 100 bitmaps - 99 will be black, the last one will be ok
//Bitmap.copy() fixed it

Related

MLKit face detection stopping after some time while simultaneously running a game

Im using the MLKit combined with the CameraX Image-Analysis Use Case to build an App, that lets you control a cursor, which gets drawn onto an overlay based on the position of the face (head based pointing essentially).
I have two activities:
Activity 1 previews the camera feed and draws the facial landmarks (in my case, just the nosetip) onto the overlay as well as the cursor. As I said before, the cursor position is being calculated based on the nosetip position in the image -> No problems here
Activity 2 runs a very simplistic game in a separate thread, which spawns obstacles that need to be avoided with the cursor. No live camera feed, "just" the face detection, the face -> cursor screen mapping, a custom gameView and the overlay for the cursor ontop.
My problem:
After some time, the face detector just stops detecting faces (thus the cursor gets "stuck") without any errors and oddly enough, the game incrementally speeds up (but still registers collision with the cursor).
I already followed the instructions for optimizing face detection in real-time by only enabling landmark-mode, enabled tracking and setting the performance mode to fast.
My guess was that running the face detection, mapping the cursor to a point on the screen, drawing onto the overlay for the cursor and having a game running at the same time might be just too much work, but I read somewhere that MLKit runs its detection on its own thread.
It must have something to do with my game, because as already mentioned above, in Activity 1 (Live camera preview + calculating cursor position + drawing landmarks & cursor on the overlay canvas) I never faced (no pun intended) a crash.
My custom GameView:
public class GameView extends SurfaceView implements SurfaceHolder.Callback{
private final int difficultyTime = 5;
private GameThread thread;
private long startTime;
private long timer;
private long difficultyTimer;
private long lastSpawned = 0;
private Paint textPaint;
private Random random;
private Pointer pointer;
private GameManager game;
public GameView(Context context) {
super(context);
init();
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GameView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void init() {
getHolder().addCallback(this);
thread = new GameThread(getHolder(), this);
game = new GameManager();
setFocusable(true);
textPaint = new Paint();
textPaint.setColor(Color.RED);
textPaint.setTextSize(70);
Paint collisionPaint = new Paint();
collisionPaint.setColor(Color.BLUE);
Paint pointerPaint = new Paint();
pointerPaint.setColor(Color.GREEN);
startTime = System.currentTimeMillis();
lastSpawned = System.currentTimeMillis();
difficultyTimer = System.currentTimeMillis() + difficultyTime * 1000;
random = new Random();
}
public void update() {
timer = (System.currentTimeMillis() - startTime) / 1000;
long currentTimeMS = System.currentTimeMillis();
if(currentTimeMS > lastSpawned + (game.getCooldown() * 1000L)) {
lastSpawned = System.currentTimeMillis();
game.setMayDraw(true);
}
if(checkCollision()) {
gameover();
}
// Raise difficulty
if(difficultyTimer <= System.currentTimeMillis()) {
difficultyTimer = System.currentTimeMillis() + difficultyTime * 1000;
game.advanceDifficulty();
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
int bgColor = Color.WHITE;
canvas.drawColor(bgColor);
// Spawn elements
if(game.getMayDraw()) {
game.setMayDraw(false);
spawnObstacles(canvas);
}
// Update existing elements
game.updateObstacles(canvas);
// Draw the timer
drawTimer(canvas);
// Draw difficulty text
drawDifficulty(canvas);
}
private void drawTimer(Canvas canvas) {
canvas.drawText(Long.toString(timer), (getWidth() / 2), 80, textPaint);
invalidate();
}
private void drawDifficulty(Canvas canvas) {
canvas.drawText("Difficulty: " + game.getCurrentDifficultyIndex(), (getWidth() / 2) + 250, 80, textPaint);
}
private void spawnObstacles(Canvas canvas) {
int random_number;
int last_random = 0;
for(int i = 0; i < game.getMAX_SPAWN(); i++) {
do {
random_number = random.nextInt(4) + 1;
}while(random_number == last_random);
switch(random_number) {
case 1:
game.spawnTop(canvas);
break;
case 2:
game.spawnBottom(canvas);
break;
case 3:
game.spawnLeft(canvas);
break;
case 4:
game.spawnRight(canvas);
break;
}
last_random = random_number;
}
}
public void gameover() {
startTime = System.currentTimeMillis();
game.getObstacles().clear();
game.resetDifficulty();
difficultyTimer = System.currentTimeMillis() + difficultyTime * 1000;
}
public boolean checkCollision() {
List<Pair<GameManager.Direction, Rect>> collidables = game.getObstacles();
for (Pair<GameManager.Direction, Rect> r : collidables) {
if(intersects(r.second, pointer.getCollisionRect()) || intersects(pointer.getCollisionRect(), r.second)) {
return true;
}
}
return false;
}
public static boolean intersects(Rect rect, Rect otherRect) {
return rect.left <= otherRect.right && otherRect.left <= rect.right
&& rect.top <= otherRect.bottom && otherRect.top <= rect.bottom;
}
#Override
public void surfaceCreated(#NonNull SurfaceHolder surfaceHolder) {
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceChanged(#NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
System.out.println("Surface changed - Format: " + format + " W/H: ("+width +"/" +height+")");
}
#Override
public void surfaceDestroyed(#NonNull SurfaceHolder surfaceHolder) {
boolean retry = true;
while (retry) {
try {
thread.setRunning(false);
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
retry = false;
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
GameThread:
public class GameThread extends Thread{
private final SurfaceHolder surfaceHolder;
private final GameView gameView;
private boolean running;
public static Canvas canvas;
public GameThread(SurfaceHolder surfaceHolder, GameView gameView) {
super();
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
#Override
public void run() {
long startTime;
long timeMillis;
long waitTime;
long totalTime = 0;
int frameCount = 0;
int targetFPS = 15;
long targetTime = 1000 / targetFPS;
while (running) {
startTime = System.nanoTime();
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized(surfaceHolder) {
this.gameView.update();
this.gameView.draw(canvas);
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (canvas != null) {
try {
surfaceHolder.unlockCanvasAndPost(canvas);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
timeMillis = (System.nanoTime() - startTime) / 1000000;
waitTime = targetTime - timeMillis;
try {
if(waitTime > 0) {
this.sleep(waitTime);
}
} catch (Exception e) {
e.printStackTrace();
}
totalTime += System.nanoTime() - startTime;
frameCount++;
if (frameCount == targetFPS) {
double averageFPS = 1000 / ((totalTime / frameCount) / 1000000);
frameCount = 0;
totalTime = 0;
Log.d("GameFPS", "" + averageFPS);
}
}
}
public void setRunning(boolean isRunning) {
running = isRunning;
}
FaceDetector:
public class Detector {
private final FaceDetector faceDetector;
private final GraphicOverlay overlay;
private final Pointer pointer;
private final ClickHandler clickHandler;
private final boolean drawFaces;
public Detector(GraphicOverlay overlay, Context context, boolean drawFaces) {
this.overlay = overlay;
this.drawFaces = drawFaces;
pointer = new Pointer(overlay, context);
clickHandler = new ClickHandler(context, this.pointer);
FaceDetectorOptions options =
new FaceDetectorOptions.Builder()
//.setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
.setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
/* disable for better performance *///.setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
.enableTracking()
.setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
.build();
faceDetector = FaceDetection.getClient(options);
}
public void detectFace(ImageProxy image) {
if(image == null) {
return;
}
InputImage inputImage = getInputImage(image);
int rotationDegrees = image.getImageInfo().getRotationDegrees();
if(rotationDegrees == 0 || rotationDegrees == 180) {
overlay.setImageSourceInfo(image.getWidth(), image.getHeight(), true);
}else{
overlay.setImageSourceInfo(image.getHeight(), image.getWidth(), true);
}
if(inputImage == null) {
return;
}
Task<List<Face>> result =
this.faceDetector.process(inputImage)
// When detection succeeded
.addOnSuccessListener(
faces -> {
overlay.clear();
if(faces.size() > 0) {
for(Face face: faces) {
if(drawFaces) {
// Adding faces to overlay
FaceGraphic g = new FaceGraphic(overlay, face);
overlay.add(g);
}
// Update Pointer/Cursor
pointer.update(face);
}
}
})
// When detection failed
.addOnFailureListener(
e -> Log.d("Processing failed", e.getMessage()))
// When detection is completed
.addOnCompleteListener(
task -> image.close()
);
}
#SuppressLint("UnsafeOptInUsageError")
private InputImage getInputImage(ImageProxy image) {
int rotation = image.getImageInfo().getRotationDegrees();
Image mediaImage = image.getImage();
if(mediaImage != null) {
return InputImage.fromMediaImage(mediaImage, rotation);
}else{
return null;
}
}
GameActivity:
public class GameActivity extends AppCompatActivity {
private GraphicOverlay mOverlay;
private GameView gameView;
private Camera camera;
private Pointer pointer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_game);
gameView = findViewById(R.id.gameView);
mOverlay = findViewById(overlay_game);
initCamera();
}
private void initCamera() {
camera = new Camera(this, mOverlay);
camera.setDrawFaces(false);
camera.setAnalysisUseCase();
camera.setAnalyzer();
camera.build();
pointer = camera.getDetector().getPointer();
gameView.setPointer(pointer);
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
The face detection "crash" can occur anywhere from 1 second to 5 minutes playing the game. I would gladly appreciate any hints or suggestions. Also im fairly new to java and mobile-app development, so please excuse my bad code.
If you need any further information/code i'll happily provide it.
Thanks in advance

Intersect method not working, keeps returning true

My intersect method keeps returning true and setting my "score text" to intersect detected when my images do not collide, instead it changes the text as soon as the emulator starts. Please notify me if more code is needed and check back within 10 minutes. Thanks! -this is all my code and collision code starts at line 163, something is wrong with my collision code because collision isn't being detected, what should I do to fix my collision code.
here is my code:
public class MainActivity extends AppCompatActivity {
//Layout
private RelativeLayout myLayout = null;
//Screen Size
private int screenWidth;
private int screenHeight;
//Position
private float ballDownY;
private float ballDownX;
//Initialize Class
private Handler handler = new Handler();
private Timer timer = new Timer();
//Images
private ImageView net = null;
private ImageView ball = null;
//for net movement along x-axis
float x;
float y;
//points
private int points = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myLayout = (RelativeLayout) findViewById(R.id.myLayout);
//score
TextView score = (TextView) findViewById(R.id.score);
//imageviews
net = (ImageView) findViewById(R.id.net);
ball = (ImageView) findViewById(R.id.ball);
//retrieving screen size
WindowManager wm = getWindowManager();
Display disp = wm.getDefaultDisplay();
Point size = new Point();
disp.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
//move to out of screen
ball.setX(-80.0f);
ball.setY(screenHeight + 80.0f);
//start timer
timer.schedule(new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
changePos();
}
});
}
}, 0, 20);
}
public void changePos() {
//down
ballDownY += 10;
if (ball.getY() > screenHeight) {
ballDownX = (float) Math.floor((Math.random() * (screenWidth -
ball.getWidth())));
ballDownY = -100.0f;
}
ball.setY(ballDownY);
ball.setX(ballDownX);
/*INTERSECT METHOD
Rect rc1 = new Rect();
net.getDrawingRect(rc1);
Rect rc2 = new Rect();
ball.getDrawingRect(rc2);
if (Rect.intersects(rc1, rc2)) {
TextView score = (TextView) findViewById(R.id.score);
score.setText("INTERSECT DETECTED");
}*/
//make net follow finger
myLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
MainActivity.this.x = event.getX();
y = event.getY();
if (event.getAction() == MotionEvent.ACTION_MOVE) {
net.setX(MainActivity.this.x);
net.setY(y);
}
return true;
}
});
}
public boolean Collision(ImageView net, ImageView ball)
{
Rect AR = new Rect();
net.getHitRect(AR);
Rect BR = new Rect();
ball.getHitRect(BR);
Render();
return AR.intersect(BR) || AR.contains(BR) || BR.contains(AR);
}
public void Render()
{
if(Collision(net, ball))
{
points++;
TextView score = (TextView)findViewById(R.id.score);
score.setText("Score:" + points);
}
}
}
I have reformed your code, try now
public class MainActivity extends AppCompatActivity
{
//Layout
private RelativeLayout myLayout = null;
//Screen Size
private int screenWidth;
private int screenHeight;
//Position
private float ballDownY;
private float ballDownX;
//Initialize Class
private Handler handler = new Handler();
private Timer timer = new Timer();
//Images
private ImageView net = null;
private ImageView ball = null;
//score
private TextView score = null;
//for net movement along x-axis
public float x = 0;
public float y = 0;
//points
private int points = 0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
this.myLayout = (RelativeLayout) findViewById(R.id.myLayout);
this.score = (TextView) findViewById(R.id.score);
this.net = (ImageView) findViewById(R.id.net);
this.ball = (ImageView) findViewById(R.id.ball);
//retrieving screen size
WindowManager wm = getWindowManager();
Display disp = wm.getDefaultDisplay();
Point size = new Point();
disp.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
//move to out of screen
this.ball.setX(-80.0f);
this.ball.setY(screenHeight + 80.0f);
//Error here
/*//Run constantly
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
Render();
}
}, 100); //100 is miliseconds interval than sleep this process, 1000 miliseconds is 1 second*/
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(100);
runOnUiThread(new Runnable() {
#Override
public void run(){Render();}});}
}catch (InterruptedException e) {}}};
t.start();
}
public void Render()
{
changePos();
if(Collision(net, ball))
{
points++; //You dont need findView Textview score for that exists in OnCreate Method
this.score.setText("Score:" + points);
}
}
public void changePos()
{
//down
ballDownY += 10;
if (ball.getY() > screenHeight) {
ballDownX = (float) Math.floor((Math.random() * (screenWidth - ball.getWidth())));
ballDownY = -100.0f;
}
ball.setY(ballDownY);
ball.setX(ballDownX);
//make net follow finger
myLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
x = event.getX();
y = event.getY();
if (event.getAction() == MotionEvent.ACTION_MOVE) {
net.setX(x);
net.setY(y);
}
return true;
}
});
public boolean Collision(ImageView net, ImageView ball)
{
Rect BallRect = new Rect();
ball.getHitRect(BallRect);
Rect NetRect = new Rect();
net.getHitRect(NetRect);
return BallRect.intersect(NetRect);
}
}
Something like this:
boolean collision = net.getRect().intersect(ball.getRect());
Collision is a boolean
if(boolean) //Action
Then
if(collision) score.setText("INTERSECT DETECTED");
OR
public boolean Collision(ImageView a, ImageView b)
{
Rect AR = new Rect();
a.getHitRect(myViewRect);
Rect BR = new Rect();
b.getHitRect(otherViewRect1);
return Rect.intersects(AR, BR);
}
--
if(Collision(net, ball))
{
//Do action
}
--
ImageView ball = (ImageView) findViewById(R.id.Ball);
ImageView net = (ImageView) findViewById(R.id.Net);
if(Collision(net, ball))
{
//Collision detected
}
--
import android.graphics.Rect;
public boolean Collision(ImageView ball, ImageView net)
{
Rect ballRect = new Rect();
ball.getDrawingRect(ballRect);
Rect netRect = new Rect();
net.getDrawingRect(netRect);
return Rect.intersects(ballRect, netRect);
}
Check this post how to detect when a ImageView is in collision with another ImageView?

Remove the last color form bitmap Undo

Please I need the help regarding Undo method , I tried to implement it like the code below but it is not remove the last color,
Kindly help me to resolve it.
awaiting your kind response.
Thanks in Advance.
MainActivity
public class MainActivity extends AppCompatActivity implements
View.OnTouchListener {
Button red, blue, yellow, undo;
Paint paint;
private RelativeLayout drawingLayout;
private MyView myView;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
/**
* Called when the activity is first created.
*/
/*
*
* private ImageView imageView; private Canvas cv; private Bitmap mask,
* original, colored; private int r,g,b; private int sG, sR, sB;
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = new MyView(this);
drawingLayout = (RelativeLayout) findViewById(R.id.relative_layout);
drawingLayout.addView(myView);
red = (Button) findViewById(R.id.btn_red);
blue = (Button) findViewById(R.id.btn_blue);
yellow = (Button) findViewById(R.id.btn_yellow);
undo = (Button) findViewById(R.id.undo);
red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.RED);
}
});
yellow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.YELLOW);
}
});
blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.BLUE);
}
});
undo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.onClickUndo();
}
});
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
// flood fill
public class MyView extends View {
final Point p1 = new Point();
Bitmap mBitmap;
ProgressDialog pd;
Canvas canvas;
private Path path;
// Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
paint = new Paint();
paint.setAntiAlias(true);
pd = new ProgressDialog(context);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.gp1_1).copy(Bitmap.Config.ARGB_8888, true);
this.path = new Path();
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
Toast.makeText(getContext(), getString(R.string.nomore), Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
paint.setColor(Color.GREEN);
// int width = drawingLayout.getWidth();
// int height = drawingLayout.getHeight();
// float centerX = (width - mBitmap.getWidth()) * 0.5f;
//float centerY = (height - mBitmap.getHeight()) * 0.5f;
canvas.drawBitmap(mBitmap, 0, 0, paint);
///////////////////////////////
for (Path p : paths) {
canvas.drawPath(p, paint);
//////////////////////////
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
paths.add(path);
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage(getString(R.string.wait));
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor,
int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0
&& image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0
&& image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1
&& image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < height - 1
&& image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
I guess you mean the undo method doesn't work. The possible reason is the previous drawing on the canvas is not removed. Try clearing the canvas before drawing in the onDraw() method.
#Override protected void onDraw(Canvas canvas) {
this.canvas = canvas;
canvas. drawColor(0,PorterDuff.Mode.CLEAR); //This clears the canvas.
paint.setColor(Color.GREEN);
//rest of the code
}
Seems it is impossible to return previous color it is required an array for each point to store the used color in every point.

The onTouchEvent is not being called

I am making a game app that displays random circles all across the screen. This is all done in the onDraw method by making a never ending loop. However in the onTouchEvent method there is code that is called when a circle is clicked. The problem is when a circle is "touched" nothing happens, but sometimes something does(if you click it a lot before it disappears). Id like to know if there is a way to get the onTouch method working so these circles can be clicked.
public class DrawingView extends View{
public DrawingView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
RectF rectf = new RectF(0, 0, 200, 0);
private static final int w = 100;
public static int lastColor = Color.BLACK;
private final Random random = new Random();
private final Paint paint = new Paint();
private final int radius = 230;
private final Handler handler = new Handler();
public static int redColor = Color.RED;
public static int greenColor = Color.GREEN;
int randomWidth = 0;
int randomHeight = 0;
public static int addPoints = 0;
public static int savedScore;
public static List<String> a = new ArrayList<String>();
public static String[] savedScores = new String[a.size()];
Paint red;
public static int howManyPoints;
public static int highestScore = 0;
boolean isTouched;
Thread newThread = new Thread();
int t = 1;
int l = 0;
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//handler.post(updateCircle);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// handler.removeCallbacks(updateCircle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// your other stuff here
Paint back = new Paint();
back.setColor(Color.BLACK);
Rect background = new Rect();
background.set(0, 0, canvas.getWidth(),canvas.getHeight() );
canvas.drawRect(background, back);
Paint newPaint = new Paint();
newPaint.setColor(Color.BLUE);
newPaint.setTextSize(60);
canvas.drawText("Beta v2", 10, 60, newPaint);
if(l < t){
lastColor = random.nextInt(2) == 1 ? redColor : greenColor;
paint.setColor(lastColor);
if(random == null){
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}else {
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}
canvas.drawCircle(randomWidth , randomHeight , radius , paint);
try {
newThread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
invalidate();
}
red = new Paint();
red.setColor(Color.BLUE);
red.setTextSize(150);
canvas.drawText("" + addPoints, 500, 1350, red);
}
#SuppressWarnings("deprecation")
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
int x = (int) event.getX();
int y = (int) event.getY();
if(isInsideCircle(x, y) == true){
if(lastColor == redColor){
howManyPoints = addPoints;
if(howManyPoints > highestScore){
highestScore = howManyPoints;
}
//handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
l = 1;
}
if(lastColor == greenColor){
addPoints++;
isTouched = true;
l = 0;
}
}else {
}
}
return false;
}
public boolean isInsideCircle(int x, int y){
if ((((x - randomWidth)*(x - randomWidth)) + ((y - randomHeight)*(y - randomHeight))) < ((radius)*(radius))){
return true;
}
return false;
}
}
You forgot to return true when you touch down
Try to add this
if(event.getAction() == MotionEvent.ACTION_DOWN){
//your code
return true;
}

How to test if something has not been touched after a circle has been drawn

I have an app that draws random circles to the screen one after another. These circles colors are also random either green or red. If you are to click a red one you loose the game if you are to click a green one you get points. What I am trying to do is add a boolean that checks if someone has not clicked on a green circle or has not clicked the screen at all when a green circle is displayed. If a red circle is displayed and the user does not click anywhere nothing happens, but in the event that a green circle is displayed and nothing is clicked the user should be redirected to another class and loose all of there points. I have tried to make a boolean called isTouched and gave it the value false then placed it all throughout my code but nothing seems to work. Here is my code if the isTouched boolean is to equal false.
if(isTouched == false){
howManyPoints = addPoints;
handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
}
and here is the entire class.
public class DrawingView extends View{
public DrawingView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
RectF rectf = new RectF(0, 0, 200, 0);
private static final int w = 100;
public static int lastColor = Color.BLACK;
private final Random random = new Random();
private final Paint paint = new Paint();
private final int radius = 230;
private final Handler handler = new Handler();
public static int redColor = Color.RED;
public static int greenColor = Color.GREEN;
int randomWidth = 0;
int randomHeight = 0;
public static int addPoints = 0;
public static int savedScore;
public static List<String> a = new ArrayList<String>();
public static String[] savedScores = new String[a.size()];
Paint red;
public static int howManyPoints;
boolean isTouched;
private final Runnable updateCircle = new Runnable() {
#Override
public void run() {
lastColor = random.nextInt(2) == 1 ? redColor : greenColor;
paint.setColor(lastColor);
if(addPoints < 10){
handler.postDelayed(this, 700);
}
if(addPoints > 9 && addPoints < 30){
handler.postDelayed(this,550);
}
if(addPoints > 29){
handler.postDelayed(this, 450);
}
postInvalidate();
}
};
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
handler.post(updateCircle);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
handler.removeCallbacks(updateCircle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// your other stuff here
Paint back = new Paint();
back.setColor(Color.BLACK);
Rect background = new Rect();
background.set(0, 0, canvas.getWidth(),canvas.getHeight() );
canvas.drawRect(background, back);
Paint newPaint = new Paint();
newPaint.setColor(Color.BLUE);
newPaint.setTextSize(60);
canvas.drawText("ALPHA 1.64.5", 10, 60, newPaint);
if(random == null){
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}else {
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}
canvas.drawCircle(randomWidth, randomHeight, radius, paint);
red = new Paint();
red.setColor(Color.BLUE);
red.setTextSize(150);
canvas.drawText("" + addPoints, 500, 1350, red);
}
#SuppressWarnings("deprecation")
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
int x = (int) event.getX();
int y = (int) event.getY();
if(isInsideCircle(x, y) == true){
//Do your things here
if(lastColor == redColor){
//saveScore();
howManyPoints = addPoints;
handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
}
if(lastColor == greenColor){
addPoints++;
isTouched = true;
}
}else {
}
}
if(isTouched == false){
howManyPoints = addPoints;
handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
}
return false;
}
public void saveScore() {
a.add("" + addPoints);
//if(Integer.parseInt(savedScores[1]) < addPoints){
//savedScores[2] = savedScores[1];
//int x = Integer.parseInt(savedScores[1]);
//x = addPoints;
//}
}
public boolean isInsideCircle(int x, int y){
if ((((x - randomWidth)*(x - randomWidth)) + ((y - randomHeight)*(y - randomHeight))) < ((radius)*(radius))){
return true;
}
return false;
}
}

Categories