Draw Circle at Center of Canvas - android

I'm just getting into basic drawing with Android. I'm starting off with a few simple shapes but I'm having a few issues. I'd like to draw a circle at the center of a canvas. I looked at a few examples but can't seem to make it work. I think it's because I don't really understand what variables go where.
Could someone please explain the proper way to draw my circle at the center of my screen. Here is my code:
public class Circle extends View{
int width = this.getWidth();
int height = this.getHeight();
public Circle(Context context) {
super(context);
setFocusable(true);
}
protected void onDraw(Canvas canvas){
canvas.drawColor(Color.CYAN);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
//canvas.drawCircle(100, 100, 50, paint);
canvas.drawCircle(width/2, height/2, 100, paint);
Display disp = ((WindowManager)this.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
float radius = 0;//Radius caused an error so I initialized this variable
canvas.drawCircle(disp.getWidth()/2, disp.getHeight()/2, radius, paint);
}
}

width and height of the view have not been yet initialized when getWidth() and getHeight() are called, just use getWidth() and getHeight() in onDraw:
canvas.drawCircle(getWidth()/2, getHeight()/2, 100, paint);
You can also override onSizeChanged and get view width and height.
PS: do not create anything in onDraw, create the paint object in the constructor.

public void drawCircle(Graphics2D g, int x, int y, int radius) {
x = x-(radius/2);
y = y-(radius/2);
g.fillOval(x,y,radius,radius);
}
here x,y is the position of canvas where you want to draw circle and you can find it with motion listener if you want to set x,y position dynamically hope this will help you

There are some links which are very useful for us and I hope they will work for you and other.
https://github.com/swapgo20/Android-Hand-Drawing
https://github.com/codepath/android_guides/wiki/Basic-Painting-with-Views
https://github.com/Korilakkuma/CanvasView
I hope above links are very useful to draw shapes on canvas.
I suggest you use third link and use only Path class (http://developer.android.com/reference/android/graphics/Path.html) of android to draw shapes.

Related

Android canvas fill background color (Canvas application)

By having the following codes, I have some questions.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView( new View(this) {
Paint mPaint = new Paint();
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int width = this.getWidth();
int height = this.getHeight();
int radius = width > height ? height/2 : width/2;
int center_x = width/2;
int center_y = height/2;
// prepare a paint
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setAntiAlias(true);
// draw a rectangle
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.FILL); //fill the background with blue color
canvas.drawRect(center_x - radius, center_y - radius, center_x + radius, center_y + radius, mPaint);
// draw some text and rotation
mPaint.setTextSize(50);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setColor(Color.BLACK);
canvas.drawText( "Hello World" , center_x , center_y, mPaint);
}
});
}
}
Q1: How can I fill blue colour in the frame? (The words still appear)
Q2: How many views and surfaces in this app? How can I count these in the app?
Q3: How many windows in this app?
Q4: In the code, I dont see any bitmap object in it.
However, I thought that bitmap is the object that I can really draw things on it. Is my
understanding incorrect?
One possibility is that Canvas constructor initializes bitmap when it is newed.
Q5: I knew that these graphic thing will finally go to surface and then pass to
surfaceflinger for final composition. Where does it locate in my code?
Thanks for any reply.
Five questions. Let's see where I can help.
Q1: Tell the Paint to fill the rectangle: paint.setStyle(Paint.Style.FILL);
Q2: I see only the one view you create programmatically. Why would you like to count the views?
Q3: Again: One
Q4: You draw an mutable bitmaps by wrapping them with a Canvas. The method to actually draw are part of Canvas
Q5: The code you show is part of an Activity. The Activity is called by Android. It's your entry point into your App.
Thanks for the answer. I did the job of making the code for marked answer, and it works.
Bitmap bg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bg);
// paint background with the trick
Paint rect_paint = new Paint();
rect_paint.setStyle(Paint.Style.FILL);
rect_paint.setColor(Color.rgb(0, 0, 0));
rect_paint.setAlpha(0x80); // optional
canvas.drawRect(0, 0, width, height, rect_paint); // that's painting the whole canvas in the chosen color.
Q2:Hierarchy Viewer is very useful when you want to count how many views in your app.
Optimizing Your UI

canvas drawtext direction

how to make that text was written vertically? how to rotate text 90 degrees?
Write each letter individually is stupid, but now ,i don't know another way.
Paint paint = new Paint();
public DrawView(Context context, double arr[])
{
super(context);
paint.setColor(Color.BLACK);
}
#Override
public void onDraw(Canvas canvas)
{
canvas.drawText("Test",50, 50, paint);
}
Simply rotating text (or anything else) is easy: Use the rotate() method to rotate the canvas (afterwards it is rotated back, otherwise everything you draw becomes rotated):
canvas.save();
canvas.rotate(90f, 50, 50);
canvas.drawText("Text",50, 50, paint);
canvas.restore();
The save() and restore()methods respectively save the state of the canvas and restores it. So the rest of your drawn elements are not rotated. If you only want to paint the text these two methods are not necessary.
If you want to put the characters of the string under each other, you need to process each character separately. First you'd need to obtain the font height and when drawing each character you need to increase the y-coordinate with this height over and over again.
int y = 50;
int fontHeight = 12; // I am (currently) too lazy to properly request the fontHeight and it does not matter for this example :P
for(char c: "Text".toCharArray()) {
canvas.drawText(c, 50, y, paint);
y += fontHeight;
}
Correct version is :
Canvas canvas_front = new Canvas(bitmap_front);
Paint paint = new Paint();
paint.setColor(Color.rgb(140, 0, 0));
paint.setAlpha(80);
paint.setStrokeWidth(2);
canvas_front.drawLine(0, (float) (frontIV.getHeight() * 0.9),frontIV.getWidth(), (float) (frontIV.getHeight() * 0.9), paint);
canvas_front.save();
canvas_front.rotate((float) 90 , 50, 50);
canvas_front.drawText("Text",50, 50, paint);
canvas_front.restore();
frontIV.setImageBitmap(bitmap_front);

Issue with Canvas.rotate() in Android .How does it exactly work?

Please find the code of my onDraw method below(.I'm trying to rotate the canvas(//Rotate call -b) by 25 degrees after drawing the arc .But i find that the arc is still drawn from 0 to 50 degrees.I was expecting it to move by another 25 degrees.
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.RED);
int px = getMeasuredWidth() / 2;
int py = getMeasuredHeight() / 2;
// radius - min
int radius = 130;
// Defining bounds for the oval for the arc to be drawn
int left = px - radius;
int top = py - radius;
int right = left + (radius * 2);
int bottom = top + (radius * 2);
RectF rectF = new RectF(left, top, right, bottom);
paint.setColor(Color.RED);
paint.setStyle(Style.FILL);
//canvas.rotate(25,px,py);//Rotate call -a
canvas.drawArc(rectF, 0, 50, true, paint);
canvas.rotate(25,px,py);//Rotate call -b
}
}
But if i place the rotate call(//Rotate call -a) before drawing the arc i see that the arc drawn is shifted by 25 degrees more .What exactly is happening here? Can someone explain to me?
Thanks
The Canvas maintains a Matrix that is responsible for all transformations on it. Even for rotation. As you can see in the documentation, the rotate method says:
Preconcat the current matrix with the specified rotation.
All transformations are done on the Canvas Matrix,hence, on the Canvas. The arc you draw isn't rotated. You first rotate the Canvas and then draw on it.
Hence, in your code, call -a works, not call -b.
EDIT:
For issues like postrotate and prerotate check the Matrix class(postRotate and preRotate methods).
Few Examples: this and this.
And few things you might want to read : this and this.

ImageView with rounded corners and inner shadow

I need to make a thumbnail view with rounded corners and inner shadow. Usually I'm making ImageView frames with 9patches, which have served me well so far, but this time the effect I need requires drawing the inner shadow on top of the image (and not just around it). This lead me to extend the ImageView class and override the onDraw() method.
public class ThumbnailImageView extends ImageView {
After many tutorials (thanks StackOverflow!), I ended up with this code for the onDraw() method:
#Override
protected void onDraw(Canvas canvas) {
if (mBitmap == null) {
return;
}
int radius = 4;
int padding = 2;
int bleed = 2;
RectF frame = new RectF(padding, padding, getWidth() - padding, getHeight() - padding);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(0xFF000000);
canvas.drawRoundRect(frame, radius, radius, mPaint);
Shader bitmapShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(0xFF000000);
mPaint.setMaskFilter(new BlurMaskFilter(bleed, Blur.INNER));
mPaint.setShader(bitmapShader);
canvas.drawRoundRect(frame, radius, radius, mPaint);
}
What I'm basically doing, is drawing a black rounded rectangle first and then drawing a rounded-corners bitmap with fading edges (with the BlurMaskFilter) on top of it. The result is what I want:
The mBitmap value is initialized in the ImageView constructor like this:
mDrawable = getDrawable();
if (mDrawable != null) {
mBitmap = ((BitmapDrawable) mDrawable).getBitmap();
}
The problem is that I am overriding onDraw() completely (no super.onDraw()) is called, so I have to pre-scale all images to the desired thumbnail size (e.g. 96x96) or else only the top-left corner of the image is drawn. What I want to be able to do is take advantage of all the scaling the framework is doing when I assign the following xml values to the ThumbnailImageView:
android:id="#+id/thumb"
android:layout_width="96dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
To do this, I thought I should somehow call super.onDraw() while getting the effects I need at the same time. I have managed to get the rounded rectange by adding a clipping path to the canvas, but I can't find a way to add the inner shadow. This is the new onDraw() code:
#Override
protected void onDraw(Canvas canvas) {
int radius = 4;
int padding = 4;
RectF frame = new RectF(padding, padding, getWidth() - padding, getHeight() - padding);
Path clipPath = new Path();
clipPath.addRoundRect(frame, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
// add inner shadow
}
I can see two alternatives:
1) To properly pre-scale the ImageView's bitmap. But where is the best place to do it? In it's constructor? In the onDraw() method where the framework seems to be doing it? Is the framework even resizing any bitmap or is there another way to draw a scaled image on the canvas without being bad for performance?
2) To add the inner shadow layer on top of what the super.onDraw() is drawing so far, but I'm running out of ideas on how to do this.
Any help would be appreciated.
Thanks!
Take a look at Eric's (from squareup) presentation material from Oreilly's AndoridOpen Conference last year in his lecture titled Beautiful Android
It has a ton of info that should help you out.
I wish they had the video of his presentation somewhere. I could not find it. So sorry.
EDIT : Thanks to #mykola for the yt link

Canvas Larger Than Screen

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.

Categories

Resources