Pinch to zoom google map with out moving marker in framelayout

后端 未结 1 961
轻奢々
轻奢々 2020-12-19 20:49

My layout



            

        
相关标签:
1条回答
  • 2020-12-19 21:10

    Any approach that relies on map events will be laggy, so I would recommed to create a helper View that manages all the touches and dispatches some of them to the map (panning gestures in this case).

    Layout:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content">
    
        <fragment
            android:id="@+id/map"
            class="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
        <!-- Helper view to manage touches -->
        <View
            android:id="@+id/helperView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
        <mypackage.AnchoredImageView
            android:id="@+id/pin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:contentDescription="@null"
            android:src="@drawable/ic_center_pin"/>
    </FrameLayout>
    

    On the Activity:

    final View mMapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
    View mHelperView = findViewById(R.id.helperView);
    mHelperView.setOnTouchListener(new View.OnTouchListener() {
        private float scaleFactor = 1f;
    
        @Override
        public boolean onTouch(final View view, final MotionEvent motionEvent) {
            if (simpleGestureDetector.onTouchEvent(motionEvent)) { // Double tap
                mMap.animateCamera(CameraUpdateFactory.zoomIn()); // Fixed zoom in
            } else if (motionEvent.getPointerCount() == 1) { // Single tap
                mMapView.dispatchTouchEvent(motionEvent); // Propagate the event to the map (Pan)
            } else if (scaleGestureDetector.onTouchEvent(motionEvent)) { // Pinch zoom
                mMap.moveCamera(CameraUpdateFactory.zoomBy( // Zoom the map without panning it
                        (mMap.getCameraPosition().zoom * scaleFactor
                                - mMap.getCameraPosition().zoom) / 5));
            }
    
            return true; // Consume all the gestures
        }
    
        // Gesture detector to manage double tap gestures
        private GestureDetector simpleGestureDetector = new GestureDetector(
                MapsActivity.this, new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onDoubleTap(MotionEvent e) {
                        return true;
                    }
                });
    
        // Gesture detector to manage scale gestures
        private ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(
                MapsActivity.this, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
                    @Override
                    public boolean onScale(ScaleGestureDetector detector) {
                        scaleFactor = detector.getScaleFactor();
                        return true;
                    }
                });
    });
    

    As the anchor of a ImageView is the center of the image, if we use a image like a pin, the marker will apparently move because the bottom center of the image must be in the center of the map. To avoid this, we can move the image creating an anchored image view.

    AnchoredImageView

    public class AnchoredImageView extends ImageView {
        public AnchoredImageView(Context context) {
            super(context);
        }
    
        public AnchoredImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public AnchoredImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            setTranslationY(-h/2);
        }
    }
    
    0 讨论(0)
提交回复
热议问题