I am creating a pixel-hunting game. So my activity shows an ImageView. And I want to create a hint "show me where is the object". For this I need to blur whole image except a circle around a point where the object is located. Instead of blur I can show a just semitransparent black background. There is there is no problem to draw a semitransparent rectangle on the Canvas. But I don't know how to crop a transparent circle from it. The result should look like like this:
Please help me to achieve same result on Android SDK.
I have done this way by creating custom LinearLayout:
Check the Screenshot:
CircleOverlayView.java
CircleDrawActivity.java:
activity_circle_draw.xml:
colors.xml:
dimens.xml:
Hope this will help you.
I found a solution without bitmap drawing and creation. Here is the result of my implementation:
You need to create a custom
FrameLayout
anddrawCircle
withClear
paint:Also do not forget to disable Hardware acceleration and call
setWillNotDraw(false)
because we will overrideonDraw
methodThe full example is here:
PS: This implementation just draws hole inside itself, you need to put background in your layout and add this
TutorialView
on top.If you're having trouble getting a transparent circle cutout over a view with an opaque background, see this answer. To get it to work, I set my custom layout view to have a transparent background in XML, then drew on the background color I wanted for the layout with the line
The full OnDraw method from the answer I linked above:
So finally I managed to do this.
Firstly I draw a semitransparent black rectangle on whole view. After that using
PorterDuff.Mode.CLEAR
I cut a transparent circle to show cat's position.I had problem with
PorterDuff.Mode.CLEAR
: firstly I was getting a black circle instead of a transparent one.Thanks to Romain Guy's comments here: comment here I understood that my window is opaque and I should draw on another bitmap. And only after draw on
View
's canvas.Here is my
onDraw
method:I don't have much to add to your answer, But if anyone's interested I moved the bitmap allocation and all to onSizeChanged so it's better performance wise.
Here you can find a FrameLayout with a "Hole" in the middle of it ;)
p.s: although it's much more efficient than the original answer it's still a relatively heavy task to do in a draw() method, so if you're using this technique in an animation like me, don't expect a 60.0fps smooth one
@Robert's answer actually showed me how to solve this problem but his code doesn't work. So I have updated his solution and made it work:
And now use this view in any layout like this:
Here I wanted a semi transparent layer on the SurfaceView with transparent circle in the center. P.S. This code is not optimized one because it creates Bitmap in onDraw method, it is because I couldn't get parent view's width and height in init method, so I only could know them in onDraw.