customize the stroke to have a border and a fill - java

How can I draw a stroke with a fill color and a (different color) border?
e.g. I want something like this:
I tried creating 2 paints - one with a Stroke style and one with a Fill style, but calling
strokePaint = new Paint();
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setColor(Color.parseColor("#A3A3A3"));
fillPaint = new Paint();
fillPaint.setStyle(Paint.Style.FILL);
fillPaint.setColor(Color.WHITE);
canvas.drawPath(totalPath, strokePaint);
canvas.drawPath(totalPath, fillPaint);
doesn't create the intended effect and looks quite bad.
Is it even possible?

Figured it out. The trick is to draw it twice, once as a background layer that is 1-2 pixels thicker, and then the foreground layer.
i.e. :
strokePaintBackground = new Paint(Paint.ANTI_ALIAS_FLAG);
strokePaintBackground.setStyle(Paint.Style.STROKE);
strokePaintBackground.setColor(Color.BLACK);
strokePaintBackground.setStrokeWidth(8);
strokePaintBackground.setPathEffect(new DashPathEffect(new float[]{30, 15}, 0));
strokePaintBackground.setStrokeCap(Paint.Cap.ROUND);
strokePaintBackground.setStrokeJoin(Paint.Join.ROUND);
strokePaintForground = new Paint(Paint.ANTI_ALIAS_FLAG);
strokePaintForground.setStyle(Paint.Style.STROKE);
strokePaintForground.setColor(Color.WHITE);
strokePaintForground.setStrokeWidth(6);
strokePaintForground.setPathEffect(new DashPathEffect(new float[]{30, 15}, 0));
strokePaintForground.setStrokeCap(Paint.Cap.ROUND);
strokePaintForground.setStrokeJoin(Paint.Join.ROUND);
canvas.drawPath(totalPath, strokePaintBackground);
canvas.drawPath(totalPath, strokePaintForground);

Related

Shadow around transparent Rect in Canvas

I just want the shadow of an empty box. But if I give the Rect a transparent Paint color the shadow becomes transparent too. Is this possible?
Paint paint = new Paint();
//paint.setColor(0x00000000);
paint.setShadowLayer(10, 0, 0, Color.BLACK);
Rect rect = new Rect(0, 0, 100, 100);
canvas.drawRect(rect, paint);
I ended up creating a second Canvas and a second Bitmap and then merge them after I cut out some parts with PorterDuff.Mode.CLEAR. This way I create layers like in image editing applications and don't lose the background.
This is how I cut parts out:
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
Rect rect = new Rect(left, top, right, bottom);
canvas.drawRect(rect, paint);
And this is how I put the layers back together:
bottomCanvas.drawBitmap(topBitmap, 0, 0, null);

How to draw a circle on a bitmap without filling it?

I am ddrawing a circle on the bitmap and setting this bitmap to ImageView. the circle is drawn correctly but i dont want it to be a filled circle is there any way to make the filled area transparent?
i am using the following code
Bitmap bmp = RasterImageConverter.convertToBitmap(_loadedImage, ConvertToImageOptions.NONE.getValue());
Canvas c = new Canvas(bmp);
c = new Canvas(bmp);
myimgview.draw(c);
Paint p = new Paint();
p.setColor(Color.RED);
float x=(float) circleX;
float y=(float) circleY;
float Tx=(float) textX;
float Ty=(float)textY;
// c.drawLine(x, y, xend, yend, p);
c.drawCircle(300, 300, 200, p);
c.drawText(myText, Tx, Ty, p);
myimgview.setImageBitmap(bmp);
You need to inform the paint that you dont' use a fill style, but a stroke style.
The default is FILL
The Style specifies if the primitive being drawn is filled, stroked, or both (in the same color). The default is FILL.
So your code must be:
Paint p = new Paint();
p.setStyle(Paint.Style.STROKE);
Here are explained the differences between the different styles.
STROKE
Geometry and text drawn with this style will be stroked, respecting the stroke-related fields on the paint.
FILL
Geometry and text drawn with this style will be filled, ignoring all stroke-related settings in the paint.
FILL_AND_STROKE
Geometry and text drawn with this style will be both filled and stroked at the same time, respecting the stroke-related fields on the paint.
You need to change the Paint style to stroke:
Paint p = new Paint();
p.setStyle(Paint.Style.STROKE);
Use the setStyle(Paint.Style.STROKE) method on your paint p instance.
You are almost there... you need to set the style of the Paint object...
by invoking the method
p.setStyle(Paint.Style.STROKE);
The options are:
Example:
Bitmap bmp = RasterImageConverter.convertToBitmap(_loadedImage, ConvertToImageOptions.NONE.getValue());
Canvas c = new Canvas(bmp);
c = new Canvas(bmp);
myimgview.draw(c);
Paint p = new Paint();
p.setColor(Color.RED);
p.setStyle(Paint.Style.STROKE);

set different colors to some different circles

i have two circles (want to have some more in the future) and want them to have different colors. At the moment, the color is set with:
public static Paint p = new Paint();
p.setColor(Color.GREEN);
The Problem is that every new Circle I create has this color too.
How can I set new colors for different new circles?
This is where I instantiate the circles (in the constructor):
c1 = new Circle (165, 350, 33);
c2 = new Circle (200, 200, 33);
p.setColor(Color.GREEN);
p1.setColor(Color.YELLOW);
And this is where I call the draw in my "onDraw()":
canvas.drawCircle(lerpX, lerpY, c1.getR(), p);
canvas.drawCircle(c2.getX(), c2.getY(), c2.getR(), p);
Thanks in advance
This is a simple way to do it. Almost procedural but it will work.
Define your color
p.setColor(Color.GREEN);
//draw shape
Define next color
p.setColor(Color.RED);
//draw next shape

Add text with grey background to pictures like Snapchat does? Android/Java

Bitmap newBm = ...
Canvas canvas = new Canvas(newBm);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setTextSize((int) (44 * scale));
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
canvas.drawText(gText, x, y, paint);
I drew text on the Bitmap like so. How could I get a grey background that is the same height as the text but covers the whole screen??
You could use a Rect. Before drawing the text draw the Rect to the screen:
int screenWidth = getApplicationContext().getResources().getDisplayMetrics().widthPixels;
Rect greyBack = new Rect(0,top,screenWidth,bottom);
Paint paint = new Paint();
paint.setARGB(128, 100, 100, 100); //added alpha because Snapchat has translucent //grey background
canvas.drawRect(greyBack, paint);
top and bottom need to be coordinates above and below the text. You could use y's value and take away a bit for top and add a bit for bottom. How much you add/subtract is up to you and changes the height of the greyBack background.
The best way to see and learn how these sort of things are done with well written code is to look at the android source code itself. For example here is the onDraw method for a TextView it includes additional stuff you won't probably need like compoundPadding, but you can follow it through and get the basic concept of how it's done.

How to change the color of the background in libgdx labels?

I can change the color of the font like this
LabelStyle style1 = new LabelStyle(..some font...,
Color.valueOf("FF4500")
);
label.setStyle(style1);
but how do I change the background?
right now the background is the same as the background of whole screen which is set in
render method lke this
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(
1.000f, 0.980f, 0.941f
,1);
Label label = new Label(labelText, skin);
Pixmap labelColor = new Pixmap(labelWidth, labelHeight, Pixmap.Format.RGB888);
labelColor.setColor(<your-color-goes-here>);
labelColor.fill();
label.getStyle().background = new Image(new Texture(labelColor)).getDrawable();
Basically, use the getDrawable() function of the Image class to assign the color of your Label's LabelStyles' background Drawable.
This is the simplest workaround I've been able to come up with and, frankly, it's just silly that there is no setBackground() in the Label class.
Actually, maybe the easiest fix is to hack the Label class and add a setBackground() method to it.
[Edit] Be sure to dispose of Pixmaps when you are done with them; i.e. labelColor.dispose();
[Update] #Mitrakov Artem made a good point: The above solution will affect all instances of this LabelStyle. If that's not what you want you can create a new LabelStyle, use the above method on it, then save it to the Label. Quoting Artem: "So I would recommend to create a new style (LabelStyle style = new LabelStyle(label.getStyle());), change its background and then apply it to the label (label.setStyle(style);)"
Actually you do not change the background of the Lable like that. You did just change the clearcolour. Guess you know that.
To change the background you need to change the background at the style of the label. To do so i'd recommend to use a simple NinePatch as background, (can be a square! if its white you can change the colour of the ninepatch and the background colour changes!)
NinePatch temp = new NinePatch(new Texture(....), 10, 10, 10, 10); //edges
For more information about ninepatch take a look here libgdx wiki ninepatch
You need to add that ninepatch to an Skin objekt. For example like this
Skin skin = new Skin();
skin.add("background",temp)
After that you can get a drawable from the skin that you can set as background of the LabelStyle.
style1.background = skin.getDrawable("background");
see libgdx API LabelStyle
You can also use a simple bitmap but that does get scaled to the label size which causes in most of the cases deformation. A Ninepatch can be scaled without having deformation.
If you need a quick and easy solution, you can use the snippet below. It doesn't work well with multiline text because it doesn't take the text width per line into account.
Anyway, the background is automatically adjusted to the width and height of the label widget (i.e. if your text changes).
private Label label = new Label("text", createLabelStyleWithBackground());
private LabelStyle createLabelStyleWithBackground() {
LabelStyle labelStyle = new LabelStyle();
labelStyle.font = new BitmapFont();
labelStyle.fontColor = Color.WHITE;
labelStyle.background = createBackground();
return labelStyle;
}
private Drawable createBackground() {
Pixmap labelColor = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
Color color = new Color(Color.GRAY);
color.a = 0.75f;
labelColor.setColor(color);
labelColor.fill();
Texture texture = new Texture(labelColor);
return new BaseDrawable() {
#Override
public void draw(Batch batch, float x, float y, float width, float height) {
GlyphLayout layout = label.getGlyphLayout();
x = label.getX();
y = label.getY() - (layout.height + 15) / 2; // +15 is some space
batch.draw(texture, x, y, layout.width, layout.height + 15);
}
};
}
here is an example with a multiline label

Categories