I am making a noughts and crosses game and i want to draw a line over the winning combination. The playing grid consists of a grid of buttons and i want the line to be over the top of them. At the moment the line will draw but it will have a black background hiding the grid of buttons even though it is set to transparent.
How would i make the transparency work then clear when i want to start a new game?
I hope that makes sense.
This is the draw class:
public class DrawView extends View {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public DrawView(Context context) {
super(context);
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawLine(0, 0, 1000, 1000, paint);
}
}
This is the part of the method in the game:
public void checkWin() {
if (squares[1] == 1 & squares[2] == 1 & squares[3] == 1) {
for (int i = 1; i <= 9; i++) {
buttons[i].setEnabled(false);
}
drawView = new DrawView(this);
drawView.setBackgroundColor(Color.TRANSPARENT);
setContentView(drawView);
Intent d = new Intent(this, Win.class);
startActivity(d);
If you want to draw a line with alpha, use :
paint.setAlpha(125);
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
Just remember to set it back after you use it, if you use paint else where.
Note:
0 = completely transparent
255 = completely opaque
Edit: Okay, I think you might be trying to clear the canvas, so it starts off blank.
Draw clear onto it, with PorterDuff to clear it.
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawLine(0, 0, 1000, 1000, paint);
}
I dont think your setBackgroundColor works because you have overriden the draw method. But I could be wrong, the above code should fix the issue.
Related
I need to draw some text on canvas, this text may single line or multi lines. I found StaticLayout can fill this require. But When I create an StaticLayout and after I want to draw it, I call getHeight(), I found it always return the line count. Shouldn't this function return the number of pixels?
This is my code:
m_staticLayout = new StaticLayout(m_message, textPaint, m_messageWidth,
Layout.Alignment.ALIGN_NORMAL, 1.0f, 0f, false);
Any help will be appreciated.
Firstly, StaticLayout is deprecated.
The reason it probably doesn't return pixels is because we haven't drawn anything yet, we're just initializing the StaticLayout. Hence, it returns the line count which we could probably use in the future. If you are trying to draw some text on Canvas, I wouldn't recommend using StaticLayout.
Instead, use the Paint class, Canvas, and Bitmap. Think of paint as the ink of the Canvas(which hosts all the draw calls). Canvas will draw into your Bitmap.
We will have to create the Paint, set up it's attributes, and then host the draw call drawText to the canvas. The Canvas will then draw the text using the Paint we created.
All of this will be in an Activity which extends View, which we will then pass as the View in setContentView for our MainActivity
This is how we can implement this:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
OtherActivity otherActivity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
otherActivity = new OtherActivity(this);
otherActivity.setBackgroundColor(Color.GRAY);
setContentView(otherActivity);
}
}
OtherActivity.java:
public class OtherActivity extends View {
public OtherActivity(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(20);
canvas.drawText("Some Text", 10, 25, paint);
}
}
I have a library that shows a camera preview. I want to add a rectangle overlay on top of the preview. I tried 2 different approaches. But both of them display the rectangle shortly then disappear.
approach (using view.getOverlay)
mPreview.setZOrderMediaOverlay(true);
mPreview.setZOrderOnTop(true);
ViewGroup rootView = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.addView(mPreview);
final ViewOverlay overlay = mPreview.getOverlay();
final Bracket bracket = new Bracket();
mPreview.post(new Runnable() {
#Override
public void run() {
bracket.setBounds(0, 0, mPreview.getWidth(), mPreview.getHeight());
overlay.add(bracket);
}
});
approach (overriding draw function in surfaceview)
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(10);
//center
int x0 = canvas.getWidth()/2;
int y0 = canvas.getHeight()/2;
int dx = canvas.getHeight()/3;
int dy = canvas.getHeight()/3;
//draw guide box
canvas.drawRect(x0-dx, y0-dy, x0+dx, y0+dy, paint);
}
mPreview extends SurfaceView
Bracket extends Drawable
UPDATE
If I use setContentView instead of rootView.addView it works as expected. But in this case I can not remove the view.
I used a new Activity and setContentView. That solved the problem.
To remove the view I finished the action.
I have a class Token which extends View. I override the onDraw method to draw two rects. After that i want to change the size of the Token object to match the size of the rects. For testing i added an onClickListener which should print out "Test"
layout = (RelativeLayout) findViewById(R.id.layout);
Paint p = new Paint();
Token a = new Token(0,0, Token.ONE, p, this);
layout.addView(a);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("test");
}
});
The Token class:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
tSize = canvas.getWidth()/Activity.SIZE;
paint.setColor(Color.BLACK);
r.set(0, 0, tSize, tSize);
canvas.drawRect(r, paint);
r.set(tSize, 0, 2 * tSize, tSize);
canvas.drawRect(r, paint);
}
So far so good. The problem is that it is always printing out "Test", no matter where i press on the screen. I figured that is because the View, which holds this two rects is the the size of the whole screen.
So i tried LayoutParams:
setLayoutParams(new RelativeLayout.LayoutParams(tSize*2, tSize);
This results in the rects not showing up at all(i think they got to small). I tried some other numbers:
setLayoutParams(new RelativeLayout.LayoutParams(600, 600);
This is working. The rects show up and the Listener only works in a 600x600 field. The only Problem is the rects are smaller than i want them to be. My guess is that their size is relative to the size of the view they are in.
How would i achive that my View is exactly (tSize*2, tSize) with the rects filling it out?
you may override onMeasure method to change the GameTokenView's size.
I have an ActionBar icon (the main one on the left, not an action item) that I would like to animate.
I am setting my ActionBar's icon in my Activity like this:
getSupportActionBar().setIcon(icon)
where icon is a Drawable produced by a library that converts a custom XML view into a bitmap. This XML view is a RelativeLayout with a background image and a TextView on top.
Today, when I have to update the TextView I simply re-generate the icon and call setIcon again. Instead, I would like to get a hold of my TextView and apply some animation effect on it, like fade-out and then fade-in after updating it (maybe never having to call setIcon, just re-use the same one).
Not sure how to go about this. Can someone recommend an approach?
EDIT: trying this approach:
In MyActivity:
Drawable myDrawable = new MyDrawable();
supportActionBar.setIcon(myDrawable);
and:
public class MyDrawable extends Drawable {
private Paint paint;
private RectF rect;
public MyDrawable() {
this.paint = new Paint();
this.rect = new RectF();
}
#Override
public void draw(Canvas canvas) {
paint.setARGB(255, 0, 255, 0);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.FILL);
rect.right = 20f;
rect.bottom = 20f;
canvas.drawRoundRect(rect, 0.5f, 0.5f, paint);
}
#Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
}
Nothing shows up. I verified that onDraw gets called. Something suspicious to me is that canvas has both height & width set to 1.
A proper approach for it would be to forget the XML layout and create a custom Drawable.
An instance of this custom drawable will be set to the icon on the ActionBar and call invalidateSelf() whenever necessary to redraw (due to animation, for example).
The drawable can hold reference to other drawables (e.g. BitmapDrawable to have something from the /res/ folder or a Color or Gradient drawable for a background shade) and call (for example) bgDraw.draw(canvas) during the onDraw callback.
It can also draw stuff directly on the canvas that is given to it during onDraw callback. With the canvas you can draw circle, lines, areas, path and text directly on it.
edit:
very simple animation example (didn't check the code, likely typos):
private long animationTime;
public void doAnimation(){
animationTime = System.currentTimeMilis() + 3000; // 3 seconds
invalidateSelf();
}
public void onDraw(Canvas canvas){
// do your drawing.
// You can use difference between
// currentTimeMilis and animationTime for status/position
...
// at the end
if(animationTime > System.currentTimeMilis())
invalidateSelf();
}
I would like to send each time different Drawable shape to view and then add it to my activity.
The problem is I can't find a way to add the drawable shape into the canvas when I'm overriding the onDraw method.
The design supposed to be reusable, I can draw rect first and then draw circle...
I want to find a way to send the view different shape. Is it possible?
#Override
protected void onDraw(Canvas canvas) {
// Draw the ball
ballBounds.set(ballX-ballRadius, ballY-ballRadius, ballX+ballRadius, ballY+ballRadius);
paint.setColor(Color.GREEN);
// canvas.drawOval(ballBounds, paint);
canvas.drawRect(ballBounds, paint);
}
Although, your question needs more explanation on what you need, but with what I could understand is you want rect, or circle on desire, here it is,
Add, global variable int ShapeStructure = 0;
#Override
protected void onDraw(Canvas canvas)
{
// Draw the ball
ballBounds.set(ballX-ballRadius, ballY-ballRadius, ballX+ballRadius, ballY+ballRadius);
paint.setColor(Color.GREEN);
if(ShapeStructure == 0){
canvas.drawOval(ballBounds, paint);
}else{
canvas.drawRect(ballBounds, paint);
}
}
Now that, you have a variable at your disposal, you can control what you want to paint.
Hope, this helps, let me know if you want something else.