Ломаные линии и многоугольники для отображения маршрутов и областей на карте

В этом примере показано, как добавить карту Google в приложение для Android, а также как использовать ломаные линии и многоугольники для отображения маршрутов и областей на карте.

Следуйте руководству по созданию приложения для Android с помощью Maps SDK for Android. Рекомендуемая среда разработки – Android Studio.

Как получить код

Клонируйте или скачайте репозиторий с примерами Google Maps Android API версии 2 с сайта GitHub.

Настройка проекта

Чтобы создать проект в Android Studio, выполните следующие действия:

  1. Скачайте и установите Android Studio.
  2. Добавьте пакет сервисов Google Play в Android Studio.
  3. Клонируйте или скачайте репозиторий с примерами Google Maps Android API версии 2 с сайта GitHub, если вы ещё не сделали этого.
  4. Импортируйте обучающий проект:

    • В Android Studio выберите Файл > Создать > Импортировать проект.
    • Перейдите в каталог, где вы сохранили репозиторий с примерами Google Maps Android API версии 2 после его скачивания.
    • Найдите проект Polygons, используя этот путь:
      PATH-TO-SAVED-REPO/android-samples/tutorials/Polygons
    • Выберите каталог проекта и нажмите ОК. Теперь Android Studio создаст ваш проект с использованием инструмента сборки Gradle.

Как получить ключ API и активировать нужные API

Для выполнения этого учебного проекта вам понадобится ключ Google API, который авторизован для Maps SDK for Android.

Нажмите кнопку ниже, чтобы получить ключ и активировать API.

Начать

Более подробную информацию можно найти в полном руководстве по получению ключа API.

Как добавить ключ API в свое приложение

  1. Отредактируйте файл gradle.properties в своем проекте.
  2. Подставьте ключ API в качестве значения для свойства GOOGLE_MAPS_API_KEY. Во время сборки приложения Gradle копирует ключ API в манифест Android приложения, как объяснено ниже.

    GOOGLE_MAPS_API_KEY=PASTE-YOUR-API-KEY-HERE
    

Как создать сборку и запустить приложение

  1. Подключите устройство Android к компьютеру. Выполните инструкции по активации параметров для разработчиков на устройстве Android и настройте ваше приложение и систему для обнаружения этого устройства. Для настройки виртуального устройства вы также можете использовать Менеджер виртуального устройства Android (AVD). Выбирая эмулятор, убедитесь, что вы используете образ, который содержит интерфейсы Google API. Подробную информацию можно найти в руководстве по началу работы.
  2. В Android Studio выберите пункт меню Запустить или нажмите на значок воспроизведения, чтобы запустить свое приложение. В открывшемся окне выберите устройство.

Android Studio запустит Gradle для сборки приложения, а затем отобразит результаты на устройстве или в эмуляторе.

Вы должны увидеть карту с двумя многоугольниками, наложенными на карту Австралии, такую, как на изображении на этой странице.

Устранение неполадок

  • Если карта не отображается, проверьте, получен ли ключ API и добавлен ли он в приложение как описано выше. Проверьте журнал Android Monitor в Android Studio на наличие сообщений об ошибках, касающихся ключа API.
  • Используйте средства отладки Android Studio чтобы просмотреть журналы и выполнить отладку приложения.

Понимание кода

В этой части руководства представлено объяснение наиболее важных компонентов приложения Polygons, помогающее понять принципы создания подобного приложения.

Проверка манифеста Android

Обратите внимание на следующие элементы в файле AndroidManifest.xml своего приложения:

  • Добавьте элемент meta-data, чтобы указать версию сервисов Google Play, с которой было скомпилировано приложение.

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    
  • Добавьте элемент meta-data с указанием своего ключа API. В примере, приведенном в этом руководстве, значение ключа API выражается строкой google_maps_key. При сборке вашего приложения Gradle копирует ключ API из файла проекта gradle.properties в строковое значение.

    <meta-data
      android:name="com.google.android.geo.API_KEY"
      android:value="@string/google_maps_key" />
    

    Чтобы узнать, каким образом ключ API передается в строковое значение, откройте файл build.gradle своего приложения. Он содержит строку кода, которая сопоставляет строкуgoogle_maps_key со свойством Gradle GOOGLE_MAPS_API_KEY:

    resValue "string", "google_maps_key",
            (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "")
    

Ниже приведен пример манифеста полностью:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.polygons">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <!--
             The API key for Google Maps-based APIs.
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name="com.example.polygons.PolyActivity"
            android:label="@string/title_activity_maps">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Добавление карты

Отобразите карту, используя Maps SDK for Android.

  1. Добавьте элемент <fragment> в файл макета для объекта Activity, activity_maps.xml. Этот элемент указывает, что фрагмент SupportMapFragment должен выступать в роли контейнера для карты и предоставить доступ к объекту GoogleMap. В учебном проекте используется версия вспомогательной библиотеки Android для фрагмента карты, чтобы обеспечить обратную совместимость с более ранними версиями фреймворка Android.

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.polygons.PolyActivity" />
    
    
  2. В методе onCreate() своего объекта activity установите файл макета как представление контента. Получите дескриптор для фрагмента карты путем вызова метода FragmentManager.findFragmentById(). Затем используйте метод getMapAsync(), чтобы зарегистрировать обратный вызов карты:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // Retrieve the content view that renders the map.
        setContentView(R.layout.activity_maps);
    
        // Get the SupportMapFragment and request notification when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(map);
        mapFragment.getMapAsync(this);
    }
    
  3. Реализуйте интерфейс OnMapReadyCallback и переопределите метод onMapReady(). Чтобы вы могли добавлять объекты на карту и настраивать их для своего приложения, API выполняет приведенный ниже обратный вызов, когда объект GoogleMap доступен.

    public class PolyActivity extends AppCompatActivity
            implements
                    OnMapReadyCallback,
                    GoogleMap.OnPolylineClickListener,
                    GoogleMap.OnPolygonClickListener {
    
        // More code goes here, including the onCreate() method described above.
    
        @Override
        public void onMapReady(GoogleMap googleMap) {
    
            // Add polylines and polygons to the map. This section shows just
            // a single polyline. Read the rest of the tutorial to learn more.
            Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
                    .clickable(true)
                    .add(
                            new LatLng(-35.016, 143.321),
                            new LatLng(-34.747, 145.592),
                            new LatLng(-34.364, 147.891),
                            new LatLng(-33.501, 150.217),
                            new LatLng(-32.306, 149.248),
                            new LatLng(-32.491, 147.309)));
    
            // Position the map's camera near Alice Springs in the center of Australia,
            // and set the zoom factor so most of Australia shows on the screen.
            googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.684, 133.903), 4));
    
            // Set listeners for click events.
            googleMap.setOnPolylineClickListener(this);
            googleMap.setOnPolygonClickListener(this);
        }
    }
    

Чтобы начертить линию на карте, используйте ломаную линию

Ломаная линия (объект Polyline) – это последовательность отрезков прямых, с помощью которых можно нарисовать любую фигуру. Как правило, ломаные линии используются для нанесения на карту маршрутов.

  1. Создайте объект PolylineOptions и добавьте к нему точки. Каждая точка соответствует местоположению на карте, которое вы определяете с помощью объекта LatLng с указанием широты и долготы. Ниже приведен пример кода для ломаной линии с шестью точками.

  2. Чтобы добавить ломаную линию на карту, вызовите GoogleMap.addPolyline().

    Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
            .clickable(true)
            .add(
                    new LatLng(-35.016, 143.321),
                    new LatLng(-34.747, 145.592),
                    new LatLng(-34.364, 147.891),
                    new LatLng(-33.501, 150.217),
                    new LatLng(-32.306, 149.248),
                    new LatLng(-32.491, 147.309)));
    

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

Сохранение произвольных данных с помощью ломаной линии

Вы можете сохранять объекты с произвольными данными при помощью ломаных линий и других геометрических фигур.

  1. Чтобы сохранить объект данных с помощью ломаной линии, вызовите метод Polyline.setTag(). Код ниже определяет произвольный тег (A), который указывает на тип ломаной линии.

    Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
            .clickable(true)
            .add(
                    new LatLng(-35.016, 143.321),
                    new LatLng(-34.747, 145.592),
                    new LatLng(-34.364, 147.891),
                    new LatLng(-33.501, 150.217),
                    new LatLng(-32.306, 149.248),
                    new LatLng(-32.491, 147.309)));
    // Store a data object with the polyline, used here to indicate an arbitrary type.
    polyline1.setTag("A");
    
  2. Извлеките данные с помощью метода Polyline.getTag(), как показано в следующем разделе.

Собственный стиль ломаной линии

В объекте PolylineOptions вы можете задавать различные свойства стиля, например, цвет линии, ее толщину и начертание, тип соединения, вид начальной и конечной точек. Если какое-либо свойство не определено, API будет использовать вариант по умолчанию.

Приведенный ниже код задает круглый элемент для конца линии, а также другой круглый элемент для ее начала. Это зависит от типа линии, который представляет собой произвольное свойство в объекте данных для нее. В этом примере также задана толщина линии, ее цвет и тип соединений.

private static final int COLOR_BLACK_ARGB = 0xff000000;
private static final int POLYLINE_STROKE_WIDTH_PX = 12;

private void stylePolyline(Polyline polyline) {
    String type = "";
    // Get the data object stored with the polyline.
    if (polyline.getTag() != null) {
        type = polyline.getTag().toString();
    }

    switch (type) {
        // If no type is given, allow the API to use the default.
        case "A":
            // Use a custom bitmap as the cap at the start of the line.
            polyline.setStartCap(
                    new CustomCap(
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_arrow), 10));
            break;
        case "B":
            // Use a round cap at the start of the line.
            polyline.setStartCap(new RoundCap());
            break;
    }

    polyline.setEndCap(new RoundCap());
    polyline.setWidth(POLYLINE_STROKE_WIDTH_PX);
    polyline.setColor(COLOR_BLACK_ARGB);
    polyline.setJointType(JointType.ROUND);
}

Приведенный ниже код задает пользовательскую битовую карту для ломаной линии типа А, а также ориентировочную толщину линии, равную 10 пикселям. API масштабирует битовую карту с учетом ориентировочной толщины линии. Укажите толщину линии, которую вы использовали при создании битовой карты в исходном размере изображения. Подсказка: откройте битовую карту в графическом редакторе в масштабе 100 % и определите нужную толщину линии для этого изображения.

Подробнее о начальных и конечных точках, а также других вариантах персонализации фигур

Обработка событий кликов для ломаной линии

  1. Чтобы сделать ломаную линию кликабельной, вызовите метод Polyline.setClickable(). По умолчанию ломаные линии не интерактивны, а приложение не получает уведомления, если пользователь нажимает на линию.

  2. Реализуйте интерфейс OnPolylineClickListener и вызовите метод GoogleMap.setOnPolylineClickListener(), чтобы добавить прослушиватель на карту:

    public class PolyActivity extends AppCompatActivity
            implements
                    OnMapReadyCallback,
                    GoogleMap.OnPolylineClickListener,
                    GoogleMap.OnPolygonClickListener {
    
        @Override
        public void onMapReady(GoogleMap googleMap) {
            // Add a polyline to the map.
            Polyline polyline1 = googleMap.addPolyline((new PolylineOptions())
                    .clickable(true)
                    .add(new LatLng(-35.016, 143.321),
                            new LatLng(-34.747, 145.592),
                            new LatLng(-34.364, 147.891),
                            new LatLng(-33.501, 150.217),
                            new LatLng(-32.306, 149.248),
                            new LatLng(-32.491, 147.309)));
    
            // Set listeners for click events.
            googleMap.setOnPolylineClickListener(this);
            googleMap.setOnPolygonClickListener(this);
        }
    }
    
  3. Переопределите метод обратного вызова onPolylineClick(). Пример кода, где вид ломаной линии меняется со сплошного на точечный или обратно каждый раз, когда пользователь нажимает на нее:

    private static final PatternItem DOT = new Dot();
    private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);
    //
    // Create a stroke pattern of a gap followed by a dot.
    private static final List<PatternItem> PATTERN_POLYLINE_DOTTED = Arrays.asList(GAP, DOT);
    
    @Override
    public void onPolylineClick(Polyline polyline) {
        // Flip from solid stroke to dotted stroke pattern.
        if ((polyline.getPattern() == null) || (!polyline.getPattern().contains(DOT))) {
            polyline.setPattern(PATTERN_POLYLINE_DOTTED);
        } else {
            // The default pattern is a solid stroke.
            polyline.setPattern(null);
        }
    
        Toast.makeText(this, "Route type " + polyline.getTag().toString(),
                Toast.LENGTH_SHORT).show();
    }
    

Представление областей на карте с помощью многоугольников

Многоугольник (Polygon) – это фигура, состоящая из упорядоченной последовательности координат и похожая на ломаную линию (Polyline). Разница только в том, что многоугольник – закрытая фигура, которую можно заполнить, а ломаная линия – нет.

  1. Создайте объект PolygonOptions и добавьте к нему точки. Каждая точка соответствует местоположению на карте, которое вы определяете с помощью объекта LatLng с указанием широты и долготы. Ниже приведен пример кода для многоугольника из четырех точек.

  2. Чтобы сделать многоугольник кликабельным, вызовите метод Polygon.setClickable(). По умолчанию многоугольники не интерактивны, а приложение не получает уведомления, если пользователь нажимает на фигуру. События кликов для многоугольников обрабатываются так же, как и для ломаных линий. См. выше.

  3. Чтобы добавить многоугольник на карту, вызовите GoogleMap.addPolygon().

  4. Чтобы сохранить объект данных с помощью многоугольника, вызовите метод Polygon.setTag(). Пример ниже определяет произвольный тип (alpha) для многоугольника.

    Polygon polygon1 = googleMap.addPolygon(new PolygonOptions()
            .clickable(true)
            .add(
                    new LatLng(-27.457, 153.040),
                    new LatLng(-33.852, 151.211),
                    new LatLng(-37.813, 144.962),
                    new LatLng(-34.928, 138.599)));
    // Store a data object with the polygon, used here to indicate an arbitrary type.
    polygon1.setTag("alpha");
    

Собственный стиль многоугольника

В объекте PolygonOptions вы можете задавать различные свойства стиля, например, цвет линии, ее толщину и начертание, тип соединения и цвет заливки. Если какое-либо свойство не определено, API будет использовать вариант по умолчанию.

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

private static final int COLOR_BLACK_ARGB = 0xff000000;
private static final int COLOR_WHITE_ARGB = 0xffffffff;
private static final int COLOR_GREEN_ARGB = 0xff388E3C;
private static final int COLOR_PURPLE_ARGB = 0xff81C784;
private static final int COLOR_ORANGE_ARGB = 0xffF57F17;
private static final int COLOR_BLUE_ARGB = 0xffF9A825;

private static final int POLYGON_STROKE_WIDTH_PX = 8;
private static final int PATTERN_DASH_LENGTH_PX = 20;
private static final int PATTERN_GAP_LENGTH_PX = 20;
private static final PatternItem DOT = new Dot();
private static final PatternItem DASH = new Dash(PATTERN_DASH_LENGTH_PX);
private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);

// Create a stroke pattern of a gap followed by a dash.
private static final List<PatternItem> PATTERN_POLYGON_ALPHA = Arrays.asList(GAP, DASH);

// Create a stroke pattern of a dot followed by a gap, a dash, and another gap.
private static final List<PatternItem> PATTERN_POLYGON_BETA =
        Arrays.asList(DOT, GAP, DASH, GAP);

private void stylePolygon(Polygon polygon) {
    String type = "";
    // Get the data object stored with the polygon.
    if (polygon.getTag() != null) {
        type = polygon.getTag().toString();
    }

    List<PatternItem> pattern = null;
    int strokeColor = COLOR_BLACK_ARGB;
    int fillColor = COLOR_WHITE_ARGB;

    switch (type) {
        // If no type is given, allow the API to use the default.
        case "alpha":
            // Apply a stroke pattern to render a dashed line, and define colors.
            pattern = PATTERN_POLYGON_ALPHA;
            strokeColor = COLOR_GREEN_ARGB;
            fillColor = COLOR_PURPLE_ARGB;
            break;
        case "beta":
            // Apply a stroke pattern to render a line of dots and dashes, and define colors.
            pattern = PATTERN_POLYGON_BETA;
            strokeColor = COLOR_ORANGE_ARGB;
            fillColor = COLOR_BLUE_ARGB;
            break;
    }

    polygon.setStrokePattern(pattern);
    polygon.setStrokeWidth(POLYGON_STROKE_WIDTH_PX);
    polygon.setStrokeColor(strokeColor);
    polygon.setFillColor(fillColor);
}

Подробнее о начертании, а также других вариантах персонализации фигур

Дополнительная информация

Прочитайте статью об объекте Circle. Он похож на многоугольник, но у него есть свойства, определяющие форму круга.