When I have a custom Android View (e.g. it extends FrameLayout) and I can draw on Canvas and I can add views with addView. How one relates to the other, e.g. when I draw sth on Canvas and I add some children which is at the top and which is at the bottom?
Related
First time here.
I create application with StreetView. Want draw markers on top Street View panoramas.
Switch between layouts with setContentView(). On layout with element "StreetViewPanoramaView extends FrameLayout" (com.google.android.gms.maps) i have element "StreetOverlayView extends SurfaceView".
With "Canvas canvas = surfaceHolder.lockCanvas();" i draw bitmap on SurfaceView.
look:
SurfaceView draw bitmap
StreetView
after setContentView all time look like:
StreetView
SurfaceView draw bitmap
I tried different options:
1) first setContentView(layout with StreetViewPanoramaView) and bitmap draw on top and look good.
After i setContentView(another layout) and again setContentView(layout with StreetViewPanoramaView) - bitmap NOT draw : ( on top - only under StreetViewPanoramaView.
2) first setContentView(another layout) and after setContentView(layout with StreetViewPanoramaView) - bitmap NOT draw : ( on top.
I tried "bringChildToFront" with elements in layout - not work.
How can i return SurfaceView with canvas draw on top ?
I have solution:
Put "StreetOverlayView extends SurfaceView" element in new FrameLayout and after setContentView i remove my element from this FrameLayout and add again.
frame1.removeView( markerView );
frame1.addView ( markerView );
I am drawing a rectangle in the canvas on the first attempt and again I am attempting to draw one more rectangle at a different position. When I finally add them to LinearLayout I see the only 2nd rectangle, the first rectangle is lost.
Bitmap place = Bitmap.createBitmap(400,800,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(place);
DrawRect dr = new DrawRect();
dr.setLocation(10,10);
dr.draw(canvas);
dr.setLocation(10,80);
dr.draw(canvas);
ll.removeAllViews();
ll.addView(dr);
How do I make both the rectangles to be visible?
removeAllViews() will remove all view of LinearLayout.
You are adding view after removeAllViews() thats why you see 2nd rectangle only.
So remove thisll.removeAllViews(); line and run again.
I found the problem in the code, i should not use the same DrawRect object for drawing one more item, instead use the same but different DrawRect object does the magic.
I'm trying to override onDraw in an EditText subclass, to show a custom subtitle.
I've got it working, but there are a few bugs.
Basicall, all I need to do is draw StaticLayout at a certain offset from top left corner of the view.
Unfortunantly, all I get in my onDraw method is canvas. The size of the canvas is equal to the size of the whole screen (320x480 on a device with 320x480 display) and its clip bounds can be pretty much anything - it can be the whole view; it can be only top or bottom part of the view if the view is inside scrollview and partially visible; it can even be same arbitrary rect inside the view, probably because superclass invalidates only some of its region.
So if I have this view with size 320x48, I can get canvas with size 320x480 and clipping rect (200, 200, 300, 230) (left, top, right, bottom). I don't understand how this clipping rect maps to my view coordinates.
I need to know where is top left corner of the clipping rect relative to the top left corner of the view. Unfortunantly, I cannot figure out how to get this.
Added:
This code will work on all os versions that I've tested:
private int[] coordinates = new int[2];
private Matrix identityMatrix = new Matrix();
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
getLocationInWindow(coordinates);
canvas.setMatrix(identityMatrix);
canvas.translate(coordinates[0], coordinates[1]);
//do the drawing in EditText coordinate space
canvas.restore();
}
However, I still have one question: why does it work?
I've trying overriding View class and it's onDraw method will always recieve a canvas which size matches that of the View itself. Canvas for direct View subclass will have no clipping rect. Same for TextView (direct ancestor of the EditText class). But it's not the same for EditText. Canvas that gets passed to onDraw method of EditText will always (or not?) have the size of the screen, and a custom clipping rect. This whole "translate by view coordinates in window thing" seems very hacky. I don't understand why I should translate the coordinate space.
I've tried hacking android source code for the answers, but found none. EditText has no onDraw of its own. Theoretically, there should be no difference between overriding TextView onDraw and EditText onDraw. But there is a difference. The canvas object passed to onDraw method will be different depending on whether its TextView or EditText. Why? How do I know when I should apply transformation to matrix, and when I shouldn't?
you can have it with the View.getLocationOnScreen method
I am experimenting with building a custom game engine based on standard Canvas drawing that resembles the Android View class in that drawable objects have an onDraw method. The idea is that the game elements are given a Canvas on which to draw themselves and that is then incorporated into the main view. I assume that there is something similar going on behind the scenes with the standard Android Views.
How can I create a "master view" that can hand small Canvases to child objects and then incorporate those canvases into it's own drawing?
NOTE: the child objects are not subclasses of View, but the "master" view can be a View
After reading the Android Source Code for View and ViewGroup I discovered how this is done. When the system draws views to the screen, it generates a Canvas which is a rastor for the entire screen. That Canvas is not "cut up" and given to subviews to draw on, but rather it is translated and clipped to accomodate each view.
Before a particular view is drawn, its parent translates the Canvas to the child's position, clips the Canvas to the child's size, and then calls .draw(Canvas) on that view. The view does not know that the canvas has been altered, each view draws as if it were at (0,0). After the child has finished drawing, the Canvas is translated back to its previous position. Abstractly, every view thinks it is the only view, when in reality each parent is repositioning and resizing the canvas to be in the right place.
So for my situation, all I needed to do was iterate each of my child objects like this:
for(MyObject mob : mobjects) {
final int restoreTo = canvas.save();
canvas.translate(mob.getX(), mob.getY());
canvas.clipRect(0, 0, mob.getWidth(), mob.getHeight());
mob.onDraw(canvas);
canvas.restoreToCount(restoreTo);
}
Ok, here's the deal. I want to move items in my extended gallery class to change the order of images. The way i'm doing it now:
on long press remove the current selected item,
use onDraw() to draw the same image so i can move it around using onTouchEvent()
on release add the item again
This works fine but the problem is that when using the onDraw() method it will draw the image behind the gallery items. Is there a way to change the priority of what is drawn?
Well i found this out after going into a totally different direction =/
Here's the solution for people that have the same problem:
In constructor (or anywhere else you initialize the component) set setWillNotDraw(false) and override dispatchDraw(). dispatchDraw() draws the ViewGroup children so you can decide yourself if you want to draw behind or a top of the other views.
Example taken from Custom drawing on top of Gallery view (and it's child views)
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
// do your drawing stuff here
canvas.drawPath(mPath,mPaint);
}