클러스터링 마커와 일반 마커의 클릭 이벤트를 함께 사용하는 방법을 알아보자! | 삽질 노트

hoya·2021년 8월 13일
0

삽질 노트

목록 보기
3/8
post-thumbnail

🙄 개요

구글 맵을 바탕으로 여러가지 기능을 구현하고 있다. 그 중 하나가 서울 자전거(따릉이) 위치 정보를 받아와 맵에 마커로 구현하는 기능이었다.

따릉이의 위치 정보는 대략 1700개정도 되는데, 이 많은 양을 맵에 표현하자니 자리도 과하게 차지하고, 성능도 저하되어 대안으로 알아본 것이 클러스터링 마커였다.

클러스터링 마커는 맵의 줌을 늘리면 자동으로 정리를 해주는데, 외적으로 보이는 모습이나 내적으로 성능 저하를 막는 모습이나 효과를 톡톡히 볼 수 있었다.

거기까진 좋았고, 이제 새로 맵을 클릭하면 클릭한 위치에 마커가 생기며 해당 마커를 클릭하면 해당 위치 정보를 기반으로 유저의 고유한 즐겨찾기 장소를 만들어 데이터베이스에 저장할 계획이었다.

그러나, 일반 마커와 클러스터링 마커 클릭 이벤트가 겹치며 클러스터링 마커 클릭 이벤트만 실행되고, 일반 마커는 실행되지 않는 사태가 발생했다.


기존 클러스터링 마커를 사용할 때의 코드는 다음과 같다.


       private GoogleMap mMap = googleMap;
       private ClusterManager<BikeItem> mClusterManager;
       
       // (중략)

        mClusterManager = new ClusterManager<BikeItem>(getActivity(), mMap);
        mClusterManager.setRenderer(new BikeRenderer(getActivity(), mMap, mClusterManager));

        mClusterManager.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<BikeItem>() {
            @Override
            public boolean onClusterItemClick(BikeItem bikeItem) {
                Log.d("Cluster Click", "START");

                bottomStationName = getView().findViewById(R.id.map_detail_stationName);

                bottomStationName.setText(bikeItem.getStationName());
                bikeBottomSheet.setVisibility(View.VISIBLE);
                if (clickMarker != null) {
                    clickMarker.remove();
                }
                return false;
            }
        });

        mMap.setOnCameraIdleListener(mClusterManager);
        mMap.setOnMarkerClickListener(mClusterManager); // 마커 클릭 이벤트 설정

mMap.setOnMarkerClickListener(mClusterManager);

위의 부분에서 맵의 마커 클릭리스너를 단순히 클러스터 매니저로 정의해버리니, 일반 마커가 클릭되지 않는 것은 당연한 결과였다. 이를 방지하기 위해서는 마커 매니저를 이용해야 한다.


🤗 해결

해결을 위해서는 당연히, 마커마다 클릭 리스너를 다르게 설정해야 한다.

 mMap.setOnMarkerClickListener(mClusterManager.getMarkerManager());

우선, 클러스터 매니저에 마커 매니저를 설정한다. 말 그대로 마커들을 관리하는 구심점 역할을 수행하는데, 이 곳에 새 컬렉션을 만들어 클러스터 마커와 구분되어 다른 이벤트를 실행해야 하는 일반 마커들을 등록할 것이다.

MarkerManager.Collection normalMarkerCollection 
= mClusterManager.getMarkerManager().newCollection();

일반 마커들을 관리하는 컬렉션 변수를 설정해 마커 매니저에 넣어준다. 그리고, 이제 우리가 사용할 마커를 넣을 차례이다. 마커를 넣는 방법은 평소와 거의 동일하다.

 MarkerOptions click = new MarkerOptions();
 click.position(point);
 click.title("즐겨찾는 장소로 저장이 가능해요!");
 click.draggable(true);
 click.icon(BitmapDescriptorFactory.fromBitmap(getBitmapFromVectorDrawable(getContext(), R.drawable.ic_map_click_marker)));
 // clickMarker = mMap.addMarker(click);
 clickMarker = normalMarkerCollection.addMarker(click);
 CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(point); // 현재 좌표 지정
 mMap.moveCamera(cameraUpdate); // 현재 좌표로 이동

차이는 마커를 맵에 추가하는 것이 아니라 마커 컬렉션에 추가하는 것이다. 이제 맵에 마커는 표시되었으니, 해당 마커의 클릭 이벤트를 넣어주면 된다. 이 역시 평소와 거의 동일하다.

normalMarkerCollection.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(@NonNull Marker marker) {
	Toast.makeText(getActivity(),"클릭 마커 클릭", Toast.LENGTH_SHORT).show();
	if (marker.getTitle().equals("즐겨찾는 장소로 저장이 가능해요!")) {
        	Toast.makeText(getActivity(),"클릭 마커 클릭", Toast.LENGTH_SHORT).show();
        }
    	return false;
    }
 });

일반 마커들을 모아놓은 컬렉션의 마커 클릭 리스너를 입력하면, 원하는 마커의 클릭 이벤트를 실행하는 것이 가능해진다. 이것으로 해결 끝!


참고 및 출처

스택 오버 플로우

profile
즐겁게 하자 🤭

0개의 댓글