Drawing something on my LinearLayout? - android

I'm extending LinearLayout:
public class MyLinearLayout extends LinearLayout {
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(0xFFFF0000);
canvas.drawLine(0, 0, getWidth(), getHeight(), paint);
}
}
If the layout has child elements, shouldn't the red line above be drawn on top of them? Considering a layout like:
<MyLinearLayout>
<ImageView />
</MyLinearLayout>
I'd expect to get the red line drawn above the child ImageView. But it gets drawn below it. I was assuming all child drawing would have been completed after the super.onDraw() line is finished.
Is there a way to get to the canvas and draw something on it after all child drawing has been completed?
Thanks

Layouts don't draw unless you call setWillNotDraw(false);. They do that for efficiency reasons.
EDIT:
onDraw() really is meant to just allow you to modify the Canvas before the drawing operation happens. It doesn't actually draw. What you want to do is override draw() like so:
#Override
protected void draw(Canvas canvas) {
super.draw(canvas);
Paint paint = new Paint();
paint.setColor(0xFFFF0000);
canvas.drawLine(0, 0, getWidth(), getHeight(), paint);
}
Calling the super will draw all the children in the view. Then it will draw all the lines. I do still believe you need setWillNotDraw(false) to be called though.

I'm rewriting my answer as I hadn't seen your line of code where you were drawing to the canvas.
The canvas like some other graphics environments is inverted. So calling getHeight() is actually drawing the line at the bottom. Instead call
canvas.drawLine( 0, 0, getWidth(), 0, paint);
This means draw the line at the top, across the width of the view.
Also, calling super first paints the children prior to any custom painting so your fine there.

If you have a LinearLayout and you need:
draw all of its children first, like buttons, image views
then, on top of those components, draw something directly on the canvas.
You can try this:
public class YourClass extends LinearLayout
{
#Override
protected void dispatchDraw(Canvas canvas)
{
super.dispatchDraw(canvas);
// do your custom drawings afterwards
canvas.drawCircle...
canvas.drawLine...

Related

Xamarin Android: How to draw on top of Canvas

I am writing a custom renderer for Xamarin.Forms. I am overriding the class ImageRenderer to do some tweaks to the image.
However, I want to overlay some parts of the image with circles, so I override the method void OnDraw(Canvas canvas).
Then I modify the Canvas a bit by drawing some circles:
protected override void OnDraw(Canvas canvas)
{
var paint = new Paint
{
Color = Color.Red
};
paint.SetStyle(Paint.Style.Fill);
foreach (var mapObject in _control.PointSource)
{
canvas.DrawCircle(mapObject.Location.X, mapObject.Location.Y, 100 / _scaleFactor, paint);
}
base.OnDraw(canvas);
}
However, everything is drawn on the background. The actual image is always on top. How can one draw circles on top of the image?
https://developer.xamarin.com/api/member/Android.Views.View.OnDraw/
In the docs they say the following:
the canvas on which the background will be drawn
So the current behaviour was expected.
I managed to fix it by moving the circle logic to the function: void Draw(Canvas canvas).

Canvas.drawRect is not work in TextView's onDraw when set gravity

I have a custom view extends form TextView,and write some code in onDraw():
#Override
protected void onDraw(Canvas canvas) {
if (mTextShader == null) {
createShader();
}
shaderMatrix.setTranslate(mProgressWidth,0);
mTextShader.setLocalMatrix(shaderMatrix);
Paint paint = new Paint();
paint.setShader(mBgShader);
canvas.drawRect(0,0,mProgressWidth,getBottom(),paint);
getPaint().setShader(mTextShader);
super.onDraw(canvas);
}
It looks like this:
enter image description here
Just set some shader,and draw a rect,it works fine if I don't use
android:gravity="center"
and
android:singleLine="true"
together,(just one of them is pretty good,)
if only use this property,these shaders and rect are gone!
why?
Before you draw in the canvas, translate the scrolled XY distance
canvas.translate(getScrollX(), getScrollY());
canvas.drawRect(0,0, getWidth(), getHeight(), borderPaint);
your super.onDraw(canvas); should be first line otherwise parent will paint on top of your drawing. also call this setWillNotDraw(false) in your constructor.

Android - redraw canvas

I have 3 ImageViews. 1st and 2nd connected with red line. Also I have simple button. Here is a picture:
I want to connect 2nd & 3rd ImageViews with new Path line and change the first line color (for example to Green) when i clicking my button. Here is parts of my code:
public class SkillPath extends View {
Paint paint;
Path path;
... constructors
#Override
protected void onDraw(Canvas canvas) {
addPath (canvas);
}
//Here is my RED line
void addPath (Canvas canvas){
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
path.moveTo(110, 110);
path.lineTo(210, 110);
canvas.drawPath(path, paint);
Log.d ("Page 2","onDraw");
}
I can get all coordinates of all Views, but how can I redraw existing canvas? I suspect, I need to use invalidate(), but I do not know enough to do this. Need help.
The invalidate() method forces the View to be re-drawn.
So just apply the modification you need on your canvas and call invalidate() on the related View after these modifications.

Insert Drawable shape to View

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.

How to draw line over an ImageView without having to reload it

I'm trying to draw a line over an ImageView but whenever I try it using Canvas, I have to reload the Bitmap, which is not my intention.
Is there a way to simply draw a line on an uploaded ImageView using Canvas without having to refresh the Image? Or another way to draw lines over Android ImageView?
Or, if you want to be able to draw any lines (rects, ovals, etc), subclass ImageView into your own ImageView and do the drawing yourself.
public class MyImageView extends ImageView {
Paint linePaint = new Paint();
#Override
protected void onDraw(Canvas canvas) {
super.onDraw();
// And draw your line.
// (Be sure to have set the values/fields in linePaint earlier so that you draw the correct line/type/size/etc).
canvas.drawLine(0, getHeight()/2, getWidth(), getHeight()/2, linePaint);
}
}
And in your layout xml, don't specify <ImageView .../>, but specify <com.mycompany.project.widget.MyImageView ... /> instead.
The way that I draw lines in Android is by creating a View with height or width of 1dp. Then set the other value to whatever you want and set the color.

Categories

Resources