Подтвердить что ты не робот

Как центрировать камеру так, чтобы маркер находился в нижней части экрана? (Google map api V2 Android)

При щелчке по маркеру поведение камеры по умолчанию заключается в том, чтобы центрировать его на экране, но поскольку у меня обычно есть длинное текстовое описание в информационном окне, более удобно фактически изменить положение камеры, чтобы маркер был включен в нижней части экрана (создание информационного окна в центре экрана). Я думаю, что я должен это сделать, переопределив функцию onMarkerClick, как показано ниже (поведение по умолчанию отменяется, когда эта функция возвращает 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 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;
}

Edit:

Проблема решена с использованием принятых шагов ответа, коды ниже:

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



    }

Спасибо за помощь ^ ^

4b9b3361

Ответ 1

Я могу позже отредактировать этот ответ, чтобы предоставить некоторый код, но я думаю, что это может сработать:

  • Получить LatLng (LatLng M) маркера с кликом.
  • Преобразование LatLng M в Point (точка M) с помощью метода Projection.toScreenLocation(LatLng). Это дает расположение маркера на дисплее устройства (в пикселях).
  • Вычислить местоположение точки (Новая точка), которая находится над точкой M на половину высоты карты.
  • Преобразуйте новую точку обратно в LatLng и центрируйте карту на ней.

Посмотрите здесь для моего ответа о том, как получить высоту карты.

    // 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);

Ответ 2

Да, используйте класс Projection. Более конкретно:

Получить проекцию карты:

 Projection projection = map.getProjection();

Получить местоположение вашего маркера:

 LatLng markerLocation = marker.getPosition();

Передать местоположение методу Projection.toScreenLocation():

 Point screenPosition = projection.toScreenLocation(markerLocation);

Подобно этому вы можете перемещать маркер относительно центра или вокруг экрана.

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

Ответ 3

Я предпочитаю, чтобы Ларри Маккензи ответил, что он не зависит от проекции экрана (т.е. mProjection.toScreenLocation()). Полагаю, разрешение проекции будет ухудшаться, когда уровень масштабирования карты низкий, он иногда меня не мог получить точную позицию. Таким образом, расчет, основанный на спецификации google map, определенно решит проблему.

Ниже приведен пример кода перемещения маркера до 30% размера экрана снизу.

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

Ответ 4

У меня была такая же проблема, я пробовал следующее отлично работающее решение

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

Ответ 5

Если вы не заботитесь о масштабировании карты и хотите, чтобы маркер находился внизу, см. ниже, я думаю, что это более простое решение

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

Ответ 6

Я провел небольшое исследование, и согласно документации карта квадратная, а при нулевом уровне масштабирования ширина и высота - 256dp и +/- 85 градусов N/S. Ширина карты увеличивается с уровнем масштабирования, поэтому ширина и высота = 256 * 2N дп. Где N - уровень масштабирования. Поэтому теоретически вы можете определить новое местоположение, получив высоту карты и разделив ее на 170 градусов, чтобы получить dp на градус. Затем получите высоту экрана (или высоту карты) в dp, разделив ее на две части и преобразуйте размер полувидного изображения в градусы широты. Затем установите новую точку камеры, которая находится на многих широтах на юг. Я могу добавить код, если он вам нужен, но я нахожусь на телефоне в данный момент.

Ответ 7

Я тестировал все предлагаемые здесь решения и пришел с их совместной реализацией. Учитывая, что проекция карты, наклона, увеличения и информационного окна.

На самом деле он не помещает маркер в нижней части "обзора камеры", но я думаю, что он в большинстве случаев хорошо освещает информационное окно и центр маркеров.

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

И тогда ваш пользовательский адаптер должен будет хранить экземпляр информационного окна с инфляционным окном, чтобы иметь возможность извлекать его высоту.

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

Ответ 8

Любой, кто все еще хочет центрировать камеру в соответствии с координатами местоположения

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

Кредиты

Ответ 9

После некоторого опыта я реализовал решение, которое подходит для меня.

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

Здесь. Сначала мы выбираем физическую точку на экране, где маркер должен быть перемещен. Затем преобразуйте его в LatLng. Следующий шаг - рассчитать расстояние от текущей позиции маркера (в центре) до цели. Наконец, мы перемещаем центр карты прямо от маркера к расчетному расстоянию.