Canvas Larger Than Screen - android

I am drawing a grid and I want it to be larger than the screen size so that a user can drag the screen left/right/up/down to get to the rest of the grid.
What is the best way to do that? I've tried drawing a larger bitmap to the canvas, but didn't get anywhere.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
Bitmap testBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888);
canvas.drawBitmap(testBitmap, 0, 0, paint);
canvas.drawPaint(paint);
//other grid drawing code here
}

I used the View's scrollBy() method in the onTouch method of the Activity. It worked.

You can probably use the canvas.translate(x, y) method. That will adjust the origin for your canvas in relation to the screen. So canvas.translate(10, 10) will make you canvas origin (0, 0) be at the point of (10, 10) on the screen. Use a negative translation to scroll the screen.

Related

Clear/Reset entire ImageView canvas

I've got a simple layout with 2 imageViews:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="#+id/takenPicture"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.example.dochjavatestimplementation.pkgActivity.ExtendedImageView
android:id="#+id/takenPicture2"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
The first ImageView displays a bitmap, the second ImageView (1) is a custom ImageView (ExtendedImageView) (2)which draws a canvas which gets displayed on top of the normal ImageView.
This looks like this:
displayimageviews
What I want is that after drawing the rect in my onDraw method, I want to clear the rect again (right now just for testing purposes). This is what my code looks like:
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
canvas.drawRect(new Rect(212,0,-720,600),paint);
//clear the rect/contents of canvas again
//try 1
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
//try2
Paint transparent = new Paint();
transparent.setAlpha(0);
canvas.drawPaint(transparent);
//try3
setImageResource(0);
}
I tried clearing the canvas/rect in three different ways as seen in code above, but it doesnt change the output as the black rect is still visible.
My question now is what can the cause be? Is it cause I'm not "updating" the canvas or is it due to how I try clearing my canvas?
The endresult should basically be that I only see the first imageview
Drawing shapes on Canvas in View.onDraw() is low-level function that directly changes pixels on the display in the final stage. So, if you once draw something, it's impossible to erase it. It's not buffered. There remain only mixed RGB(w/o A) pixels on the screen. The former pixel colors (originated from the "takenPicture") are already lost.
If you'd like to make shapes erasable, prepare another canvas backed by an ARGB-bitmap and draw all on it. Then draw the bitmap on the canvas in the end.
#Override
protected void onDraw(Canvas canvas)
{
// Prepare Bitmap and Canvas
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas draw_canvas = new Canvas(bitmap);
// Draw a rect.
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
draw_canvas.drawRect(new Rect(212,0,-720,600),paint);
// Clear
draw_canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
// Draw the bitmap.
canvas.drawBitmap(bitmap, 0, 0, null);
bitmap.recycle();
}

canvas draw not smooth circles

At the first of my game, I draw some circles from alpha 0 to 255 using canvas(it's like making a fade_in animation by myself)
But if you see in picture(this picture captured in alpha 230),from alpha 0 to 254 these circles aren't smooth!(click on picture to see what I mean)
(and only when alpha become 255 the circles become smooth)
What's the problem and how can I fix this?
my code:
I have a game loop, that get canvas
canvas = gameView.getHolder().lockCanvas();
then in my view ,at first I set :
paintAlpha = 0;
paint = new Paint();
paint.setAntiAlias(true);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setAlpha(paintAlpha);
paint.setColor(Color.parseColor(color));
then in every loop(every ticks) I do this:
if(paintAlpha < 255) {
paintAlpha+=1;
paint.setAlpha(paintAlpha);
}
canvas.drawCircle(cx, cy, currentRadius, paint);
Solution:
Thanks to #nitesh.
The problem was because of surfaceView that can't set anti alias to canvas (in View you don't have this problem ,I don't know why)
By using Bitmap and draw on it and finally draw bitmap by canvas , the problem solved (instead of drawing on canvas directly)
Set the following property to paint object
paint.setAntiAlias(true);
For better understanding and other approaches refer this link
https://medium.com/#ali.muzaffar/android-why-your-canvas-shapes-arent-smooth-aa2a3f450eb5#.p9iktozdi
From the article
Draw a bitmap first if:
- You need to persist the image.
- You need to draw transparent pixels.
- Your shapes don’t change often and/or require time consuming operations.
Use anti-aliasing to draw smooth edges.
Avoid redraws on the bitmap if possible or else, clear a bitmap before redrawing.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (bitmap == null) {
bitmap = Bitmap.createBitmap(200,
200,
Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
}
bitmapCanvas.drawColor(
Color.TRANSPARENT,
PorterDuff.Mode.CLEAR); //this line moved outside if
drawOnCanvas(bitmapCanvas);
canvas.drawBitmap(bitmap, mLeftX, mTopY, p);
}
protected void drawOnCanvas(Canvas canvas) {
canvas.drawCircle(mLeftX + 100, mTopY + 100, 100, p);
}
you can approach this by
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
or
paint.setAntiAlias(true);

canvas.clipPath() not working even after disabling harware acceleration

I have drawn a circle filled with black color in the canvas and I have set the background color of the canvas to red.
I want only the circle which is black color to appear as my view but I get the red color as well.
I tried using canvas.clipPath() it dint work. I searched the net and found out we need to disable hardware acceleration to get it work. I tried that but it still dint work.
Tried disabling the Hardware Acceleration for particular view:
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
And also to whole application:
android:hardwareAccelerated="false"
Dint work in both the cases.
Any ideas on how to make it work ?
Code:
And here I am clipping
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
path.reset();
left = 50;
top = 50;
right = getWidth()- 50;
bottom = getHeight()-50;
RectF rectf = new RectF(left, top, right, bottom);
path.arcTo(rectf, startAngle, sweepAngle);
path.lineTo(linex, liney);
canvas.clipPath(path);
canvas.drawPath(path, paint);
//canvas.restore();
}
This is not what clip path is for. When you draw a path and then clip it - it means that the rest of the things you will draw on the canvas from that point will be masked by the path.
In your case you draw a red background before clipping the canvas - so it went all over the canvas, then you clipped it but draw only inside the path, so the clipping was useless.
you can get what you need that in that code:
// Do not set any background to the view before
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
path.reset();
left = 50;
top = 50;
right = getWidth()- 50;
bottom = getHeight()-50;
RectF rectf = new RectF(left, top, right, bottom);
path.arcTo(rectf, startAngle, sweepAngle);
path.lineTo(linex, liney);
canvas.clipPath(path);
canvas.drawRect(0, 0, getWidth(), getHeight(), Red Paint in here);
canvas.drawPath(path, paint);
//canvas.restore();
}
That way you draw the background after pathClip
You will not see any red color because you draw all over the path right after it, if I am guessing right - you want to be able to draw a part of a circle in one color and the rest in other - you can achieve it if your path that you will clip will be the full circle and the path that you draw will be the part that you want to draw

Smooth bitmap movement in canvas (android)

I tried to create a Maze with a moving ball and a hole using the Accelerometer Sensor. With the following code, the ball falls into the hole, but the performance is really bad, I set the Accelerometer Frequency to the fastest, but it's everything other than smooth. I made a second canvas, because so I could make a hole.
public RenderView(Context context, int width, int height) {
super(context);
playGround = new Rect(40, 40, width - 40, height - 40);
holes.addElement(new PointF(500f, 500f));
// Set background
this.setBackgroundResource(R.drawable.bottom);
// Set bitmap
woodGround= wood.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas();
bitmapCanvas.setBitmap(woodGround);
// Set eraser paint properties
eraserPaint.setAlpha(0);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
eraserPaint.setAntiAlias(true);
}
protected void onDraw(Canvas canvas) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG
| Paint.FILTER_BITMAP_FLAG);
paint.setStyle(Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
if (ballInHole)
canvas.drawBitmap(ball, b.x, b.y, paint);
bitmapCanvas.drawBitmap(wall, 0, 0, paint);
bitmapCanvas.drawBitmap(wood, playGround, playGround, paint);
canvas.drawBitmap(bitmap, 0, 0, paint);
for (PointF h : holes) {
bitmapCanvas.drawCircle(h.x + radius, h.y + radius, radius,
eraserPaint);
}
if (!ballInHole)
canvas.drawBitmap(ball, b.x, b.y, paint);
invalidate();
}
It's solved very ugly, because I just draw the ball bellow the other bitmaps when he falls into a hole. Is there another way to do it?
The performance is also really bad, i set the Accelerometer-Sensor-Delay to the fastest, but the ball doesn't run smooth. When I remove the line canvas.drawBitmap(bitmap, 0, 0, paint);, then the ball is smoother, but then the wooden background is away.
The problem here is that you're doing A LOT of drawings all the time and that's take time to draw and the performance gets very low.
here a few tips on how you should approach it.
You probably better have one view with the static stuff (the background image and the holes) and on your layout have a second view on top of it just drawing the ball.
on the background image, do not call invalidate. That way you will draw the background just once.
and the top image (the ball only) you can invalidate, so it can redraw on the new position.
I'm not sure on this last part: but you may need to call invalidate(rect); passing the area where the ball was on the previous time, to make the background only re-draw that small area (instead of the whole screen)
happy coding.

How to set a background bitmap to a rect or rectF?

Is there a way to set a background image for a rectangle drawn in a canvas ?
For exemple i have the following onDraw method :
protected void onDraw(Canvas canvas) {
this.setBackgroundGradient();
RectF rect = new RectF();
rect.set(0, 0, canvas.getWidth(), 50);
canvas.drawRoundRect(rect, 0, 0, this.paint);
}
private void setBackgroundGradient()
{
this.paint.setShader(new LinearGradient(0, 0,0, getHeight(), 0xff919191, 0xff424242, Shader.TileMode.MIRROR));
}
I would like to change my gradient by a background image (repeatable if possible).
Note : i would rather to keep rectangle and not use drawBitmap.
A Rect is not a drawable, it is a convenience class and only holds the four values that define the rect. Canvas knows how to draw a rect with the Paint object you give it.
If you want to have a background (image) instead of a rect, then you either use drawBitmap on the canvas or have a (bitmap)drawable that you pass the canvas to when drawing.

Categories

Resources