Android - Google Maps inside CircleView
Asked Answered
A

1

2

I wanted to show map inside a circle view where circle's outside area filled with a color. I referred a post Draw transparent circle filled outside. But now the problem is touch events. Map can be touched through outside circle view while I need map can be touched (zoom or move) only form inside Circle view (where the map is visible).

What I tried,

  1. setEnabled=false
  2. clickable=false

but still map is touched from outside circle view.

Is that possible to achieve that map can be touched from inside circle view.

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);
    }

    @Override
    public boolean isEnabled() {
        return false;
    }

    @Override
    public boolean isClickable() {
        return false;
    }

    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(Color.CYAN); // This is the color of your activity background
        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 - 50;
        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
    }
}


XML layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
    <!--loading map in container-->
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <mypackage.RadiusOverlayView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        />
</RelativeLayout>

Result: enter image description here

Any help will be appreciated.

Audi answered 26/2, 2016 at 8:40 Comment(0)
B
2

You could set a View.OnTouchListener to your RadiusOverlayView and calculate whether the RadiusOverlayView needs to manage the touch events or not. In this example I calculate this by testing if the RadiusOverlayView color touched is != 0 (maybe you want to improve this):

final RadiusOverlayView radiusOverlayView = (RadiusOverlayView) findViewById(R.id.radiusView);
radiusOverlayView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(final View view, final MotionEvent motionEvent) {
        view.setDrawingCacheEnabled(true);
        Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
        view.setDrawingCacheEnabled(false);

        return bmp.getPixel((int) motionEvent.getX(), (int) motionEvent.getY()) != 0;
    }
});
Bataan answered 26/2, 2016 at 10:9 Comment(5)
Just clarify, If I return false always its not suppose to move Right?Audi
No, if you always return true the map will not move. Returning true means that the RadiusOverlayView's listener has consumed the event avoiding it from being propagated to the map.Bataan
Ya this logic works. The only hard thing is find x y (round shape) of inside/outside of the circle and return boolean value. Can you give any glimpse of that so that I can make sure touch happened outside the circle area.Audi
The color check of my example is not enough?Bataan
Sorry my mistake, I didn't understand the return value but now I do.. It works good.Audi

© 2022 - 2024 — McMap. All rights reserved.