如何在Android API 28中将SupportMapFragment设置为圆形?
解决API 28下SupportMapFragment设置圆形的问题
问题原因
直接给FragmentContainerView或SupportMapFragment的View设置clipToOutline无效,主要有两个原因:
- XML中的
android:clipToOutline属性需要API 32及以上才支持,API 28无法通过XML生效; SupportMapFragment底层依赖SurfaceView,低版本系统中SurfaceView对clipToOutline的支持存在兼容性问题,直接设置无法完成裁剪。
方案一:用CardView作为父容器(推荐)
CardView的圆角裁剪是自身实现的,不依赖系统API,兼容性更好,实现起来也最简单:
修改布局文件:
<androidx.cardview.widget.CardView android:id="@+id/mapContainer" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="16dp" app:cardCornerRadius="100dp" <!-- 圆角半径设为宽高的一半,实现圆形 --> app:cardElevation="0dp" <!-- 不需要阴影可以设为0 --> app:layout_constraintEnd_toEndOf="@id/pulsatingCircle" app:layout_constraintStart_toStartOf="@id/pulsatingCircle" app:layout_constraintTop_toTopOf="@id/pulsatingCircle"> <androidx.fragment.app.FragmentContainerView android:id="@+id/customerMapView" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@string/customer_map_view" /> </androidx.cardview.widget.CardView>
无需额外Kotlin代码,CardView会自动将内部的地图裁剪为圆形。
方案二:自定义父布局的OutlineProvider
如果不想用CardView,可以给父布局设置自定义的圆形轮廓,再开启裁剪:
- 修改布局文件,给
FragmentContainerView套一层父布局:
<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/mapContainer" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="16dp" app:layout_constraintEnd_toEndOf="@id/pulsatingCircle" app:layout_constraintStart_toStartOf="@id/pulsatingCircle" app:layout_constraintTop_toTopOf="@id/pulsatingCircle"> <androidx.fragment.app.FragmentContainerView android:id="@+id/customerMapView" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@string/customer_map_view" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
- 在Kotlin代码中设置父布局的轮廓和裁剪:
private fun initMap() { val mapContainer = findViewById<ConstraintLayout>(R.id.mapContainer) // 设置圆形轮廓 mapContainer.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { val radius = view.width.coerceAtMost(view.height) / 2f outline.setRoundRect(0, 0, view.width, view.height, radius) } } mapContainer.clipToOutline = true // 初始化地图逻辑 val mapView = supportFragmentManager.findFragmentById(R.id.customerMapView) as SupportMapFragment mapView.getMapAsync { googleMap -> // 处理地图初始化,比如设置地图样式、添加标记等 } }
注意事项
- 确保父布局的宽高是正方形,否则裁剪出来会是椭圆形;
- 方案二中要确保父布局已经完成测量(比如在
onViewCreated或onResume中调用相关代码,避免宽高为0导致轮廓设置无效)。
内容的提问来源于stack exchange,提问作者Zachary Smouse
相关产品推荐
相关产品推荐

