Android MapView стрелки направления

1

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

Теги:
android-mapview
android-maps

2 ответа

1
Лучший ответ

Вот мое решение:

import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
import com.jettaxi.R;

import java.util.ArrayList;

public class ArrowDirectionsOverlay extends Overlay {
    private Context context;

    private ArrayList<GeoPoint> directions;
    private Bitmap arrowBitmap;
    private int maximalPositionX;
    private int maximalPositionY;

    public ArrowDirectionsOverlay(Context context) {
        this.context = context;

        directions = new ArrayList<GeoPoint>();

        arrowBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.direction);
    }

    public void addDirectionPoint(GeoPoint destination) {
        directions.add(destination);
    }

    public void clear() {
        directions.clear();
    }

    private double getAngle(GeoPoint center, GeoPoint destination) {
        double lat1 = center.getLatitudeE6() / 1000000.;
        double lon1 = center.getLongitudeE6() / 1000000.;
        double lat2 = destination.getLatitudeE6() / 1000000.;
        double lon2 = destination.getLongitudeE6() / 1000000.;

        int MAXITERS = 20;
        // Convert lat/long to radians
        lat1 *= Math.PI / 180.0;
        lat2 *= Math.PI / 180.0;
        lon1 *= Math.PI / 180.0;
        lon2 *= Math.PI / 180.0;

        double a = 6378137.0; // WGS84 major axis
        double b = 6356752.3142; // WGS84 semi-major axis
        double f = (a - b) / a;
        double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);

        double L = lon2 - lon1;
        double A = 0.0;
        double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
        double U2 = Math.atan((1.0 - f) * Math.tan(lat2));

        double cosU1 = Math.cos(U1);
        double cosU2 = Math.cos(U2);
        double sinU1 = Math.sin(U1);
        double sinU2 = Math.sin(U2);
        double cosU1cosU2 = cosU1 * cosU2;
        double sinU1sinU2 = sinU1 * sinU2;

        double sigma = 0.0;
        double deltaSigma = 0.0;
        double cosSqAlpha = 0.0;
        double cos2SM = 0.0;
        double cosSigma = 0.0;
        double sinSigma = 0.0;
        double cosLambda = 0.0;
        double sinLambda = 0.0;

        double lambda = L; // initial guess
        for (int iter = 0; iter < MAXITERS; iter++) {
            double lambdaOrig = lambda;
            cosLambda = Math.cos(lambda);
            sinLambda = Math.sin(lambda);
            double t1 = cosU2 * sinLambda;
            double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
            double sinSqSigma = t1 * t1 + t2 * t2; // (14)
            sinSigma = Math.sqrt(sinSqSigma);
            cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
            sigma = Math.atan2(sinSigma, cosSigma); // (16)
            double sinAlpha = (sinSigma == 0) ? 0.0 :
                    cosU1cosU2 * sinLambda / sinSigma; // (17)
            cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
            cos2SM = (cosSqAlpha == 0) ? 0.0 :
                    cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)

            double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
            A = 1 + (uSquared / 16384.0) * // (3)
                    (4096.0 + uSquared *
                            (-768 + uSquared * (320.0 - 175.0 * uSquared)));
            double B = (uSquared / 1024.0) * // (4)
                    (256.0 + uSquared *
                            (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
            double C = (f / 16.0) *
                    cosSqAlpha *
                    (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
            double cos2SMSq = cos2SM * cos2SM;
            deltaSigma = B * sinSigma * // (6)
                    (cos2SM + (B / 4.0) *
                            (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
                                    (B / 6.0) * cos2SM *
                                            (-3.0 + 4.0 * sinSigma * sinSigma) *
                                            (-3.0 + 4.0 * cos2SMSq)));

            lambda = L +
                    (1.0 - C) * f * sinAlpha *
                            (sigma + C * sinSigma *
                                    (cos2SM + C * cosSigma *
                                            (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)

            double delta = (lambda - lambdaOrig) / lambda;
            if (Math.abs(delta) < 1.0e-12) {
                break;
            }
        }

        float distance = (float) (b * A * (sigma - deltaSigma));
        float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
                cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
        initialBearing *= 180.0 / Math.PI;
        float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
                -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
        finalBearing *= 180.0 / Math.PI;

        return finalBearing;
    }

    private void drawArrow(Canvas canvas, MapView mapView, GeoPoint destination) {
        Point screenPts = mapView.getProjection().toPixels(destination, null);

        int deltaX = mapView.getMapCenter().getLatitudeE6() - destination.getLatitudeE6();
        int deltaY = mapView.getMapCenter().getLongitudeE6() - destination.getLongitudeE6();

        double angle = getAngle(mapView.getMapCenter(), destination);
        double tan = Math.tan(Math.toRadians(angle));

        Matrix matrix = new Matrix();
        matrix.postRotate((float) angle);
        Bitmap rotatedBmp = Bitmap.createBitmap(
                arrowBitmap,
                0, 0,
                arrowBitmap.getWidth(),
                arrowBitmap.getHeight(),
                matrix,
                true
        );

        int currentPositionX = screenPts.x - (rotatedBmp.getWidth() / 2);
        int currentPositionY = screenPts.y - (rotatedBmp.getHeight() / 2);

        if ((currentPositionX < 0) || (currentPositionY < 0) ||
                (currentPositionX > maximalPositionX) || (currentPositionY > maximalPositionY)) {

            int arrowPositionX = (int) (mapView.getWidth() / 2 - Math.signum(deltaX) * mapView.getHeight() / 2 * tan);
            arrowPositionX = Math.min(Math.max(arrowPositionX, 0), maximalPositionX);
            int arrowSpanX = (int) (mapView.getWidth() / 2.);

            int arrowPositionY = (int) (mapView.getHeight() / 2 + Math.signum(deltaY) * arrowSpanX / tan);
            arrowPositionY = Math.min(Math.max(arrowPositionY, 0), maximalPositionY);

            canvas.drawBitmap(
                    rotatedBmp,
                    arrowPositionX,
                    arrowPositionY,
                    null
            );
        }
    }

    public void draw(Canvas canvas, MapView mapView, boolean shadow) {
        super.draw(canvas, mapView, shadow);

        maximalPositionX = mapView.getWidth() - arrowBitmap.getWidth();
        maximalPositionY = mapView.getHeight() - arrowBitmap.getHeight();

        for (GeoPoint geoPoint : directions) {
            drawArrow(canvas, mapView, geoPoint);
        }
    }
}

Растровая стрелка указывает на вершину в моем случае

0

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

  • 0
    Меня интересуют стрелки на краях экрана. Можете ли вы привести пример наложения?
  • 0
    Я сделал несколько вещей с Картами, но не с этим, поэтому у меня нет примера. Похоже, стрелки расположены от средней точки, идущей влево или вправо.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню