I have two paints and set their colors to different colors. The problem is that the second paint overrides the first paint.
That's my code:
public class Score {
static Globals g = Globals.getInstance();
private Rect bounds = new Rect();
private Paint paintBG = new Paint();
private Paint paintFG = new Paint();
private int mid;
public Score(Paint paint) {
this.paintBG = paint;
this.paintFG = paint;
// PROBLEME
paintBG.setColor(Color.GRAY);
paintFG.setColor(Color.WHITE); // <-- this paint overrides the paint before
}
public void draw(Canvas canvas) {
String score = String.valueOf(g.getScore());
paintFG.getTextBounds(score, 0, score.length(), bounds);
mid = (canvas.getWidth() / 2) - (bounds.width() / 2);
// different "paints" but the same color
canvas.drawText(score, mid, 60, paintBG);
canvas.drawText(score, mid, 50, paintFG);
}
}
Best regards from germany. :)
amahfouz has explained the problem. One solution to the problem is to use Paint's copy constructor.
public Score(Paint paint) {
paintBG = new Paint(paint);
paintFG = new Paint(paint);
paintBG.setColor(Color.GRAY);
paintFG.setColor(Color.WHITE);
}
This is expected. Both paints are referring to the same Paint object, the one passed as a parameter. So basically, both calls to setColor are modifying the same object and the last one is the one that sticks!
zum wohle!
Related
I made a custom View Class that draws the waveform of an audio file, unfortunately, I'm having some problems with changing the background color of the canvas/custom view to transparent.
I can change the background color inside the onDraw function canvas.drawColor(Color.WHATEVER);
However, this works with any color but transparent, which shows black instead.
This works: canvas.drawColor(Color.BLUE);
This doesn't: canvas.drawColor(Color.TRANSPARENT);
Also, if I use the Android Studio Layout inspector, it seems to actually work, but in reality it does not. See the screenshot here:
Layout Inspector vs Android Emulator Screenshot
public class SimpleWaveform extends View {
Context context;
public Paint beforePlaySectionPencil = new Paint();
public Paint playSectionPencil = new Paint();
public Paint afterPlaySectionPencil = new Paint();
public Paint peakPencilBefore = new Paint();
public Paint peakPencilPlay = new Paint();
public Paint peakPencilAfter = new Paint();
public Paint xAxisPencil = new Paint();
public void init() {
beforePlaySectionPencil.setStrokeWidth(10);//set bar width (ERA /2)
beforePlaySectionPencil.setColor(ContextCompat.getColor(getContext(), R.color.aaDarkBlue));
playSectionPencil.setStrokeWidth(10); // (ERA /2)
playSectionPencil.setColor(ContextCompat.getColor(getContext(), R.color.aaLightBlue));
afterPlaySectionPencil.setStrokeWidth(10); // (ERA /2)
afterPlaySectionPencil.setColor(ContextCompat.getColor(getContext(), R.color.aaDarkBlue));
peakPencilBefore.setStrokeWidth(barGap / 8);//set peak outline width (ERA /6)
peakPencilBefore.setColor(0xfffe2f3f);
peakPencilPlay.setStrokeWidth(barGap / 8); //(ERA /6)
peakPencilPlay.setColor(0xfffe2f3f);
peakPencilAfter.setStrokeWidth(barGap / 8); //(ERA /6)
peakPencilAfter.setColor(0xfffe2f3f);
xAxisPencil.setStrokeWidth(1);
xAxisPencil.setColor(0x88ffffff);
#Override
protected void onDraw(Canvas canvas) {
if (clearScreenListener != null) {
clearScreenListener.clearScreen(canvas);
} else {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
}
if (clearScreen) {
clearScreen = false;
return;
}
drawWaveList(canvas);
canvas.drawColor(Color.TRANSPARENT);
}
private void drawWaveList(Canvas canvas) {
if (showBar) {
canvas.drawLines(barPoints, 0, playSectionLeftOffset * barUnitSize, beforePlaySectionPencil);
canvas.drawLines(barPoints, playSectionLeftOffset * barUnitSize, (playSectionRightOffset - playSectionLeftOffset) * barUnitSize, playSectionPencil);
canvas.drawLines(barPoints, playSectionRightOffset * barUnitSize, (barNum - playSectionRightOffset) * barUnitSize, afterPlaySectionPencil);
}
if(showXAxis){
canvas.drawLines(xAxisPoints, xAxisPencil);
}
}
}
I did a bit of research and found out how to achieve that in a canvas.
Take a look at this explanation.
I need to create a view that is filled with a dynamic color at runtime. I've accomplished this task however the actual view needs to have a "peak" on the right side. Typically ImageView's are only square or rectangular. Does anyone know how I would accomplish adding a triangular peak to the view?
For example:
You can override the onDraw event of the ImageView and do whatever you need with the canvas object.
public class MyImageView extends ImageView {
...
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
Point[] point = ... //create three points here for the triangle
Paint paint = ... // create your desired color
drawTriangle(canvas, point, paint);
}
And for the triagle draw (see this SO answer):
private void drawTriangle(Canvas canvas, Point[] point, Paint paint) {
float [] points = new float[8];
points[0] = point[0].x;
points[1] = point[0].y;
points[2] = point[1].x;
points[3] = point[1].y;
points[4] = point[2].x;
points[5] = point[2].y;
points[6] = point[0].x;
points[7] = point[0].y;
canvas.drawVertices(VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
Path path = new Path();
path.moveTo(point[0].x , point[0].y);
path.lineTo(point[1].x,point[1].y);
path.lineTo(point[2].x,point[2].y);
canvas.drawPath(path,paint);
}
So i've come across this problem that i simply can't manage to sort out.
I'm making a game with the help of LibGdx and am trying to create a chat bubble functionality. The problem is, when i try to change the background of the label style to a 9patch drawable, it doesn't scale it well, or at all?
public class ChatBubble
{
private Label textLabel;
private BitmapFont font;
private Label.LabelStyle lStyle;
private int scaledWidth = 0;
private int scaledHeight = 0;
private Timer.Task currentTask;
private Texture bkg;
public ChatBubble()
{
font = new BitmapFont();
font.setColor(Color.BLACK);
bkg = new Texture("data/ui/chatb.9.png");
NinePatch np = new NinePatch(bkg,11,11,9,10);
NinePatchDrawable npd = new NinePatchDrawable(np);
lStyle = new Label.LabelStyle(font,font.getColor());
lStyle.background = npd;
textLabel = new Label("",lStyle);
textLabel.setVisible(false);
textLabel.setAlignment(Align.center);
currentTask = new Timer.Task() {
#Override
public void run() {
textLabel.setVisible(false);
}};
}
public void show(String text, float duration)
{
if(currentTask.isScheduled())currentTask.cancel();
textLabel.setText(text);
textLabel.setVisible(true);
scaledHeight = (int)textLabel.getPrefHeight();
scaledWidth = (int)textLabel.getWidth()/2;
Timer.schedule(currentTask,duration);
}
public void show(String text)
{
if(currentTask.isScheduled())currentTask.cancel();
textLabel.setText(text);
textLabel.setVisible(true);
scaledHeight = (int)textLabel.getPrefHeight();
scaledWidth = (int)textLabel.getWidth()/2;
Timer.schedule(currentTask,(float)(text.length()*0.1));
}
public void draw(SpriteBatch batch, float x, float y)
{
if(!textLabel.isVisible())return;
textLabel.setPosition(x - scaledWidth, y + scaledHeight);
batch.begin();
textLabel.draw(batch, 1);
batch.end();
}
}
How it looks ingame:
How the 9batch looks:
Any help would be appreciated!
Update:
I've found out that my 9patch scales ok, the problem being in label not updating it's size when setText() is called, thus having it width and height 0 since constructor was "".. calling layout() on label doesn't solve this either.
Call .pack() on the label after .setText() to tell it to size itself to its text (plus whatever padding there is in the background drawable). You don't need to call layout() since that's handled automatically.
I'm not sure the exact reason you have to manually call pack(), but this is generally the case with Widgets that you are not children of a WidgetGroup subclass (i.e. Table, VerticalGroup, etc.).
Okay, I am not sure how to describe this. I have made a Class called ScreenAreas that defines specific areas on the screen. Later on, I am drawing these ScreenAreas.
What I would like to do, is to couple Paint attributes (Color, strokeWidth, Shaddowsettings, etc) to these ScreenAreas, in such a way, that I don't have to reset all these attributes, when drawing them again.
This is my ScreenArea Class:
import android.graphics.Canvas;
import android.graphics.Paint;
public class ScreenArea {
private int xMin;
private int yMin;
private int xMax;
private int yMax;
private Paint paint;
public ScreenArea(int x1, int x2, int y1, int y2, Paint paint) {
this.setXMin(x1);
this.setXMax(x2);
this.setYMin(y1);
this.setYMax(y2);
this.paint = paint;
}
// I removed the getters and setters for clarity
public void draw(Canvas canvas){
canvas.drawRect(this.xMin, this.yMin, this.xMax, this.yMax, this.paint);
}
}
And in my main Class I am constructing them using:
paint.setColor(Color.rgb(10,10,10));
area1 = new ScreenArea (
0,
0,
100,
100,
paint);
paint.setColor(Color.rgb(100,100,100));
area2 = new ScreenArea(
20,
20,
80,
80,
paint);
When I try to draw them, I simply do:
area1.draw(canvas);
area2.draw(canvas);
Both of the area's will be given the same color, though. In fact they are given the last color used. Probably, this is because the Paint objects in the ScreenArea are simply pointing to the same Paint object in the main Class. The question is, how to solve this problem!
Anyone?
You should remember that Paint object has a copy constructor. So instead of:
this.paint = paint;
within your ScreenArea constructor, you can use:
this.paint = new Paint(paint);
The answer is good, but if for some reason you don't want to instantiate a new Paint (perhaps because you're inside onDraw(), which I realize is not the case here) then you can use Paint.set().
public void set (Paint src) Added in API level 1
Copy the fields from src into this paint. This is equivalent to
calling get() on all of the src fields, and calling the corresponding
set() methods on this.
Replace private Paint paint; with private Paint paint = new Paint(); and then this.paint = paint; (which just copies to pointer to the Paint object) with this.paint.set(paint); (which copies the fields from paint to this.paint.
I'm trying to make custom brushes for my Android painting app. I started with Michael's code (found here) and I have managed to get .png brushes and use that as a bitmap and redraw it. It works fine but I can't change the colour. Tried using the setcolorfilter and colormatrixfilter but it doesn't seem to be working. Anyone knows how I can do this?
private Bitmap mBitmapBrush;
private Vector2 mBitmapBrushDimensions;
private List<Vector2> mPositions = new ArrayList<Vector2>(100);
private Paint mPanit;
public MyView(Context c) {
super(c);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mBitmapBrush = BitmapFactory.decodeResource(c.getResources(),R.drawable.brush1);
mBitmapBrushDimensions = new Vector2(mBitmapBrush.getWidth(), mBitmapBrush.getHeight());
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Vector2 pos : mPositions) {
canvas.drawBitmap(mBitmapBrush, pos.a, pos.b, mPanit);
}
invalidate();
}
When I tried using the Colormatrixfilter, the .set function was giving an error.
I had the same issue. In order to change the bitmap color you need to add color to your paint object and apply it into bitmap. See the working example here,
for (Vector2 pos : customBrushMap.get(p)) {
Paint paint = new Paint();
ColorFilter filter = new PorterDuffColorFilter(R.Color.GREEN, PorterDuff.Mode.SRC_IN);
paint.setColorFilter(filter);
canvas.drawBitmap(mBitmapBrush, pos.x, pos.y, paint);
}
Result,