How to center the camera so that marker is at the bottom of screen? (Google map api V2 Android)

前端 未结 10 2129
执念已碎
执念已碎 2020-11-30 23:13

When a marker is clicked, the default behavior for the camera is to center it on screen, but because I usually have long text description in the info window, it\'s more conv

相关标签:
10条回答
  • 2020-11-30 23:20

    I did a little research and according to the documentation the map is square and at zero zoom level the width and height is 256dp and +/- 85 degrees N/S. The map width increases with zoom level so that width and height = 256 * 2N dp. Where N is the zoom level. So in theory you can determine the new location by getting the map height and dividing it by 170 total degrees to get dp per degree. Then get the screen height (or mapview height) in dp divided it by two and convert half view size to degrees of latitude. Then set your new Camera point that many degrees of latitude south. I can add code if you need it but I'm on a phone at the moment.

    0 讨论(0)
  • 2020-11-30 23:23

    Yes, use Projection class. More specifically:

    Get Projection of the map:

     Projection projection = map.getProjection();
    

    Get location of your marker:

     LatLng markerLocation = marker.getPosition();
    

    Pass location to the Projection.toScreenLocation() method:

     Point screenPosition = projection.toScreenLocation(markerLocation);
    

    Like this you can move your marker relative to center or around the screen

    Point mappoint = googleMap.getProjection().toScreenLocation(new LatLng(latitude, longitude));
            mappoint.set(mappoint.x, mappoint.y-30);
            googleMap.animateCamera(CameraUpdateFactory.newLatLng(googleMap.getProjection().fromScreenLocation(mappoint)));
    
    0 讨论(0)
  • 2020-11-30 23:27

    I had the same issue, I tried the following perfectly working solution

    mMap.setOnMarkerClickListener(new OnMarkerClickListener() 
            {
                @Override
                public boolean onMarkerClick(Marker marker)
                {
                    int yMatrix = 200, xMatrix =40;
    
                    DisplayMetrics metrics1 = new DisplayMetrics();
                    getWindowManager().getDefaultDisplay().getMetrics(metrics1);
                    switch(metrics1.densityDpi)
                    {
                    case DisplayMetrics.DENSITY_LOW:
                        yMatrix = 80;
                        xMatrix = 20;
                        break;
                    case DisplayMetrics.DENSITY_MEDIUM:
                        yMatrix = 100;
                        xMatrix = 25;
                        break;
                    case DisplayMetrics.DENSITY_HIGH:
                        yMatrix = 150;
                        xMatrix = 30;
                        break;
                    case DisplayMetrics.DENSITY_XHIGH:
                        yMatrix = 200;
                        xMatrix = 40;
                        break;
                    case DisplayMetrics.DENSITY_XXHIGH:
                        yMatrix = 200;
                        xMatrix = 50;
                        break;
                    }
    
                    Projection projection = mMap.getProjection();
                    LatLng latLng = marker.getPosition();
                    Point point = projection.toScreenLocation(latLng);
                    Point point2 = new Point(point.x+xMatrix,point.y-yMatrix);
    
                    LatLng point3 = projection.fromScreenLocation(point2);
                    CameraUpdate zoom1 = CameraUpdateFactory.newLatLng(point3);
                    mMap.animateCamera(zoom1);
                    marker.showInfoWindow();
                    return true;
                }
            });
    
    0 讨论(0)
  • 2020-11-30 23:27

    I also faced this problem and fixed it in a hacky way. Let's declare a double field first. You need to adjust the value of it based on your requirement but I recommend you keep it between 0.001~0.009 otherwise you can miss your marker after the zoom animation.

      double offset = 0.009 
      /*You can change it based on your requirement.
     For left-right alignment please kindly keep it between 0.001~0.005 */
    

    For bottom-centered:

        LatLng camera = new LatLng(marker.getPosition().latitude+offset , marker.getPosition().longitude);
    //Here "marker" is your target market on which you want to focus
    

    For top-centered:

    LatLng camera = new LatLng(marker.getPosition().latitude-offset , marker.getPosition().longitude);
    

    For left-centered:

    LatLng camera = new LatLng(marker.getPosition().latitude, marker.getPosition().longitude+offset);
    

    For right-centered:

    LatLng camera = new LatLng(marker.getPosition().latitude-offset , marker.getPosition().longitude-offset);
    

    Then finally call the -

    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(camera, yourZoom));
    
    0 讨论(0)
  • 2020-11-30 23:29

    I have been trying out all the solutions proposed here, and came with a combined implementation of them. Considering, map projection, tilt, zoom and info window height.

    It doesn't really place the marker at the bottom of the "camera view", but I think it accommodates the info window and the marker centre pretty well in most cases.

    @Override
    public boolean onMarkerClick(Marker marker) {
        mIsMarkerClick = true;
        mHandler.removeCallbacks(mUpdateTimeTask);
        mLoadTask.cancel(true);
        getActivity().setProgressBarIndeterminateVisibility(false);
        marker.showInfoWindow();
        Projection projection = getMap().getProjection();
        Point marketCenter = projection.toScreenLocation(marker.getPosition());
        float tiltFactor = (90 - getMap().getCameraPosition().tilt) / 90;
        marketCenter.y -= mInfoWindowAdapter.getInfoWindowHeight() / 2 * tiltFactor;
        LatLng fixLatLng = projection.fromScreenLocation(marketCenter);
    
        mMap.animateCamera(CameraUpdateFactory.newLatLng(fixLatLng), null);
    
        return true;
    }
    

    And then, your custom adapter would have to keep an instance of the info window inflated view, to be able to fetch its height.

    public int getInfoWindowHeight(){
        if (mLastInfoWindoView != null){
            return mLastInfoWindoView.getMeasuredHeight();
        }
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-30 23:30

    I prefer Larry McKenzie's answer which it doesn't depend on screen projection (i.e. mProjection.toScreenLocation()), my guess is the projection resolution will go poor when the map zoom level is low, it made me sometimes couldn't get an accurate position. So, calculation based on google map spec will definitely solve the problem.

    Below is an example code of moving the marker to 30% of the screen size from bottom.

    zoom_lvl = mMap.getCameraPosition().zoom;
    double dpPerdegree = 256.0*Math.pow(2, zoom_lvl)/170.0;
    double screen_height = (double) mapContainer.getHeight();
    double screen_height_30p = 30.0*screen_height/100.0;
    double degree_30p = screen_height_30p/dpPerdegree;      
    LatLng centerlatlng = new LatLng( latlng.latitude + degree_30p, latlng.longitude );         
    mMap.animateCamera( CameraUpdateFactory.newLatLngZoom( centerlatlng, 15 ), 1000, null);
    
    0 讨论(0)
提交回复
热议问题