I'm developing an Android application, I have to implement a function that allow me to draw different point in an activity.
This is my code:
public class MainActivity extends AppCompatActivity {
public Paint paint;
public List<Point> coords;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawingView(this));
paint = new Paint();
coords = new ArrayList();
ImageView iv = new ImageView(getApplicationContext());
iv.setImageResource(R.drawable.car);
iv.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
LinearLayout.LayoutParams parms = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
iv.setLayoutParams(parms);
}
class DrawingView extends SurfaceView {
private final SurfaceHolder surfaceHolder;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public DrawingView(Context context) {
super(context);
surfaceHolder = getHolder();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
addpoint(event.getX(), event.getY());
}
return false;
}
public void addpoint(float x, float y){
Point point = new Point();
point.x = Math.round(x);
point.y = Math.round(y);
coords.add(point);
for(int i = 0; i< coords.size(); i++) {
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawCircle(coords.get(i).x, coords.get(i).y, 20, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
Everytime that I touch the screen I get and save the coordinates in a list, then I try to draw the list of point, but only one point remain on the screen, I don't understand why.
So how I can draw different point on the screen (and save it) ?
Another question: how I can show a background image ?
From the official Javadocs:
drawColor(int color) Fill the entire canvas' bitmap (restricted to the
current clip) with the specified color, using srcover porterduff mode.
So every time you draw a circle, first you clear the whole canvas with white color. So after a draw, the circle drawed before is cleared.
So one option is to save the current state of the background, and always draw it on top of the white, or try not using drawColor
for(int i = 0; i< coords.size(); i++) {
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawCircle(coords.get(i).x, coords.get(i).y, 20, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
should be
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
for(int i = 0; i< coords.size(); i++) {
canvas.drawCircle(coords.get(i).x, coords.get(i).y, 20, paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
canvas.drawColor(Color.WHITE); Everytime ereases all the canvas and surfaceHolder.unlockCanvasAndPost(canvas); shows only the last added Circle
Related
I am tryin to set an image in full screen using canvas and bitmap but whenever I load the app the image gets zoomed in and only displays half of what it's supposed to. How would I do this? I have attached my code snippet and i have tried updating the canvas.drawbitmap line of code inside the onDraw method but it doesn't help, the image still appears zoomed in. Some help would greatly be appreciated thank you in advance...
public class Fish extends View {
private Bitmap fish [] =new Bitmap[2];
private int fishX=10;
private int fishY;
private int fishSpeed;
private int canvasWidth, canvasHeight;
private int yellowX, yellowY, yellowSpeed=16;
private Paint yellowPaint=new Paint();
private int greenX, greenY, greenSpeed=20;
private Paint greenPaint=new Paint();
private int redX, redY, redSpeed=25;
private Paint redPaint=new Paint();
private int score, lifeCountOfLife;
private boolean touch=false;
private Bitmap backgroundImage;
private Paint scorePaint= new Paint();
private Bitmap life[]=new Bitmap[2];
//updates the background
public Fish(Context context) {
super(context);
fish [0]=BitmapFactory.decodeResource(getResources(),R.drawable.fish1);
fish [1]=BitmapFactory.decodeResource(getResources(),R.drawable.fish2);
//updates the bg
backgroundImage=BitmapFactory.decodeResource(getResources(),R.drawable.mn);
//creates the ball/foood color
yellowPaint.setColor(Color.YELLOW);
yellowPaint.setAntiAlias(false);
greenPaint.setColor(Color.GREEN);
greenPaint.setAntiAlias(false);
redPaint.setColor(Color.RED);
redPaint.setAntiAlias(false);
// updates score
scorePaint.setColor(Color.WHITE);
scorePaint.setTextSize(70);
scorePaint.setTypeface(Typeface.DEFAULT_BOLD);
scorePaint.setAntiAlias(true);
//displays the heart and life
life[0]=BitmapFactory.decodeResource(getResources(),R.drawable.heartts);
life[1]=BitmapFactory.decodeResource(getResources(),R.drawable.greyheart);
fishY=550;
score=0;
lifeCountOfLife=3;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvasWidth=canvas.getWidth();
canvasHeight=canvas.getHeight();
//displays it to the main actiivty
canvas.drawBitmap(backgroundImage,canvasWidth,canvasHeight,null);
int minFish= fish[0].getHeight();
int maxFishY=canvasHeight-fish[0].getHeight() *3;
fishY=fishY+fishSpeed;
if(fishY<minFish){
fishY=minFish;
}
if(fishY> maxFishY){
fishY=maxFishY;
}
fishSpeed=fishSpeed+2;
if(touch){
canvas.drawBitmap(fish[1], fishX,fishY, null);
touch=false;
}else{
canvas.drawBitmap(fish[0],fishX,fishY,null);
}
yellowX=yellowX-yellowSpeed;
//updates the score if the ball is collected
if(hitBallChecker(yellowX,yellowY)){
score=score+10;
yellowX=-100;
}
if(yellowX<0){
yellowX=canvasWidth+21;
yellowY=(int) Math.floor(Math.random() * (maxFishY-minFish))+ minFish;
}
//increases size of ball
canvas.drawCircle(yellowX, yellowY, 25, yellowPaint);
//Green ball
greenX=greenX-greenSpeed;
if(hitBallChecker(greenX,greenY)){
score=score+20;
greenX=-100;
}
if(greenX<0){
greenX=canvasWidth+21;
greenY=(int) Math.floor(Math.random() * (maxFishY-minFish))+ minFish;
}
//increases size of ball
canvas.drawCircle(greenX, greenY, 25, greenPaint);
//red ball
//if the ball gets hit
redX=redX-redSpeed;
if(hitBallChecker(redX,redY)){
redX=-100;
lifeCountOfLife--;
if(lifeCountOfLife==0){
Intent gameOverIntent= new Intent(getContext(), GameOverActivity.class);
gameOverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
gameOverIntent.putExtra("score", score);
getContext().startActivity(gameOverIntent);
}
}
//increases size of ball
if(redX<0){
redX=canvasWidth+21;
redY=(int) Math.floor(Math.random() * (maxFishY-minFish))+ minFish;
}
canvas.drawCircle(redX, redY, 30, redPaint);
canvas.drawText("Score: " +score, 20, 60, scorePaint);
for(int i=0; i<3; i++){
int x=(int) (580+life[0].getWidth() * 1.5 * i);
int y=30;
if(i<lifeCountOfLife){
canvas.drawBitmap(life[0], x,y, null);
}else{
canvas.drawBitmap(life[1], x,y, scorePaint);
}
}
}
public boolean hitBallChecker(int x, int y){
if(fishX< x && x<(fishX+fish[0].getWidth()) &&fishY<y &&y<(fishY+ fish[0].getHeight())){
return true;
}
return false;
}
//updates fish speed
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
touch=true;
fishSpeed=-22;
}
return true;
}
}
public void drawBitmap (Bitmap bitmap,
float left,
float top,
Paint paint)
In drawBitmap left and top define the (x,y) of the top left corner of the image, which in your case should be (0,0).
If you want to draw a canvas sized backgound it would probably be best to use:
public void drawBitmap (Bitmap bitmap,
Rect src,
Rect dst,
Paint paint)
Where src is the Rect that defines the subset of the Bitmap that you want to draw (you can leave it at null to draw the entire Bitmap), and dst is the destination Rect that will automatically be filled with the Bitmap.
You are going to need to define the destination Rect:
Rect backgroundRect = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());
You can now call
canvas.drawBitmap(backgroundImage,null,backgroundRect,null);
I have 2 bitmaps on a canvas. ontouching the top bitmap , the lower bitmap should be visible and the top bitmap should be erased.
I took help from this thread. Make certain area of bitmap transparent on touch. I can see the bottom bitmap through the circle, but the top bitmap is not erasing on touching. How to erase the the bitmap on touching. I know that this question has been asked before, but i am not able to solve the problem.
this is my code:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Panel(this));
}
class Panel extends View {
Bitmap bmOverlay;
private Paint mPaint;
Bitmap bm2, bm1;
Bitmap bitmap;
Canvas pcanvas;
int x = 0;
int y = 0;
int r = 0;
public Panel(Context context) {
super(context);
setFocusable(true);
setBackgroundColor(Color.TRANSPARENT);
// setting paint
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mPaint.setAntiAlias(true);
bm1 = BitmapFactory.decodeResource(getResources(), R.drawable.aa);
bm2 = BitmapFactory.decodeResource(getResources(), R.drawable.aaa);
bmOverlay = Bitmap.createBitmap(bm1.getWidth(), bm1.getHeight(),
Bitmap.Config.ARGB_8888);
pcanvas = new Canvas(bmOverlay);
}
#Override
protected void onDraw(Canvas canvas) {
// draw a circle that is erasing bitmap
super.onDraw(canvas);
canvas.drawBitmap(bm2, 0, 0, null);
pcanvas.drawBitmap(bm1, 0, 0, null);
pcanvas.drawCircle(x, y, 40, mPaint);
canvas.drawBitmap(bmOverlay, 0, 0, null);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// set parameter to draw circle on touch event
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
x = (int) ev.getX();
y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
x = (int) ev.getX();
y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
}
You need to make two changes to get the top bitmap to erase. First, make it a mutable Bitmap so that you can change the contents as it is erased:
Bitmap temp = BitmapFactory.decodeResource(getResources(), R.drawable.aa);
bm1 = temp.copy(Bitmap.Config.ARGB_8888, true); // mutable = true
Be careful about out of memory errors here.
Secondly, in your onDraw function, update the bitmap contents by writing back to bm1:
#Override
protected void onDraw(Canvas canvas) {
// draw a circle that is erasing bitmap
super.onDraw(canvas);
canvas.drawBitmap(bm2, 0, 0, null);
pcanvas.drawBitmap(bm1, 0, 0, null);
pcanvas.drawCircle(x, y, 40, mPaint);
canvas.drawBitmap(bmOverlay, 0, 0, null);
// erase the top bitmap:
Canvas bitmapCanvas = new Canvas(bm1);
bitmapCanvas.drawBitmap(bm2, 0, 0, null);
bitmapCanvas.drawBitmap(bmOverlay, 0, 0, null);
}
Also, to stop a circle being erased in the top left corner when you start the app, create a boolean with a default value of false and set it inside onTouchEvent when you have valid co-ordinates, and check it before calling drawCircle.
How can I extract a Bitmap object out of my onDraw() routine in my CustomView?
Here is my code:
public class DrawView extends View {
private Paint paint = new Paint();
private Point point;
private LinkedList<Point> listaPontos;
private static Context context;
class Point {
public Point(float x, float y) {
this.x = x;
this.y = y;
}
float x = 0;
float y = 0;
}
public DrawView(Context context) {
super(context);
this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
this.context = context;
paint.setColor(Color.YELLOW);
this.listaPontos = new LinkedList<Point>();
}
#Override
public void onDraw(Canvas canvas) {
if(listaPontos.size() != 0){
for(Point point : listaPontos){
canvas.drawCircle(point.x, point.y, 25, paint);
}
}
calculateAmount(canvas);
}
private void calculateAmount(Canvas canvas) {
LinkedList<Integer> colors = new LinkedList<Integer>();
for(int i = 0 ; i != canvas.getWidth(); i++)
{
for(int j = 0; j != canvas.getHeight(); j++){
int color = BITMAP.getPixel(i,j); //How can I get the bitmap generated on onDraw ?
colors.add(color);
}
}
int yellow = 0;
int white = 0;
for(Integer cor : colors) {
if(cor == Color.WHITE) {
white++;
}
if(cor == Color.YELLOW) {
yellow++;
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
listaPontos.add(new Point(event.getX(), event.getY()));
break;
}
invalidate();
return true;
}
}
Thanks alot in advance ;)
EDIT: The bitmap thing is to calculate each pixel color, how can I add a background image to my DrawView ? I tested this.setBackgroundResource(R.drawable.a); at constructor but didn't work, thanks again ;)
There is no way to extract a Bitmap out of a Canvas. At least not directly.
However, it is possible to draw on a Bitmap with the Canvas and then use the Bitmap.
Bitmap mDrawBitmap;
Canvas mBitmapCanvas;
Paint drawPaint = new Paint();
#Override
public void onDraw(Canvas canvas) {
drawPaint.setColor(Color.RED);
if (mDrawBitmap == null) {
mDrawBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mBitmapCanvas = new Canvas(mDrawBitmap);
}
// clear previously drawn stuff
mBitmapCanvas.drawColor(Color.WHITE);
// draw on the btimapCanvas
mBitmapCanvas.drawStuff(...);
//... and more
// after drawing with the bitmapcanvas,
//all drawn information is stored in the Bitmap
// draw everything to the screen
canvas.drawBitmap(mDrawBitmap, 0, 0, drawPaint);
}
After the onDraw() method has finished, all drawn information will be drawn on the screen (by calling canvas.drawBitmap(...), and also be stored in your Bitmap object (because all draw operations have been done on the Canvas that was created with the Bitmap).
I have a Rect object which I draw using drawRect(Rect, Paint). I have a OnTouchEvent that checks if the touch position is inside the Rect. If the touch is inside the Rect then something on my screen changes.
The issue I'm having is: Where I have to touch to get the on touch statements to execute is around 50 pixels higher than the Rect object.
Here is the relevant parts of my code:
public class MainActivity extends Activity {
DrawView drawView;
RelativeLayout fLY;
static Rect newGame = new Rect(LEFT, 165 + 35, 320, 200 + 35);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
fLY = new RelativeLayout(this);
drawView = new DrawView(this);
fLY.addView(drawView);
setContentView(fLY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int touchX = (int)event.getX();
int touchY = (int)event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
if(newGame.contains(touchX, touchY))reset();
}
}
And my DrawView class:
public class DrawView extends View{
Paint paint = new Paint();
int COLORS[] = Constants.COLORS;
int left = 250;
int size = 35;
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawRect(MainActivity.newGame, paint);
}
}
It's probably off by exactly the height of the Status Bar. You can get the height of the status bar through this answer: Height of statusbar?
Then add that to your getY and it should work.
I have two methods with description of two pictures, and on touching the picture/screen I want to alternate between the two on the screen. How can one do this using boolean?
Here is my code:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
/**
* DrawView.java
* A first drawing view example
*/
public class DrawView extends View implements OnTouchListener
{
private Paint backgroundPaint = new Paint();
private Paint backgroundPaintn = new Paint();
private Paint drawPaint_grass = new Paint();
private Paint drawPaint_grassn = new Paint();
private Paint drawPaint_door = new Paint();
private Paint drawPaint_doorn = new Paint();
private Paint drawPaint_house = new Paint();
private Paint drawPaint_housen = new Paint();
private Paint drawPaint_roof = new Paint();
private Paint drawPaint_roofn = new Paint();
private Paint circlePaint = new Paint();
private Paint circlePaintn = new Paint();
private Paint circlePaint_sun = new Paint();
private Paint circlePaint_sunn = new Paint();
private Paint textPaint = new Paint();
private Paint textPaintn = new Paint();
private Paint path = new Paint();
private Paint pathn = new Paint();
private Path trianglePath;
private float sx, sy;
public DrawView(Context context)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
backgroundPaint.setColor(Color.rgb(0,250,205));
backgroundPaint.setAntiAlias(true);
backgroundPaint.setStyle(Style.FILL);
backgroundPaintn.setColor(Color.rgb(107,92,240));
backgroundPaintn.setAntiAlias(true);
backgroundPaint.setStyle(Style.FILL);
drawPaint_grass.setColor(Color.rgb(124,252,0));
drawPaint_grass.setStyle(Style.FILL);
drawPaint_grassn.setColor(Color.rgb(63,104,73));
drawPaint_grassn.setStyle(Style.FILL);
drawPaint_door.setColor(Color.rgb(233,82,65));
drawPaint_door.setStyle(Style.FILL);
drawPaint_doorn.setColor(Color.rgb(105, 15, 5));
drawPaint_doorn.setStyle(Style.FILL);
drawPaint_house.setColor(Color.rgb(205, 133, 63));
drawPaint_house.setStyle(Style.FILL);
drawPaint_housen.setColor(Color.rgb(175, 142, 138));
drawPaint_housen.setStyle(Style.FILL);
drawPaint_roof.setColor(Color.rgb(160, 82, 45));
drawPaint_roof.setStyle(Style.FILL);
drawPaint_roofn.setColor(Color.rgb(67,52,51));
drawPaint_roofn.setStyle(Style.FILL);
circlePaint_sun.setColor(Color.rgb(255, 255, 0));
circlePaint_sun.setStyle(Style.FILL);
circlePaint_sunn.setColor(Color.rgb(249, 245, 245));
circlePaint_sunn.setStyle(Style.FILL);
trianglePath = new Path();
trianglePath.moveTo(70, 300); // starting point
trianglePath.lineTo(170,250); // 1st vertix
trianglePath.lineTo(270, 300); // 2nd vertix
trianglePath.lineTo(70, 300); // 3rd vertix and close
textPaint.setColor(Color.BLACK);
textPaint.setStyle(Style.FILL);
textPaintn.setColor(Color.WHITE);
textPaintn.setStyle(Style.FILL);
circlePaint.setColor(Color.rgb(211, 211, 211));
circlePaint.setStyle(Style.FILL);
this.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas)
{
//canvas.drawPath(path, paint);
//canvas.drawPath(path, paint);
// Draw white background
canvas.drawRect(this.getLeft(), this.getTop(), this.getRight(), this.getBottom(), backgroundPaint);
//draw a rectangle with blue paint
canvas.drawRect(0,400, 540,600, drawPaint_grass);
canvas.drawRect(100,400, 240,300, drawPaint_house);
canvas.drawRect(150,400, 190,335, drawPaint_door);
canvas.drawPath(trianglePath, drawPaint_roof); // or whatever paint you want
//draw text with green paint
canvas.drawText("Muhibur Rahim", 232, 565, textPaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(sx-30,sy-30, 3, circlePaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(80, 80, 30, circlePaint_sun);
}
public void onDrawn(Canvas canvas)
{
//canvas.drawPath(path, paint);
//canvas.drawPath(path, paint);
// Draw white background
canvas.drawRect(this.getLeft(), this.getTop(), this.getRight(), this.getBottom(), backgroundPaintn);
//draw a rectangle with blue paint
canvas.drawRect(0,400, 540,600, drawPaint_grassn);
canvas.drawRect(100,400, 240,300, drawPaint_housen);
canvas.drawRect(150,400, 190,335, drawPaint_doorn);
canvas.drawPath(trianglePath, drawPaint_roofn); // or whatever paint you want
//draw text with green paint
canvas.drawText("Muhibur Rahim", 232, 565, textPaintn);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(sx-30,sy-30, 3, circlePaintn);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(80, 80, 30, circlePaint_sunn);
}
public boolean onTouch(View v, MotionEvent event)
{
//update the coordinates for the OnDraw method above, with wherever we touch
sx = event.getX();
sy = event.getY();
invalidate();
return true;
}
}
My problem is with the last part of the code, public boolean onTouch...
if (flag) {
// call first method
flag = false;
} else {
// call second method
flag = true;
}
public boolean bool = false;
public int count = 0; // say before the constructor.
//then in your onDraw method take everything and encapsulate it in an if statement:
if(!bool){
//the code in your onDraw() method
}else{//here you would put the call to the other draw method like
onDrawn(canvas);
}
then in your overridden onTouch() method make like this
public boolean onTouch(View v, MotionEvent event)
{
//update the coordinates for the OnDraw method above, with wherever we touch
sx = event.getX();
sy = event.getY();
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(count == 0){
bool = true;
count++;}
if(count == 1){
bool = false;
count--;}
}
invalidate();
return true;
}
how about this?
public void onDraw(Canvas canvas)
{
if(!bool){
// Draw white background
canvas.drawRect(this.getLeft(), this.getTop(), this.getRight(), this.getBottom(), backgroundPaint);
//draw a rectangle with blue paint
canvas.drawRect(0,400, 540,600, drawPaint_grass);
canvas.drawRect(100,400, 240,300, drawPaint_house);
canvas.drawRect(150,400, 190,335, drawPaint_door);
canvas.drawPath(trianglePath, drawPaint_roof); // or whatever paint you want
//draw text with green paint
canvas.drawText("Muhibur Rahim", 232, 565, textPaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(sx-30,sy-30, 3, circlePaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(80, 80, 30, circlePaint_sun);
} else {
onDrawn(canvas);
}
}
Random randomizer = new Random();
if(randomizer.nextBoolean()==True){
}
else{
}