Is there a way to implement rounded corners to a Mapfragment?
Asked Answered
B

7

15

I want to give the map a nice looking rounded corners as the two boxes below it have. I can't do it with the map fragment it self because there is not a background property to a fragment. setting the map inside a layout and setting it background to a rounded shape didn't help me as well and this is the result:

https://static.mcmap.net/file/mcmap/ZG-AbGLDKwfpKnMxcF_AZVLQamyA/LJhP1.jpg

I could merge the map but this would make it smaller and i would like to avoid it.

EDIT: @Ryan this is the new result #2:

https://static.mcmap.net/file/mcmap/ZG-AbGLDKwfpKnMxcF_AZVLQamyA/69D59.jpg

I guess this is not bad, no even close to the corners on the other boxes, but still not bad with a little more work a could get somewhere close i just dont have a normal image editor. but one thing that still bothers me now is the separation between the "Location" Textview and the map it's self. could i painted the patch in other way so that there was now distance? this is how i did it:

https://static.mcmap.net/file/mcmap/ZG-AbGLDKwfpKnMxcF_AZVLQamyA/1Qx66.png

Well I have finally figured this out:

https://static.mcmap.net/file/mcmap/ZG-AbGLDKwfpKnMxcF_AZVLQamyA/bY4N5.jpg

this is what i used for the patch:

enter image description here

Thanks.

Bresee answered 22/1, 2013 at 22:26 Comment(0)
T
8

I haven't tried this, but I'd put a view with rounded corners and a transparent middle on top of the mapView / mapFragment.

That is, put the mapFragment and the rounded corner view in a FrameLayout with both filling the FrameLayout, then make the middle of the rounded corner view transparent.

For further clarification, you could do it in a layout as follows:-

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<fragment
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:id="@+id/mapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.MapFragment" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/rounded_background"
    android:orientation="vertical" >
</LinearLayout>

</FrameLayout>

The rounded_background is a 9-patch with rounded corners and a transparent middle. E.g.

rounded_background.9.png

Hope that helps,

Ryan

Tientiena answered 22/1, 2013 at 22:39 Comment(6)
what do you mean by putting a view? what kind of view? and how do i make the middle of it transparent?Bresee
I just made a really rough 9 patch to give you the idea, didn't intend you to use it as is ;-) If you make a decent asset it will look fine.Tientiena
Plus you need to use it as a nine patch, rename it filename.9.png. See here for more radleymarx.com/blog/simple-guide-to-9-patchTientiena
well i try to do that but i wounder is there another way to deal with this issue, what software do you use to create those 9-patchs?Bresee
I have never understood how to use this tool, are there another alternatives?Bresee
It doesn't do anything special, it just adds a 1 pixel border around your image. Feel free to use your preferred image editing tool.Tientiena
B
40

I know it's an old post, but you can try using Cards like so:

<android.support.v7.widget.CardView
    android:layout_width="300dp"
    android:layout_height="350dp"
    android:layout_gravity="center_horizontal|center_vertical"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginTop="20dp"
    app:cardCornerRadius="12dp"
    app:cardElevation="12dp">

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.v7.widget.CardView>

enter image description here

Beem answered 30/8, 2017 at 22:48 Comment(1)
Indeed today you can use cards to do that. When this question was asked the Cards did not exist yet. Great Answer.Bresee
T
8

I haven't tried this, but I'd put a view with rounded corners and a transparent middle on top of the mapView / mapFragment.

That is, put the mapFragment and the rounded corner view in a FrameLayout with both filling the FrameLayout, then make the middle of the rounded corner view transparent.

For further clarification, you could do it in a layout as follows:-

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<fragment
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:id="@+id/mapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.MapFragment" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/rounded_background"
    android:orientation="vertical" >
</LinearLayout>

</FrameLayout>

The rounded_background is a 9-patch with rounded corners and a transparent middle. E.g.

rounded_background.9.png

Hope that helps,

Ryan

Tientiena answered 22/1, 2013 at 22:39 Comment(6)
what do you mean by putting a view? what kind of view? and how do i make the middle of it transparent?Bresee
I just made a really rough 9 patch to give you the idea, didn't intend you to use it as is ;-) If you make a decent asset it will look fine.Tientiena
Plus you need to use it as a nine patch, rename it filename.9.png. See here for more radleymarx.com/blog/simple-guide-to-9-patchTientiena
well i try to do that but i wounder is there another way to deal with this issue, what software do you use to create those 9-patchs?Bresee
I have never understood how to use this tool, are there another alternatives?Bresee
It doesn't do anything special, it just adds a 1 pixel border around your image. Feel free to use your preferred image editing tool.Tientiena
B
5

The easiest way is to wrap the map fragment inside a FrameLayout along with an ImageView. The Imageview would display a rounded rectangle on top of the map fragment. In its simplest form you will see the map fragment inside the rounded rectangle with its corners sticking out of the rounded rectangle because the map view itself is not rounded. To overcome this visual oddity simply apply a layout_margin value on map fragment. The value should be equal to the rectangle's border width.

   <FrameLayout
    android:id="@+id/map_container"
    android:layout_width="wrap_content"
    android:layout_height="340dp" >

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="3dp"
        android:name="com.google.android.gms.maps.SupportMapFragment"/>

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/map_bg_box" />

</FrameLayout>

The rectangle drawable is defined as an xml shape as below

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <stroke android:width="3dp"
    android:color="#ff000000" />

    <corners android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp"
    android:topLeftRadius="7dp" android:topRightRadius="7dp"/>

</shape>

Notice the stroke width of the rectangle is 3dp that is exactly the same value we applied to the layout_margin property of the map fragment. The result is a nicely round cornered map fragment as shown in the screenshot below enter image description here

Broker answered 14/9, 2015 at 15:12 Comment(4)
This did not work for me. I tried everything but it did not.Misvalue
what result did you get after following the solution described here?Broker
The map corners overlap the black rounded shape :S the map goes beyond the shape.Misvalue
@Misvalue you are sure followed the right order of placing the shapes ?Disentail
A
2

Wrap the map fragment in this layout:

package com.example.yourpackage;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

/**
 * Just extend any Layout you like/need
 */
public class RoundedLayout extends RelativeLayout {

private Path mPathCorners = new Path();
private Path mPathCircle = new Path();
private float mCornerRadius;

/**
 * border path
 */
private Path mPathCornersBorder = new Path();
private Path mPathCircleBorder = new Path();
private int mBorderWidth = 0;
private int mBorderHalf;
private boolean mShowBorder = false;
private int mBorderColor = 0xFFFF7700;

private float mDensity = 1.0f;

/**
 * Rounded corners or circle shape
 */
private boolean mIsCircleShape = false;

private Paint mPaint = new Paint();

private float dpFromPx(final float px) {
    return px / mDensity;
}

private float pxFromDp(final float dp) {
    return dp * mDensity;
}

public RoundedLayout(Context context) {
    this(context, null);
}

public RoundedLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public RoundedLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mDensity = getResources().getDisplayMetrics().density;
    // just a default for corner radius
    mCornerRadius = pxFromDp(25f);

    mPaint.setAntiAlias(true);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setColor(mBorderColor);
    setBorderWidth(Math.round(pxFromDp(2f)));
}

/**
 * Switch to circle or rectangle shape
 *
 * @param useCircle
 */
public void setShapeCircle(boolean useCircle) {
    mIsCircleShape = useCircle;
    invalidate();
}

/**
 * change corner radius
 *
 * @param radius
 */
public void setCornerRadius(int radius) {
    mCornerRadius = radius;
    invalidate();
}

public void showBorder(boolean show) {
    mShowBorder = show;
    invalidate();
}

public void setBorderWidth(int width) {
    mBorderWidth = width;
    mBorderHalf = Math.round(mBorderWidth / 2);
    if (mBorderHalf == 0) {
        mBorderHalf = 1;
    }

    mPaint.setStrokeWidth(mBorderWidth);
    updateCircleBorder();
    updateRectangleBorder();
    invalidate();
}

public void setBorderColor(int color) {
    mBorderColor = color;
    mPaint.setColor(color);
    invalidate();
}

// helper reusable vars, just IGNORE
private float halfWidth, halfHeight, centerX, centerY;
private RectF rect = new RectF(0, 0, 0, 0);
private RectF rectBorder = new RectF(0, 0, 0, 0);

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    // just calculate both shapes, is not heavy

    // rounded corners path
    rect.left = 0;
    rect.top = 0;
    rect.right = w;
    rect.bottom = h;
    mPathCorners.reset();
    mPathCorners.addRoundRect(rect, mCornerRadius, mCornerRadius, Path.Direction.CW);
    mPathCorners.close();

    // circle path
    halfWidth = w / 2f;
    halfHeight = h / 2f;
    centerX = halfWidth;
    centerY = halfHeight;
    mPathCircle.reset();
    mPathCircle.addCircle(centerX, centerY, Math.min(halfWidth, halfHeight), Path.Direction.CW);
    mPathCircle.close();

    updateRectangleBorder();
    updateCircleBorder();
}

// helper reusable var, just IGNORE
private int save;

@Override
protected void dispatchDraw(Canvas canvas) {
    save = canvas.save();
    canvas.clipPath(mIsCircleShape ? mPathCircle : mPathCorners);
    super.dispatchDraw(canvas);
    canvas.restoreToCount(save);

    if (mShowBorder) {
        canvas.drawPath(mIsCircleShape ? mPathCircleBorder : mPathCornersBorder, mPaint);
    }
}

private void updateCircleBorder() {
    // border path for circle
    mPathCircleBorder.reset();
    mPathCircleBorder.addCircle(centerX, centerY, Math.min(halfWidth - mBorderHalf,
            halfHeight - mBorderHalf), Path.Direction.CW);
    mPathCircleBorder.close();
}

private void updateRectangleBorder() {
    // border path for rectangle
    rectBorder.left = rect.left + mBorderHalf;
    rectBorder.top = rect.top + mBorderHalf;
    rectBorder.right = rect.right - mBorderHalf;
    rectBorder.bottom = rect.bottom - mBorderHalf;
    mPathCornersBorder.reset();
    mPathCornersBorder.addRoundRect(rectBorder, mCornerRadius - mBorderHalf, mCornerRadius -
            mBorderHalf, Path.Direction.CW);
    mPathCornersBorder.close();
}
}

In layout will be like this:

<com.example.yourpackage.RoundedLayout
    android:id="@+id/maplayout"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:layout_margin="20dp">

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        tools:context="com.example.yourpackage.MapsMarkerActivity"/>
</com.example.yourpackage.RoundedLayout>

In code can be like this for a round shape with border:

    RoundedLayout rl = (RoundedLayout) findViewById(R.id.maplayout);
    rl.setShapeCircle(true);
    rl.showBorder(true);
    rl.setBorderWidth(2);

This layout can be used to shape any view.

It's incredible how google is incapable of making competent (usable) complete demos for it's android API.

Avesta answered 13/3, 2017 at 1:56 Comment(0)
G
0

For other people looking into this, I just tackled this using GoogleMap.snapshot and manipulating the bitmap result with this stack over flow answer: How to make an ImageView with rounded corners?

Mind you this is only valid if you are going to have a static map that is not going to be interacted with.

Make sure you take the snap shot after the map is loaded.

I updated the image view helper code to draw with path to support rounding only some corners. ie. If you want to round only 2 of the corners.

You just need the path round rect function that takes a float[]

I show a progress bar until I get a callback from GoogleMap loaded listener than I take the snapshot.

If you take your snapshot too early you will get can't create bitmap with 0 width and height error.

Hope this helps someone looking for rounded corners or other weird shape in static map snapshot.

Gamboa answered 14/11, 2013 at 9:1 Comment(0)
A
0

If you are only trying to target API 21 (Lollipop) and higher


This is the easiest way possible.

parentView.setClipToOutline(true);

Result

enter image description here

Asphyxiate answered 7/3, 2016 at 19:26 Comment(3)
What is 'parentView'? I tried setting setClipToOutline(true); to the actual MapFragment, but that does not work for me...Provinciality
parentView is the view that the mapFragment is in. It's the view that has the mapFragment inside of it.Asphyxiate
Doesn't work for me... I wrapped the map fragment with a LinearLayout with a round corner background and called setClipToOutline(true); as you suggested. Perhaps it has something to do with the theme I am using which is 'Theme.Translucent.NoTitleBar.Fullscreen'...?Provinciality
T
0

Following @Nouman_Hanif post I ended up with a solution that looks quite good.

map_rounded_corner_overlay.xml:

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <stroke android:width="1dp"
          android:color="@color/white" />
  <corners android:radius="<your_desired_view_corner_radius>"/>
</shape>

My map xml file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
  <fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_margin="1dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
  <ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/map_rounded_corner_overlay" />
</RelativeLayout>
Tilney answered 26/7, 2017 at 8:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.