android 현재 안드로이드 확대 축소 위치와 관계없이지도 중심 유지




안드로이드 스튜디오 구글 맵 마커 (4)

LatLngBounds를 사용하여 원하는 위치에서지도를 이동할 수 있습니다. (북동쪽과 남서쪽 경계선을 같은 지점으로 설정할 수 있습니다).

아래 링크를 확인하십시오.

https://developers.google.com/maps/documentation/android-api/views

Uber가 핀치 확대 / 축소 이벤트를 처리하는 방식과 비슷한 것을하려고합니다. 화면의 어느 위치에 있더라도지도를 중앙에 유지하고 중앙 위치를 확대합니다. 지도 조각에 오버레이를 사용하지 않고이 작업을 수행 할 수있는 방법이 있습니까? 아니면지도의 이벤트를 비활성화하고지도 조각에 오버레이를 만들고 오버레이에서 모든 확대 / 축소 이벤트를 처리해야합니까?


MechEthan이 생각하고있는 코드는 다음과 같습니다.

  1. 먼저 오버레이보기에서 더블 탭을 감지해야합니다.

    public class TouchableWrapper extends FrameLayout {
        private final GestureDetector.SimpleOnGestureListener mGestureListener
                = new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTap(MotionEvent e) {
    
                //Notify the event bus (I am using Otto eventbus of course) that you have just received a double-tap event on the map, inside the event bus event listener
                EventBus_Singleton.getInstance().post(new EventBus_Poster("double_tapped_map"));
    
                return true;
            }
        };
    
        public TouchableWrapper(Context context) {
            super(context);
            mGestureDetector = new GestureDetectorCompat(context, mGestureListener);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            mGestureDetector.onTouchEvent(ev);
    
            return super.onInterceptTouchEvent(ev);
        }
    }
  2. 당신이 mapView를 움켜 잡는 곳이라면, 위에서 만든 TouchableWrapper 안에서 그 mapView를 감싸 주면됩니다. 이것은 mapFragment를 다른 조각에 추가해야하므로이 작업을 수행하기 위해 사용자 정의 SupportMapFragment가 필요하기 때문에이 작업을 수행하는 방법입니다

    public class CustomMap_Fragment extends SupportMapFragment {
    
        TouchableWrapper mTouchView;
    
        public CustomMap_Fragment() {
            super();
        }
    
        public static CustomMap_Fragment newInstance() {
            return new CustomMap_Fragment();
        }
    
        @Override
        public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) {
            View mapView = super.onCreateView(arg0, arg1, arg2);
    
            Fragment fragment = getParentFragment();
            if (fragment != null && fragment instanceof OnMapReadyListener) {
                ((OnMapReadyListener) fragment).onMapReady();
            }
    
            mTouchView = new TouchableWrapper(getActivity());
            mTouchView.addView(mapView);
    
            return mTouchView;
        }
    
        public static interface OnMapReadyListener {
            void onMapReady();
        }
    }
  3. 내 Map_Fragment (결국 내비게이션 서랍을 지원하는 액티비티의 FrameLayout과 뷰 전환을위한 프래그먼트 트랜잭션에 위치 함)

    mMapFragment = CustomMap_Fragment.newInstance();
    getChildFragmentManager().beginTransaction().replace(R.id.map_container, mMapFragment).commit();
  4. 마침내 내 맵을 얻은이 동일한 조각 내에서 EventBus 수신기는 "double_tapped_map"을 수신하면 다음 작업을 수행합니다.

    @Subscribe public void eventBus_ListenerMethod(AnswerAvailableEvent event) {
        //Construct a CameraUpdate object that will zoom into the exact middle of the map, with a zoom of currentCameraZoom + 1 unit
       zoomInUpdate = CameraUpdateFactory.zoomIn();
       //Run that with a speed of 400 ms.
       map.animateCamera(zoomInUpdate, 400, null);
    }

참고 : 이 작업을 완벽하게 수행하려면지도에서 zoomGestures를 사용하지 않도록 설정해야합니다 (즉, myMap.getUiSettings().setZoomGesturesEnabled(false); 그렇게하지 않으면 맵에서 빠르게 두 번 탭할 수 있습니다. 두 번 탭의 구현이 내가 게시 한 첫 번째 답변에서와 똑같기 때문에 센터에서 멀리 확대 될 것입니다. 즉, 이전 탭 시간에서 현재 시간을 뺍니다. 따라서 해당 창에서 미끄러질 수 있습니다 세 번째 탭을 클릭하면 이벤트 버스 이벤트가 발생하지 않고 Google지도가 대신 잡아서 줌 제스처를 사용 중지합니다.

그러나 핀치 인 / 아웃이 더 이상 작동하지 않을 것이며 핀치도 처리해야한다는 것을 알게 될 것입니다.이 작업도 한 번 더 했으므로 필요합니다. 내가 할 때 대답을 업데이트 할 것이다.

TIP : Uber는지도에서 회전 동작을 사용 중지했습니다. map.getUiSettings().setRotateGesturesEnabled(false);


나는 대략 3 일을 google에 찾기 지출 한 후에 완전한 해결책을 발견했다. 내 대답은 https://.com/a/32734436/3693334 에서 수정되었습니다.

public class CustomMapView extends MapView {

    private int fingers = 0;
    private GoogleMap googleMap;
    private long lastZoomTime = 0;
    private float lastSpan = -1;
    private Handler handler = new Handler();

    private ScaleGestureDetector scaleGestureDetector;
    private GestureDetector gestureDetector;

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

    public CustomMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomMapView(Context context, AttributeSet attrs, int style) {
        super(context, attrs, style);
    }

    public CustomMapView(Context context, GoogleMapOptions options) {
        super(context, options);
    }

    public void init(GoogleMap map) {
        scaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                if (lastSpan == -1) {
                    lastSpan = detector.getCurrentSpan();
                } else if (detector.getEventTime() - lastZoomTime >= 50) {
                    lastZoomTime = detector.getEventTime();
                    googleMap.animateCamera(CameraUpdateFactory.zoomBy(getZoomValue(detector.getCurrentSpan(), lastSpan)), 50, null);
                    lastSpan = detector.getCurrentSpan();
                }
                return false;
            }

            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                lastSpan = -1;
                return true;
            }

            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                lastSpan = -1;

            }
        });
        gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {

                disableScrolling();
                googleMap.animateCamera(CameraUpdateFactory.zoomIn(), 400, null);

                return true;
            }
        });
        googleMap = map;
    }

    private float getZoomValue(float currentSpan, float lastSpan) {
        double value = (Math.log(currentSpan / lastSpan) / Math.log(1.55d));
        return (float) value;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        gestureDetector.onTouchEvent(ev);
        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_POINTER_DOWN:
                fingers = fingers + 1;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                fingers = fingers - 1;
                break;
            case MotionEvent.ACTION_UP:
                fingers = 0;
                break;
            case MotionEvent.ACTION_DOWN:
                fingers = 1;
                break;
        }
        if (fingers > 1) {
            disableScrolling();
        } else if (fingers < 1) {
            enableScrolling();
        }
        if (fingers > 1) {
            return scaleGestureDetector.onTouchEvent(ev);
        } else {
            return super.dispatchTouchEvent(ev);
        }
    }

    private void enableScrolling() {
        if (googleMap != null && !googleMap.getUiSettings().isScrollGesturesEnabled()) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    googleMap.getUiSettings().setAllGesturesEnabled(true);
                }
            }, 50);
        }
    }

    private void disableScrolling() {
        handler.removeCallbacksAndMessages(null);
        if (googleMap != null && googleMap.getUiSettings().isScrollGesturesEnabled()) {
            googleMap.getUiSettings().setAllGesturesEnabled(false);
        }
    }
}

MapFragment 사용자 정의 및 사용자 정의

public class CustomMapFragment extends Fragment {

        CustomMapView view;
        Bundle bundle;
        GoogleMap map;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            bundle = savedInstanceState;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_map, container, false);

            view = (CustomMapView) v.findViewById(R.id.mapView);
            view.onCreate(bundle);
            view.onResume();

            map = view.getMap();
            view.init(map);

            MapsInitializer.initialize(getActivity());

            return v;
        }

        public GoogleMap getMap() {
            return map;
        }

        @Override
        public void onResume() {
            super.onResume();
            view.onResume();
        }

        @Override
        public void onPause() {
            super.onPause();
            view.onPause();
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            view.onDestroy();
        }

        @Override
        public void onLowMemory() {
            super.onLowMemory();
            view.onLowMemory();
        }
    }

마지막으로, 귀하의 활동에서 :

....
<fragment
    android:id="@+id/map"
    class="yourpackage.CustomMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
...

Android 4.1 (API 16) 및 후자에서 이미 테스트를 마쳤습니다. 정상적으로 작동합니다. (API <16, 테스트 할 장치가 없습니다).


이는 GoogleMap 객체의 setLatLngBoundsForCameraTarget() 메소드를 사용하면 쉽게 달성 할 수 있습니다. Android 용 Google지도 SDK의 '카메라 및보기'페이지에서

private GoogleMap mMap;
// Create a LatLngBounds that includes the city of Adelaide in Australia.
private LatLngBounds ADELAIDE = new LatLngBounds(
  new LatLng(-35.0, 138.58), new LatLng(-34.9, 138.61));
// Constrain the camera target to the Adelaide bounds.
mMap.setLatLngBoundsForCameraTarget(ADELAIDE);`

신뢰하십시오. LatLngBounds 를 마커의 정확한 좌표에 배치하면 카메라가 마커에 집중되도록 할 수 있습니다. 쉬운!





zoom