-
[ Android ] View 의 이미지 화 (구글 맵 마커 커스터 마이징 예제)Android & Kotlin 2022. 6. 20. 00:52
📌 배경
구글맵의 마커 부분을 기존 서비스에서 제공하는 ui 형태가 아닌
새로운 ui 로 커스터마이징 해서 사용하고 싶어 찾던중
View 를 Bitmap 으로 변환하는 방법을 알게 되었습니다.
📌 주요 코드 분석
1. View 의 Instance 화
- 커스터마이징할 뷰를 생성하고 인플레이트하여 인스턴스화 시켜줍니다.
- 그 외 필요한 값에 대해 초기화 해줍니다.
2. View 의 위치 및 크기 설정
- measure 함수를 호출함으로써 onMeasure 가 내부적으로 호출되고 비로서 우리는 View 의 크기에 대한 접근을 할 수 있게 됩니다. 그전에는 0 값을 반환함.
- measure 의 인자인 measureSpec 에 UNSPECIFIED 에 해당하는 0 을 넣었습니다.
https://developer.android.com/reference/android/view/View.MeasureSpec
View.MeasureSpec | Android Developers
android.net.wifi.hotspot2.omadm
developer.android.com
3. View 의 Bitmap 화
- View 의 키기에 맞는 비트맵(View 를 그릴 빈 도화지 ) 을 생성합니다.
- createBitmap()
- 비트맵을(빈 도화지를 ) 캔버스 위에 올립니다.
- Canvas(bitmap)
- 원하는 뷰를 캔버스를 통해 비트맵에 그립니다.
- markerContainer(=View).draw(canvas)
진행중 View 를 통해 draw 함수를 호출하고 인자로 canvas 넣었는데 그 안에 있는 비트맵이 변경된는
다소 부자연스러운 플로우로 인해 이해가 좀 어려웠던 것 같습니다.
📌 결과
class MapActivity : AppCompatActivity(), OnMapReadyCallback { private lateinit var binding: ActivityMapBinding private lateinit var mMap: GoogleMap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_map) setContentView(binding.root) setMapFragment() listenBackButtonClick() } private fun listenBackButtonClick() { binding.btnBackToMenu.setOnClickListener { finish() } } private fun setMapFragment() { val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) } override fun onMapReady(googleMap: GoogleMap) { mMap = googleMap val location = LatLng(37.491, 127.0335) // 방법2. View를 이미지화하여 구현한 방법(완전한 Custom이 가능함) addMyMarker(Marker(37.491, 127.0335, "₩201,599")) addMyMarker(Marker(37.501, 127.0362, "₩101,699")) addMyMarker(Marker(37.4612, 127.0513, "₩11,599")) mMap.moveCamera(CameraUpdateFactory.newLatLng(location)) mMap.animateCamera(CameraUpdateFactory.zoomTo(12.0f)); } private fun addMyMarker(marker: Marker) { val markerOptions = MarkerOptions().apply { position(LatLng(marker.lat, marker.lon)) title(marker.price) icon( BitmapDescriptorFactory.fromBitmap( createDrawableFromView( marker.price ) ) ) } mMap.addMarker(markerOptions) } private fun createDrawableFromView(price: String): Bitmap { val markerContainer = LayoutInflater.from(this).inflate(R.layout.custom_marker, null); val markerTextView = markerContainer.findViewById<TextView>(R.id.tv_marker) markerTextView.text = price val displayMetrics = DisplayMetrics() markerContainer.measure(displayMetrics.widthPixels, displayMetrics.heightPixels) markerContainer.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels) val bitmap = Bitmap.createBitmap( markerContainer.measuredWidth, markerContainer.measuredHeight, Bitmap.Config.ARGB_8888 ) val canvas = android.graphics.Canvas(bitmap) markerContainer.draw(canvas) return bitmap } }
'Android & Kotlin' 카테고리의 다른 글
[ Android ] Context 와 메모리 릭 (0) 2022.07.27 [ Android ] CallAdapter, SealedClass 를 활용한 레트로핏 응답 처리 (0) 2022.07.12 [ Android ] 안드로이드 저장소 정리 (Legacy, Scoped Storage) (0) 2022.06.12 [Android] Background Task1 : WorkManager 개념 및 예제 (0) 2022.06.07 [ Android ] 이미지 라이브러리 분석 : Glide (0) 2022.05.04