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.
Related
i have an activity to display an image, i am able to zoom the image and move it, i have a rectangle in the center of the screen which doesnt move, i want all what it is inside this rectangle to be able to crop the image , how can i do it ?
I have a custom class only for rectangle's draw
here is my code :
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect mCropRectangle = new Rect();
mCropRectangle.set(
getLeft(),
getTop()+(getBottom()+getTop())/6,
getRight(),
getBottom()-(getBottom()+getTop())/6
);
}
You should be able to use PorterDuff to achieve this. I've pasted an example which will crop a big yellow background using a blue mask.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//create a second canvas
Bitmap mask = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(mask);
Rect cropRect = new Rect(100, 100, 400, 400);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.BLUE); //color doesn't matter
c.drawRect(cropRect, p); //draw the crop rect first
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //change transfer mode
p.setColor(Color.YELLOW);//draw your original image/content here, pretty much whatever you wanted to draw
c.drawRect(0, 0, getWidth(), getHeight(), p);
canvas.drawBitmap(mask, 0, 0, null); //draw the result back onto the canvas
}
I am trying to programmatically create a gray Rect and black Rect with BlurMaskFilter layer (drop shadow effect) by overriding onDraw in a custom View. I am able to get it to draw on screen without any issues, but when I try to draw the view to a bitmap the results are different. In drawing to bitmap, it appears BlueMaskFilter is applied to the View rather than the specific layer of the black Rect.
What am I missing to make the drawn bitmap same as the output drawn on screen?
CustomView's onDraw override:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw black box (shadow) first
RectF rectShadow = new RectF();
rectShadow.set(10, 10, 120, 120);
Paint shadowPaint = new Paint();
shadowPaint.setMaskFilter(new BlurMaskFilter(5, Blur.NORMAL));
shadowPaint.setStyle(Paint.Style.FILL);
shadowPaint.setColor(Color.DKGRAY);
shadowPaint.setAntiAlias(true);
canvas.drawRect(rectShadow, shadowPaint);
setLayerType(View.LAYER_TYPE_SOFTWARE, shadowPaint);
// draw grey box
RectF rectGray = new RectF();
rectGray.set(0, 0, 100, 100);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#656565"));
paint.setAntiAlias(true);
canvas.drawRoundRect(rectGray, paint);
}
Function to save view to bitmap:
public void saveViewToBitmap( View customView int outWidth, int outHeight ) {
customView.setLayoutParams(new ViewGroup.LayoutParams(outWidth, outHeight));
customView.measure(
ViewGroup.MeasureSpec.makeMeasureSpec(customView.getLayoutParams().width,
ViewGroup.MeasureSpec.EXACTLY),
ViewGroup.MeasureSpec.makeMeasureSpec(customView.getLayoutParams().height,
ViewGroup.MeasureSpec.EXACTLY));
customView.layout(0, 0,
customView.getMeasuredWidth(), customView.getMeasuredHeight());
customView.requestLayout();
Bitmap outputBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outputBitmap);
customView.draw(canvas);
return outputBitmap;
}
Note in the following images the screen image has crisp edges for the gray rect, whereas the drawn bitmap has the top and left edges of the gray rect blurred demonstrating the problem.
Image on screen:http://i.stack.imgur.com/0Hl0t.png
Image saved from bitmap created by saveViewToBitmap: http://i.stack.imgur.com/xNzi5.png
Thanks!
I have an ImageView subclass that I use to draw images with rounded corners. The code is based on this answer, and is as follows:
public class ImageViewRoundedCorners extends ImageView {
...
#Override
protected void onDraw(Canvas canvas) {
Bitmap scaledBitmap = Bitmap.createBitmap(getMeasuredWidth(),
getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas scaledCanvas = new Canvas(scaledBitmap);
super.onDraw(scaledCanvas);
drawRoundedCornerBitmap(canvas, scaledBitmap,
getMeasuredWidth(), getMeasuredHeight());
scaledBitmap.recycle();
}
protected void drawRoundedCornerBitmap(Canvas outputCanvas, Bitmap input, int w, int h) {
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
mPaint.reset();
mPaint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(mClipPath, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(input, 0, 0, mPaint);
outputCanvas.drawBitmap(output, 0, 0, null);
}
}
With this code, the image is drawn with properly rounded corners. To avoid the allocations on the first two lines of drawRoundedCornerBitmap, I want to draw directly to outputCanvas, which is the canvas originally passed to onDraw. The new implementation looks like this:
protected void drawRoundedCornerBitmap(...) {
mPaint.reset();
mPaint.setAntiAlias(true);
outputCanvas.drawARGB(0, 0, 0, 0);
mPaint.setStyle(Paint.Style.FILL);
outputCanvas.drawPath(mClipPath, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
outputCanvas.drawBitmap(input, 0, 0, mPaint);
}
For some reason, this code seems to ignore the Porter-Duff mode, and instead just draws the image with normal (non-rounded) corners. Why is this the case? What is it about drawing to an intermediate Bitmap that makes the original code work?
Create a drawable Romain Guy has done this for you. We are not a link factory but his blog post explains it quite extensively and provides an efficient way of doing this. Rounded Corners
The real basic principle, is create a BitmapShader and attach it to a Paint object which draws in a custom Drawable that way you just apply that Drawable to the ImageView.
Using a drawable means that the Image is only painted to a canvas once, meaning that drawing the image is only done once, then all the ImageView does is just scale the drawable.
I need to overlay two images in live wallpaper. The overlay images is the jpg which needs to be set to "additive" overlay. it adds the pixel value rather than calculating the transparency. how can i achieve this in android ?
You can make use of Android's Bitmap and Drawable classes mixed with Canvas, and try something like in this snippet:
public static Drawable mergeImage(Drawable orig, Drawable over, int left, int top) {
Bitmap original = ((BitmapDrawable)orig).getBitmap();
Bitmap overlay = ((BitmapDrawable)over).getBitmap();
Bitmap result = Bitmap.createBitmap(original.getWidth(), original.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(original, 0, 0, paint);
canvas.drawBitmap(overlay, left, top, paint);
return new BitmapDrawable(result);
}
I've coded a photo image gridview overlayered with "online status" using the above lines. Hope that it works for you too.
A more general approach may be to create a PorterDuffXfermode with your wanted PorterDuffMode and then set it on the Paint object that you use with your canvas, as referenced in mthama's answer but substituting some lines. This allows you to use other Porter-Duff modes as wanted/needed.
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(original, 0, 0, paint);
paint.setXferMode(new PorterDuffXferMode(PorterDuff.Mode.OVERLAY));
canvas.drawBitmap(overlay, left, top, paint);
Mind you, I haven't tried this, so go with mthama's answer. :)
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.