Draw transparent circle filled outside

后端 未结 3 1316
予麋鹿
予麋鹿 2020-12-01 17:12

I have a mapview that I want to draw a circle on to focus on a given area. But i want the circle to be inverted. That is, instead of the inside of the circle being filled, i

相关标签:
3条回答
  • 2020-12-01 17:51

    My answer is pretty late, but may help someone to achieve this. Here is an example how to make semitransparent view with transparent circle matching size of the smallest dimension, placed in center with small margin. It can be placed as overlay upon any view.

    /*
     * Copyright (c) 2015 Singularex Inc.
     */
    
    package your_package.ui.widget;
    
    import android.annotation.TargetApi;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.RectF;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    
    import your_package.R;
    
    /**
     * @author Victor Kosenko
     */
    public class RadiusOverlayView extends LinearLayout {
        private Bitmap windowFrame;
    
        public RadiusOverlayView(Context context) {
            super(context);
        }
    
        public RadiusOverlayView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
    
            if (windowFrame == null) {
                createWindowFrame(); // Lazy creation of the window frame, this is needed as we don't know the width & height of the screen until draw time
            }
    
            canvas.drawBitmap(windowFrame, 0, 0, null);
        }
    
        protected void createWindowFrame() {
            windowFrame = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); // Create a new image we will draw over the map
            Canvas osCanvas = new Canvas(windowFrame); // Create a   canvas to draw onto the new image
    
            RectF outerRectangle = new RectF(0, 0, getWidth(), getHeight());
    
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Anti alias allows for smooth corners
            paint.setColor(getResources().getColor(R.color.map_radius_outer)); // This is the color of your activity background
            paint.setAlpha(84);
            osCanvas.drawRect(outerRectangle, paint);
    
            paint.setColor(Color.TRANSPARENT); // An obvious color to help debugging
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // A out B http://en.wikipedia.org/wiki/File:Alpha_compositing.svg
            float centerX = getWidth() / 2;
            float centerY = getHeight() / 2;
            float radius = Math.min(getWidth(), getHeight()) / 2 - getResources().getDimensionPixelSize(R.dimen.view_margin_small2);
            osCanvas.drawCircle(centerX, centerY, radius, paint);
        }
    
        @Override
        public boolean isInEditMode() {
            return true;
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
    
            windowFrame = null; // If the layout changes null our frame so it can be recreated with the new width and height
        }
    }
    

    And here how it looks in my case:

    Transparent circle overlay view.

    0 讨论(0)
  • 2020-12-01 18:04

    Do as you would do to draw a normal circle but with complement location and complement radius. Like:

    {0-Lat, (Long-180)%180, 20037508.34-Radius}
    
    0 讨论(0)
  • 2020-12-01 18:15

    You can create a new BufferedImage, fill it grey then erase the circle where you want.

    And then, draw that BufferedImage on top of your view.

    BufferedImage img = new BufferedImage(sizeX, sizeY, BufferedImage.TYPE_INT_RGBA);
    Graphics2D g = img.createGraphics();
    
    int ovalX = 50;
    int ovalY = 70;
    int ovalRadius = 20;
    
    /* Draw the grey rectangle */
    g.setColor(Color.GRAY);
    g.fillRect(0, 0, sizeX, sizeY);
    
    /* Enable Anti-Alias */
    g.setRenderingHint(RenderingHints.HINT_ANTIALIAS, RenderingHints.VALUE_ANTIALIAS_ON);
    
    /* Clear the circle away */
    g.setComposite(AlphaComposite.CLEAR, 1.0f);
    g.fillOval(ovalX - ovalRadius, ovalY - ovalRadius, 2 * ovalRadius, 2 * ovalRadius);
    
    g.dispose();
    
    0 讨论(0)
提交回复
热议问题