Путь с указателями направления на карте с использованием Yandex Map Kit для Android

в 17:09, , рубрики: Android разработка, overlay, Yandex Map Kit, Разработка под android, метки: , ,

Здравствуйте!

В этом сообщении рассмотрим:

  1. Встраивание библиотеки Yandex Map Kit Android в проект
  2. Создание расширения для класса Overlay с целью вывода на карту пути с указателями направления и обработки событий «onClick» по карте

image

1. Встраивание библиотеки в проект (Eclipse, Windows)

Загружаем архив с библиотекой отсюда и получаем API-ключ.
Создаем проект в Eclipse, копируем с заменой папки yandexmapkit-libraryres и yandexmapkit-librarylibs из загруженного архива в папку нашего проекта.
В настройках проекта добавляем ссылку на yandexmapkit-android.jar из папки libs нашего проекта (Build Path->Configure Buil Path->Libraries->Add External JARs)
Добавляем разрешения в манифест нашего проекта

  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.WAKE_LOCK"/>
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
  <uses-permission android:name="android.permission.READ_PHONE_STATE"/> 

Изменяем разметку activity

  <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
      <ru.yandex.yandexmapkit.MapView
        android:id="@+id/map"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:apiKey="ваш ключ" />
  </RelativeLayout>

2. Создание расширения для класса Overlay с целью вывода на карту пути с указателями направления и обработки событий «onClick» по карте

Чтобы нарисовать путь, нам потребуется расширить класс OverlayIRender, который реализует интерфейс IRender

public class MyOverlayIRender extends OverlayIRender {

	Overlay mOverlay;

	public MyOverlayIRender(Overlay overlay) {
		super();
		mOverlay = overlay;
	}

	@Override
	public void draw(Canvas canvas, OverlayItem arg1) {
		super.draw(canvas, arg1);
		List<OverlayItem> oi = mOverlay.getOverlayItems();
		if (oi.size() < 2)
			return;
		Paint mPaint = new Paint();
		mPaint.setDither(true);
		mPaint.setColor(Color.RED);
		mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
		mPaint.setStrokeJoin(Paint.Join.ROUND);
		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStrokeWidth(2);
		mPaint.setAntiAlias(true);
		for (int i = 0; i < oi.size() - 1; i++) {
			Path path = new Path();
			ScreenPoint p1 = mOverlay.getMapController().getScreenPoint(
			oi.get(i).getGeoPoint());
			ScreenPoint p2 = mOverlay.getMapController().getScreenPoint(
			oi.get(i + 1).getGeoPoint());
			float angle = (float) (Math.atan2(p2.getY() - p1.getY(), 
					p2.getX()- p1.getX()) * 180 / 3.14);
			path.moveTo(p2.getX(), p2.getY());
			path.lineTo(p1.getX(), p1.getY());
			canvas.drawPath(path, mPaint);
			canvas.save();
			canvas.rotate(angle + 90, p2.getX(), p2.getY());
			Path path2 = new Path();
			path2.moveTo(p2.getX(), p2.getY());
			path2.lineTo(p2.getX() + 5, p2.getY() + 8.66f);
			path2.lineTo(p2.getX() - 5, p2.getY() + 8.66f);
			path2.close();
			canvas.drawPath(path2, mPaint);
			canvas.restore();
		}
	}
}

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

public class MyPathOverLay extends Overlay {

	MapView mMmapView;

	public MyPathOverLay(MapController arg0, MapView mapView) {
		super(arg0);
		mMmapView = mapView;
		this.setIRender(new MyOverlayIRender(this));
	}

	@Override
	public int compareTo(Object arg0) {
		return 0;
	}

	@Override
	public boolean onLongPress(float x, float y) {
		OverlayItem m = new OverlayItem(
				this.c.getGeoPoint(new ScreenPoint(x, y)),
				BitmapFactory.decodeResource(
						this.c.getContext().getResources(),
						R.drawable.flag2leftred));
		m.setOffsetY(-23);
		this.addOverlayItem(m);
		this.c.setPositionNoAnimationTo(this.c
				.getGeoPoint(new ScreenPoint(x, y)));
		return true;
	}
}

В переопределенном методе onLongPress будем добавлять промежуточные точки для нашего пути долгим нажатием на карту.
R.drawable.flag2leftred — картинка для точки,
m.setOffsetY(-23); — смещение, которое нужно подобрать, если нужно сместить картинку относительно точки нажатия на карту, по-умолчанию центр картинки совмещается с точкой нажатия.
Осталось добавить наш Overlay на карту и протестировать

public class BlogYandexActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		MapView mMap = (MapView) findViewById(R.id.map);
		MapController mMapController = mMap.getMapController();
		OverlayManager mOverlayManager = mMapController.getOverlayManager();
		mOverlayManager.addOverlay(new MyPathOverLay(mMapController, mMap));
		mMap.showBuiltInScreenButtons(true);
		mOverlayManager.getMyLocation().setEnabled(false);
	}
}

Результат

image

Автор: constv

  1. Дмитрий:

    (Здесь не ясно, когда будет отображен комментарий, в при первой попытке у меня был сбой. Поэтому с этим добавлением посылаю снова – так как просто не увидел нормальной реакции сервиса.)

    Тема очень для меня актуальная. Но в Вашем примере пользователь сам себе строит маршрут, просто кликая по карте. В моем же приложении требуется маршрут прокладывать автоматически. Буду делать поддержку множества карт, это точно будут Google карты и Open Street Map, при этом буду использовать Android-движки каждой отдельно – о том, что можно использовать один движок, а подсовывать разные карты, я как-то не догадался, не подумал, но теперь не вижу в этом необходимости – и для гугл-карт, и для Open Street Map у меня есть уже рабочие примеры прокладки маршрута (пока без наворотов вроде маркеров и прочего, но с этим не вижу дальнейших сложностей. Код же для поддержки Яндекс-Карт движком от Open Street Map мне показался излишне сложным, зачем?

    Итак, к сути вопроса. Яндекс-карты тоже хочу добавить. Есть ли возможность прокладки маршрута при использовании Yandex Map Kit, рассчитанного не мной лично, а самим Яндексом?

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js