本文同時適用于高德地圖和百度地圖。
本人總結下來有三種實現方案,但每種方案都有利弊:
- 方案一:使用CardView包裹MapView,通過設置CardView的圓角屬性來實現地圖圓角效果。弊端:存在兼容性問題。
- 方案二:原理同第一種方案,自定義圓角Layout包裹MapView。同樣也存在兼容性問題。
- 方案三:添加一個圓角遮罩(中間透明)蓋到MapView上面,從而實現圓角效果。好處是不存在兼容性問題,弊端是適用性較狹窄。適用于地圖邊框顏色同外部容器顏色一致的情況,否則存在色差就比較難看。
下面詳述三種方案:
方案一:使用CardView包裹MapView
<android.support.v7.widget.CardView
android:layout_weight="0.6"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="50dp"
android:layout_width="match_parent"
android:layout_height="0dp"
app:cardCornerRadius="6dp">
<com.amap.api.maps.MapView
android:id="@+id/road_help_map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v7.widget.CardView>
由于CardView本身兼容性問題,導致5.0(API 21)以下圓角存在邊距。下圖顯示效果不明顯,但是實際開發肉眼是可以看到的。
5.0以下(真機API19)
5.0以上顯示效果良好,地圖邊緣沒有白邊。
5.0以上(真機API27)
方案二:自定義圓角Layout包裹MapView
自定義圓角布局RoundRelativeLayout
public class RoundRelativeLayout extends RelativeLayout {
private Path path;
private float radius = 20f;
public RoundRelativeLayout(@NonNull Context context) {
this(context, null);
}
public RoundRelativeLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundRelativeLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (attrs != null) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundRelativeLayout);
radius = ta.getDimension(R.styleable.RoundRelativeLayout_radius, 20);
ta.recycle();
}
path = new Path();
}
@Override
protected void dispatchDraw(Canvas canvas) {
path.reset();
path.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()), radius, radius, Path.Direction.CW);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
canvas.clipPath(path, Region.Op.REPLACE);
super.dispatchDraw(canvas);
}
}
屬性文件attrs.xml:
<declare-styleable name="RoundRelativeLayout">
<attr name="radius" format="dimension" />
</declare-styleable>
看下實現效果:
模擬器API 17
真機API 19
在API17上沒有圓角效果,而API19上則有。原因跟我們使用clipPath來實現圓角有關,這個方法在API 18才支持硬件加速(參見我的另一篇文章硬件加速),經過實驗發現如果我們設置關閉硬件加速,那么是可以看到圓角的,但是地圖MapView會出現黑屏現象。大家可以手動試下。本人測試的關閉硬件加速的方法:
public RoundRelativeLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setLayerType(LAYER_TYPE_SOFTWARE, null);
....
}
嘗試過網上的其他圓角控件GcsSloop/rclayout,VibeXie/Android實現圓角ViewGroup,和MapView結合使用都會存在黑屏或顯示不出來的現象。
綜上,采用本方法,API18以下的設備將無法實現圓角,API18(含)以上設備有圓角。
方案三:給MapView添加圓角遮罩
定義一個圓角遮罩mapview_corner.xml,這里的colorPrimary顏色同地圖容器背景色相近,如果能一樣是最好。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape >
<solid android:color="@android:color/transparent"/>
<stroke android:color="@color/colorPrimary" android:width="2dp"/>
</shape>
</item>
<item>
<shape >
<solid android:color="@android:color/transparent"/>
<stroke android:color="@color/colorPrimary" android:width="2dp"/>
<corners android:radius="6dp"/>
</shape>
</item>
</layer-list>
布局代碼:
<RelativeLayout
android:layout_weight="0.6"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="50dp"
android:layout_width="match_parent"
android:layout_height="0dp">
<com.amap.api.maps.MapView
android:id="@+id/road_help_map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<View android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/mapview_corner"/>
</RelativeLayout>
在MapView的上方添加一個和MapView大小一樣的View,設置背景為mapview_corner.xml作為圓角遮罩。
顯示效果:
圓角遮罩
因為我的背景為漸變色,和純色的邊框顏色差異較大,所以會很明顯的看出來。
這種方案,如果你的背景為純色,則效果會很良好。
我這里的背景遮罩采用layer-list實現,實際上你也可以考慮用9-patch來做,效果會不會更好