밍쯔와 안작고 안귀여운 에러들🖤

[Android/Java] mapView, naverMapFragment in ScrollView 본문

Develop/Android | iOS

[Android/Java] mapView, naverMapFragment in ScrollView

밍쯔 2023. 7. 31. 15:17

회사 어플에서 장소 정보를 제공하는 등의 여러 상황에서 지도가 이용되는데

이때 scrollview안에 map에서 문제가 발생했다.

 

[문제]

1. 지도 스크롤을 컨트롤하기 어려움.

특히, 상하 스크롤뿐만 아니라 좌우 스크롤도 버벅거리고이벤트가 쉽게 뺏기는 것을 경험할 수 있다.

 

2. 

무엇때문인지 원인을 명확하게 설명하지는 못하지만,

홈에서 naver mapfragment로 생성된 뷰를 들어갔다가 슬라이딩 패널 안의 scrollview 안 mapView가

생성한 마커만 보이고 지도가 보이지 않는 문제를 발견했다.

 

2번 문제의 경우, mapView로 생성된 지도를 mapfragment로 변경하면 문제가 해결 됐는데, 이때 1번의 문제가 발생한다.

따라서, 커스텀 mapfragment를 만들기로 했다.

 

[해결]

먼저, naver의 mapFragment를 상속 받는 CustomMapFragment와 터치 이벤트를 관리할 OnTouchListener 를 만든다.

public interface OnTouchListener {
    void onTouch();
    void onUnTouch();
}

 

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.core.content.ContextCompat;
import com.naver.maps.map.MapFragment;

public class CustomMapFragment extends MapFragment {
    private OnTouchListener mListener;

    public static CustomMapFragment newInstance() {
        return new CustomMapFragment();
    }

    @Override
    public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstance) {
        View layout = super.onCreateView(layoutInflater, viewGroup, savedInstance);

        TouchableWrapper frameLayout = new TouchableWrapper(getActivity());

        frameLayout.setBackgroundColor(ContextCompat.getColor(getActivity().getApplicationContext(), R.color.transparent));

        ((ViewGroup) layout).addView(frameLayout,
                new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        return layout;
    }

    public void setListener(OnTouchListener listener) {
        mListener = listener;
    }

    public class TouchableWrapper extends FrameLayout {

        public TouchableWrapper(Context context) {
            super(context);
        }

        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mListener.onTouch();
                    break;
                case MotionEvent.ACTION_MOVE:
                    mListener.onTouch();
                    break;
                case MotionEvent.ACTION_UP:
                    mListener.onUnTouch();
                    break;
                case MotionEvent.ACTION_CANCEL:
                    mListener.onUnTouch();
                    break;
            }
            return super.dispatchTouchEvent(event);
        }
    }
}

이후, mapView로 생성했던 지도를 fragment로 바꾸고, activity에서 mapfragment로 지도를 불러오는 방식으로 onCreate에 추가한다.

<FrameLayout
    android:id="@+id/mapView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="packagename.CustomMapFragment"/>

* name이 기존에는 "com.naver.maps.map.MapFragment"인데 이 위치를 바꾸는 것 유의!

 

private CustomMapFragment mapFragment;

public void initMap() {
    FragmentManager fm = getSupportFragmentManager();
    mapFragment = (CustomMapFragment) fm.findFragmentById(binding.mapView.getId());
    if (mapFragment == null) {
        mapFragment = CustomMapFragment.newInstance();
        fm.beginTransaction().add(binding.mapView.getId(), mapFragment).commit();
    }
    mapFragment.getMapAsync(new OnMapReadyCallback() {
        @Override
        public void onMapReady(@NonNull NaverMap map) {
            naverMap = map;

            UiSettings uiSettings = map.getUiSettings();
            ...

            mapFragment.setListener(new OnTouchListener() {
                        @Override
                        public void onTouch() {
                            binding.scrollView.requestDisallowInterceptTouchEvent(true);
                        }

                        @Override
                        public void onUnTouch() {
                            binding.scrollView.requestDisallowInterceptTouchEvent(true);
                        }
                    });
        }
    });
}

이렇게 지도를 생성할 함수를 적용해주면 완성!

터치 이벤트도 잘 작동하고, 기존의 지도 생성 오류도 모두 해결됐다.

 

 

 

[참고]

https://stackoverflow.com/questions/30525066/how-to-set-google-map-fragment-inside-scroll-view

 

how to set google map fragment inside scroll view

I want to set a Google map fragment inside vertical ScrollView, when I do the map does not zoom vertically, how can I override the touch event listener on MapView over the listener of ScrollView? ...

stackoverflow.com

https://zion830.tistory.com/140

 

[Android/Kotlin] MapFragment in ScrollView 구현하기 (Cant scroll map vertically)

상황 설명 스크롤뷰 안에 지도가 들어갈 경우, 지도를 상하 방향으로 움직일 때 스크롤뷰 쪽의 이벤트 우선순위가 높아서 지도는 안움직이고 화면 스크롤이 됨 예제는 네이버 지도를 사용했지

zion830.tistory.com