web-dev-qa-db-fra.com

Comment centrer la caméra pour que le marqueur soit en bas de l'écran? (Google map api V2 Android)

Lorsqu'un marqueur est cliqué, le comportement par défaut de la caméra est de le centrer à l'écran, mais comme j'ai généralement une longue description textuelle dans la fenêtre d'informations, il est plus pratique de changer la position de la caméra pour que le marqueur soit au bas de l'écran (faisant la fenêtre d'information au centre de l'écran). Je pense que je devrais être capable de le faire en remplaçant la fonction onMarkerClick comme ci-dessous (le comportement par défaut est annulé lorsque cette fonction retourne true)

@Override

public boolean onMarkerClick(final Marker marker) {


    // Google sample code comment : We return false to indicate that we have not

    // consumed the event and that we wish
    // for the default behavior to occur (which is for the camera to move
    // such that the
    // marker is centered and for the marker's info window to open, if it
    // has one).

    marker.showInfoWindow();

            CameraUpdate center=
                CameraUpdateFactory.newLatLng(new LatLng(XXXX,
                                                         XXXX));
            mMap.moveCamera(center);//my question is how to get this center

            // return false;
    return true;
}

Éditer:

Problème résolu en utilisant les étapes de réponse acceptées, les codes ci-dessous:

@Override

    public boolean onMarkerClick(final Marker marker) {

                //get the map container height
        LinearLayout mapContainer = (LinearLayout) findViewById(R.id.map_container);
        container_height = mapContainer.getHeight();

        Projection projection = mMap.getProjection();

        LatLng markerLatLng = new LatLng(marker.getPosition().latitude,
                marker.getPosition().longitude);
        Point markerScreenPosition = projection.toScreenLocation(markerLatLng);
        Point pointHalfScreenAbove = new Point(markerScreenPosition.x,
                markerScreenPosition.y - (container_height / 2));

        LatLng aboveMarkerLatLng = projection
                .fromScreenLocation(pointHalfScreenAbove);

        marker.showInfoWindow();
        CameraUpdate center = CameraUpdateFactory.newLatLng(aboveMarkerLatLng);
        mMap.moveCamera(center);
        return true;



    }

Merci d'avoir aidé ^ ^

42
Arch1tect

Je pourrais modifier cette réponse plus tard pour fournir du code, mais ce que je pense pourrait fonctionner est le suivant:

  1. Obtenez LatLng ( LatLng M ) du marqueur cliqué.
  2. Convertir LatLng M en Point ( Point M ) en utilisant la méthode Projection.toScreenLocation(LatLng) . Cela vous donne l'emplacement du marqueur sur l'écran de l'appareil (en pixels).
  3. Calculer l'emplacement d'un point ( Nouveau point ) au-dessus Point M de la moitié de la hauteur de la carte.
  4. Convertissez le nouveau point en LatLng et centrez la carte dessus.

Regardez ici pour ma réponse sur la façon d'obtenir la hauteur de la carte.

    // googleMap is a GoogleMap object
    // view is a View object containing the inflated map
    // marker is a Marker object
    Projection projection = googleMap.getProjection();
    LatLng markerPosition = marker.getPosition();
    Point markerPoint = projection.toScreenLocation(markerPosition);
    Point targetPoint = new Point(markerPoint.x, markerPoint.y - view.getHeight() / 2);
    LatLng targetPosition = projection.fromScreenLocation(targetPoint);
    googleMap.animateCamera(CameraUpdateFactory.newLatLng(targetPosition), 1000, null);
48
zbr

Oui, utilisez la classe Projection. Plus précisement:

Obtenez la projection de la carte:

 Projection projection = map.getProjection();

Obtenez l'emplacement de votre marqueur:

 LatLng markerLocation = marker.getPosition();

Passez l'emplacement à la méthode Projection.toScreenLocation ():

 Point screenPosition = projection.toScreenLocation(markerLocation);

Comme ça, vous pouvez déplacer votre marqueur par rapport au centre ou autour de l'écran

Point mappoint = googleMap.getProjection().toScreenLocation(new LatLng(latitude, longitude));
        mappoint.set(mappoint.x, mappoint.y-30);
        googleMap.animateCamera(CameraUpdateFactory.newLatLng(googleMap.getProjection().fromScreenLocation(mappoint)));
20
Sampath Kumar

Je préfère la réponse de Larry McKenzie qui ne dépend pas de la projection d'écran (c.-à-d. MProjection.toScreenLocation ()), je suppose que la résolution de projection deviendra médiocre lorsque le niveau de zoom de la carte est bas, cela m'a parfois empêché d'obtenir une précision position. Ainsi, un calcul basé sur les spécifications de google map résoudra définitivement le problème.

Voici un exemple de code pour déplacer le marqueur à 30% de la taille de l'écran à partir du bas.

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);
6
chunyap

J'ai eu le même problème, j'ai essayé la solution suivante parfaitement fonctionnelle

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;
            }
        });
3
Samadhan Medge

Si vous ne vous souciez pas du zoom de la carte et que vous voulez juste que le marqueur soit en bas, voir ci-dessous, je pense que c'est une solution plus simple

double center = mMap.getCameraPosition().target.latitude;
double southMap = mMap.getProjection().getVisibleRegion().latLngBounds.southwest.latitude;

double diff = (center - southMap);

double newLat = marker.getPosition().latitude + diff;

CameraUpdate centerCam = CameraUpdateFactory.newLatLng(new LatLng(newLat, marker.getPosition().longitude));

mMap.animateCamera(centerCam);
3
Cam Connor

J'ai fait un peu de recherche et selon la documentation, la carte est carrée et à un niveau de zoom nul, la largeur et la hauteur sont de 256dp et +/- 85 degrés N/S. La largeur de la carte augmente avec le niveau de zoom de sorte que la largeur et la hauteur = 256 * 2N dp. Où N est le niveau de zoom. Donc, en théorie, vous pouvez déterminer le nouvel emplacement en obtenant la hauteur de la carte et en la divisant par 170 degrés totaux pour obtenir un dp par degré. Ensuite, obtenez la hauteur de l'écran (ou la hauteur de la carte) en dp divisé par deux et convertissez la moitié de la taille de la vue en degrés de latitude. Réglez ensuite votre nouveau point de caméra sur plusieurs degrés de latitude sud. Je peux ajouter du code si vous en avez besoin mais je suis en ce moment sur un téléphone.

1
Larry McKenzie

J'ai essayé toutes les solutions proposées ici et je suis venu avec une mise en œuvre combinée de celles-ci. Considérant, projection de la carte, inclinaison, zoom et hauteur de la fenêtre d'information.

Il ne place pas vraiment le marqueur au bas de la "vue caméra", mais je pense qu'il accueille assez bien la fenêtre d'informations et le centre du marqueur dans la plupart des cas.

@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;
}

Et puis, votre adaptateur personnalisé devrait conserver une instance de la vue gonflée de la fenêtre d'informations, pour pouvoir récupérer sa hauteur.

public int getInfoWindowHeight(){
    if (mLastInfoWindoView != null){
        return mLastInfoWindoView.getMeasuredHeight();
    }
    return 0;
}
0
mdelolmo

Après quelques expériences, j'ai mis en place la solution qui me convient.

DisplayMetrics metrics = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(metrics);

Point targetPoint = new Point(metrics.widthPixels / 2, metrics.heightPixels - metrics.heightPixels / 9);
LatLng targetLatlng = map.getProjection().fromScreenLocation(targetPoint);
double fromCenterToTarget = SphericalUtil.computeDistanceBetween(map.getCameraPosition().target, targetLatlng);

LatLng center = SphericalUtil.computeOffset(new LatLng(location.latitude, location.longitude), fromCenterToTarget/1.2, location.bearing);
CameraUpdate camera = CameraUpdateFactory.newLatLng(center);
map.animateCamera(camera, 1000, null);

Ici. Tout d'abord, nous choisissons le point physique sur l'écran où le marqueur doit être déplacé. Ensuite, convertissez-le en LatLng. Étape suivante - calculez la distance entre la position actuelle du marqueur (au centre) et la cible. Enfin, nous déplaçons le centre de la carte directement du marqueur à la distance calculée.

0
Edward

Quiconque cherche toujours à centrer la caméra en fonction des coordonnées de l'emplacement

CameraPosition cameraPosition = new CameraPosition.Builder().target(new LatLng(Lat, Lon))
        .zoom(15) 
        .bearing(0)
        .tilt(45)
        .build();
    map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

Crédits

0
user3354265