For days I tried to implement a simple Imagebutton in Android, using a dynamic LinearGradient as background. I want the base design from android.R.drawable.btn_default, which is colored starting from the left edge of the button to a value given in percent from v = 0-100%(right edge). The edge between the left and right part of the button should be sharp (like an equalizer). For any suggestions without NullException errors I would be very thankful!
EDIT 29.07.14
Here is the code snippet, working without errors:
Drawable dr = getResources().getDrawable(android.R.drawable.btn_default);
Bitmap bitmap = Bitmap.createBitmap(dr.getIntrinsicWidth(), dr.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
dr.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
dr.draw(canvas);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
paint.setShader(new LinearGradient(0, 0, canvas.getWidth()*7*vol, 0, new int[] { Color.GREEN, Color.TRANSPARENT }, new float[] { 0, 1 }, Shader.TileMode.CLAMP));
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
mButtonSpeech.setBackground(new BitmapDrawable(getResources(), bitmap));
But even without the middle part of my code, adding the gradient to the canvas, the button background does not look like I expect it (it is to small and in the center not colored like the other buttons, where I set the backgrund by:
mButtonDraw.setBackgroundResource(android.R.drawable.btn_default);
If I also draw the Paint into Canvas, I would expect the default button background, colored in the left part, like I could do it with setColorFilter().
Related
I need to apply dynamically a gradient color to a bitmap (it looks like a scratch with some transparent parts) that will be draw over another bitmap: this is the result i need.
This is my code:
Bitmap bitmapbackground = bitmaporiginal.copy(bitmaporiginal.getConfig(), true);
Bitmap bitmaptocolor = BitmapFactory.decodeResource(activity.getResources(), R.drawable.scratch);
LinearGradient gradient = new LinearGradient(0, 0, 0, bitmaptocolor.getHeight(), Color.parseColor("#D81B60"), Color.parseColor("#F48FB1"), Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(gradient);
Canvas canvas = new Canvas(bitmapbackground);
canvas.drawBitmap(bitmaptocolor, 0, 0, paint);
But in this way it does not apply the gradient color to the scratch (it remains always black). What am i doing wrong ?
Make sure bitmaptocolor.getHeight() is actually returning height.
Use hexadecimal equivalent for color.
LinearGradient gradient = new LinearGradient(0, 0, 0, bitmaptocolor.getHeight(), 0xD81B60, 0xD81B60, Shader.TileMode.CLAMP);
So I have the following image to be used as a mask:
Now I want to apply this mask to images so that the image will fill the inner white space but will not fill the borders, keeping it as it is. However, when I use the code below, the image takes the inner white space plus the border.
public static Bitmap applyMask(Bitmap scaledBitmap, Bitmap mask) {
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(scaledBitmap, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
return result;
}
So is there any way to make the image fill only the white space? How can I keep the mask borders intact?
Thanks in advance.
I had to download your image to see the transparent areas. They are on the outside of your shape (which is why DST_IN is the mode that works for this).
What the DST_IN mode does is erases any pixels already on the canvas where the pixels in the mask are transparent. So whether it's the dark border or the white inside, those pixels all have alpha > 0, so they mask the canvas just the same. Those pixels outside the shape have alpha == 0, so they erase the canvas pixels.
Since the final bitmap is the size of your mask, as I see it you have two options:
OPTION 1: If you can put the background color in the mask image:
Change your mask image so that the transparent pixels are inside the shape, and the pixels outside the shape are your background color. Then use SRC_OVER as your xfer mode. The background color outside the border, plus the black border will overwrite the existing pixels in this mode, and since the inner pixels are transparent, the middle part of the image will come through the way you want.
OPTION 2: If you have to specify the background color in the app so you can't put it in the mask image:
For this you'll need two mask images, the one you have and a copy with the inside pixels transparent as well, so you are left with the border. Draw with your mask image the way you are doing right now using DST_IN, then draw the image with just the border using SRC_OVER to draw the border on top of your masked image.
Here you have an example of what you want and you can adapt it to your case:
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = 12;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
I've found it here. Hope it helps! :)
I'm using the mask a bitmap with another. The operation succeeds well, unfortunately the result of masking seen a slight black border, as you can see in the image:
How do I remove this border? in the source image is not there.
I'll post the code I'm using:
public Bitmap mask(Bitmap source) {
Bitmap targetBitmap = Bitmap.createBitmap(getWidth(),getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
paint.setAntiAlias(true);
paint.setDither(true);
canvas.drawBitmap(source, 0, 0, null);
canvas.drawBitmap(getMask(), 0, 0, paint);
paint.setXfermode(null);
return targetBitmap;
}
where getMask () returns the Bitmap that represents the figure of the Puzzle.
I hope to receive your help, thank you all
Sorry for my english :-)
UPDATE:
the black border is what I point out in this picture:
UPDATE:
place the sequence of transformation. The third image would be identical to the first but without color. The problem is the black edge of the puzzle.
I hope to be more clear:
The way I draw images with mask is kind of the other way around from what you do.
public Bitmap mask(Bitmap source) {
Bitmap targetBitmap = Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
// paint.setAntiAlias(true); // you've already set this in the constructor
paint.setDither(true);
canvas.drawBitmap(getMask(), 0, 0, null);
canvas.drawBitmap(source, 0, 0, paint);
// paint.setXfermode(null); // no need for this
return targetBitmap;
}
Note that PorterDuff.Mode is set to SRC_IN (not DST_in) and that the mask is drawn first and then the image on top of that mask. With this approach you can also draw the previous source as the base mask, add the new (puzzle) mask and then draw the final source/image on top of that with SRC_IN paint to add new puzzle pieces each time.
If that doesn't solve the black border, check that your mask doesn't have feathered (transparent) edges that might be causing these problems.
Also, ANTI_ALIAS_FLAG doesn't do anything on textures. If you want smoothly scaled textures use paint.setFilterBitmap(true);
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. :)
Is there a way to put a gradient to a bitmap object in android 2.1? The image must look like this:
I need the gradient only on top of the bitmap. DrawableGradient or LinearGradient are only from android 2.2 so these objects doesn't help me at all. Thanks
Do you need this from XML or from code? In code, try this:
/* Create a 200 x 200 bitmap and fill it with black. */
Bitmap b = Bitmap.createBitmap(200, 200, Config.ARGB_8888);
Canvas c = new Canvas(b);
c.drawColor(Color.BLACK);
/* Create your gradient. */
LinearGradient grad = new LinearGradient(0, 0, 0, 50, Color.GRAY, Color.BLACK, TileMode.CLAMP);
/* Draw your gradient to the top of your bitmap. */
Paint p = new Paint();
p.setStyle(Style.FILL);
p.setShader(grad);
c.drawRect(0, 0, 200, 50, p);
In XML, just make two separate views in a vertical linear layout. The top view should have a gradient drawable background, the bottom, taller view should have a solid background.