I was having some issues having a view on top of my surface view. I followed the instructions on this answer: https://stackoverflow.com/a/2934759/1315692
That worked great EXCEPT for a view that is custom drawn.
The custom drawn view ALWAYS remains on top. What do I need to do to be able to put a view on top of it? Thanks for any suggestions or insights.
I figured out a solution. It may not be the best solution but it is working for me.
I drew my view that I wanted on top in the draw routine of the object that was stubbornly staying on top USING THE SAME CANVAS. I added a field of type View to my SurfaceView (because that is where the view that remained on top is drawn) with a setter. Then in my draw routine I simply called passedInView.draw(canvas);
If you are at a point where you are not drawing on top of the surface view at all then start with the link from my question. That should be all you need. This is for a situation where a custom drawn view still remains.
Now this can cause some undesired behavior in regards to tapping (you can tap right through your on top view)...so you will need code to handle that but if all else fails, as it had for me, this got my view on top.
Related
I have a card-like view with elevation and a white background that I want to expand to fill up the whole screen. It's a card in a list (my own custom layout, not a CardView), and I want to make it take up the whole screen when it's tapped via a Fragment transition.
My first idea is to create a fake, identical view in the new fragment, place it at the item's position, and animate it to the top, while animating its layout bounds to take up the whole screen. However, I don't think this is the best idea, as Android will have to remeasure the layout every single frame while the animation is running (likely to lag). Is there a way I can get this effect in a clean way? I'm going to be using fragment transitions, so hopefully I can use Animator in some way, but I'll take any solution.
You can try to do the same, but instead of relayouting, do redrawing. Create custom implementation of view's onDraw(), it's not that hard.
View will fill entire screen but at the start of animation will draw only initial part.
Or you can just try your approach, it's easy to implement and may be it is not that slow.
Also, may be directly modifying view's setLeft(), setRight(), etc. with Animators is a valid solution.
When covering a view with an overlay I am aware that I need to use a FrameLayout, and the child views stack on top of each other. Setting a view to having a background with opacity will create the overlay effect. However, in my situation, I am required to create a hole in my overlay to display the contents of a tab item / other views beneath it. This is where I am stuck.
I am not sure how to perform the intersection on the view so that it is transparent in a specific area of the view (which I need to determine based upon the position of a specific View element (Tab, ImageView, etc).
The image above shows the result I want to achieve. With the entire view having an overlay on it, besides one of the Tabs and the Info box (which needs to move based on the view displayed through the overlay).
I believe I need an intersection of the views to achieve the result I need...this is something I am not sure about. Can someone point me in the right direction of a solution please, I do not expect to be just given a solution, its all about learning!
I have a complex frame layout containing several custom views. The main view is a graph.
Overlaying the graph is a custom view which represents a cross hair pointer that the user can drag around the graph to read off detailed information about a particular data point.
The frame layout captures all touch events, calls "hit test" methods on each of it's child views to determine if the touch was on that view then dispatches the touch event to the appropriate view.
When the user touches the cross hair and drags it, I pass the touch event to the cross hair which it uses to update it's position and invalidate itself.
Everything is working except...
All views in the layout are redrawing when I invalidate any of these child views. I know this as I have turned on "show screen updates" in developer options. At no point do I invalidate the containing FrameLayout - or at least, not knowingly.
Certainly, the Activity handling the layout does not invalidate it and I do not have any references to the parent in the child views.
I haven't posted code since a) I don't know if this might be normal behaviour, b) there's a lot of it! and c) if it's not normal behaviour, I don't know which part of the code is problematic. Of course, I'm happy to give anything that might be requested.
My minimum API is 2.3.3 and my target is 4.0. This happens on both of those versions so I suspect my code is the problem but where to start?
Any clues as to what might be going on?
There is no way for View to draw "just itself", since it depends on it's parent (which provides it's clipped and translated Canvas via dispatchDraw method). Invalidation requires whole view tree to be invalidated - this is the answer that you're looking for :)
If you'll check out the source of ViewGroup, you'll find there two important methods: dispatchDraw (which responsible for dispatching draw event down to it's childs) and drawChild (which called by dispatchDraw and let's you specify how childs will be drawn). Note, that there is no check on which View starts invalidation, although there is a RectF that specifies invalidation region. As far as I understand - you need to make sure that your invalidating View (cross) doesn't takes the whole screen, so redrawn will be only that part that it actually takes.
If understand you right, the lines of the cross-hair view cover the whole screen, i.e. one vertical line from top to bottom and one horizontal from left to right.
Now if you change the center of the cross-hair and the other views would not be redrawn, your screen would soon be cluttered with old lines from previous cross-hair positions. You would not want this, so you can be glad that the other views redraw itself too.
If you want, you can specify a 'dirty' rectangle and call invalidate(Rect dirty), which would not redraw Views that are completely outside that rectangle. Though it's up to you in that case, not to change anything outside that rectangle.
try this:
setDrawingCacheEnabled(true);
Enabling drawing cache for view will make view not be redrawn if view not changed
Take a look : Android Invalidate() only single view
May be my answer so simple, but I resolved this problem with help:
this.invalidate()
Run it for each canvas-view, and it will updating one by one (not all at once)
I'm drawing some graphics and i would like to add scroll to it. But with the surface view how to add the scroll programatically ?
SurfaceView is a very special component, it's not easy to mix it with other components. The main reason is due to how it works: when you use a SurfaceView, a new window will be created (by default behind the activity) and all the rendering in the SurfaceView will go to that window. SurfaceView will also "draw a hole" in the activity, so the window behind it will be visible.
SurfaceView needs to synchronize the window position with it's position, which is not done perfectly. For example if you put a SurfaceView inside something which can scroll, the window won't scroll (at least it didn't the last time I tried, around Froyo time).
Please provide some more information about what you are trying to do. If you just want to create a custom component, it's easier to just subclass View and override onDraw(Canvas).
In my sample app i am drawing images on canvas.
Now on touch of any view I use "view.bringToFront(..)" to bring view on top,and invalid selected view.
But here it drawn each view again at place of an single view.
I just want to draw an dirty view here.
Pls let me know how can I handle this,
Similar problem here : Android: How to get a custom view to redraw partially?
Thnx