feat: Add samples for V3 BETA 3.1.0 release.

This commit is contained in:
Chris Arriola 2020-05-13 17:17:33 -07:00
parent 325cc756a2
commit 039244ca50
109 changed files with 4798 additions and 1380 deletions

View File

@ -55,15 +55,13 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'
// Needed for the LiteListDemo
implementation "androidx.recyclerview:recyclerview:1.1.0"
v3Implementation name:'maps-sdk-3.0.0-beta', ext:'aar'
v3Implementation 'com.google.android.gms:play-services-basement:17.3.0'
v3Implementation 'com.google.android.gms:play-services-base:17.3.0'
v3Implementation 'com.google.android.gms:play-services-gcm:17.0.0'
v3Implementation 'com.google.android.gms:play-services-location:17.0.0'
// GMS
gmsImplementation 'com.google.android.gms:play-services-maps:17.0.0'
// V3
v3Implementation 'com.google.android.libraries.maps:maps:3.1.0-beta'
// Tests
testImplementation 'junit:junit:4.13'

View File

@ -15,7 +15,7 @@
~ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mapdemo" >
package="com.example.mapdemo">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
@ -37,7 +37,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/demo_title"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
android:theme="@style/AppTheme">
<!--
To add your Maps API key to this project:
@ -51,118 +51,124 @@
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".BasicMapDemoActivity"
android:label="@string/basic_map_demo_label"/>
android:label="@string/basic_map_demo_label" />
<activity
android:name=".CameraDemoActivity"
android:label="@string/camera_demo_label"/>
android:label="@string/camera_demo_label" />
<activity
android:name=".CameraClampingDemoActivity"
android:label="@string/camera_clamping_demo_label"/>
android:label="@string/camera_clamping_demo_label" />
<activity
android:name=".CircleDemoActivity"
android:label="@string/circle_demo_label"/>
android:label="@string/circle_demo_label" />
<activity
android:name=".CloudBasedMapStylingDemoActivity"
android:label="@string/cloud_styling_label" />
<activity
android:name=".EventsDemoActivity"
android:label="@string/events_demo_label"/>
android:label="@string/events_demo_label" />
<activity
android:name=".GroundOverlayDemoActivity"
android:label="@string/ground_overlay_demo_label"/>
android:label="@string/ground_overlay_demo_label" />
<activity
android:name=".IndoorDemoActivity"
android:label="@string/indoor_demo_label"/>
android:label="@string/indoor_demo_label" />
<activity
android:name=".LayersDemoActivity"
android:label="@string/layers_demo_label"/>
android:label="@string/layers_demo_label" />
<activity
android:name=".LiteDemoActivity"
android:label="@string/lite_demo_label"/>
android:label="@string/lite_demo_label" />
<activity
android:name=".LiteListDemoActivity"
android:label="@string/lite_list_demo_label"/>
android:label="@string/lite_list_demo_label" />
<activity
android:name=".LocationSourceDemoActivity"
android:label="@string/location_source_demo_label"/>
android:label="@string/location_source_demo_label" />
<activity
android:name=".MapInPagerDemoActivity"
android:label="@string/map_in_pager_demo_label"/>
android:label="@string/map_in_pager_demo_label" />
<activity
android:name=".MarkerDemoActivity"
android:label="@string/marker_demo_label"/>
android:label="@string/marker_demo_label" />
<activity
android:name=".MarkerCloseInfoWindowOnRetapDemoActivity"
android:label="@string/marker_close_info_window_on_retap_demo_label"/>
android:label="@string/marker_close_info_window_on_retap_demo_label" />
<activity
android:name=".MarkerCollisionDemoActivity"
android:label="@string/marker_collision_label" />
<activity
android:name=".polyline.PolylineDemoActivity"
android:label="@string/polyline_demo_label" />
<activity
android:name=".MultiMapDemoActivity"
android:label="@string/multi_map_demo_label"/>
android:label="@string/multi_map_demo_label" />
<activity
android:name=".MyLocationDemoActivity"
android:label="@string/my_location_demo_label"/>
android:label="@string/my_location_demo_label" />
<activity
android:name=".OptionsDemoActivity"
android:label="@string/options_demo_label"/>
android:label="@string/options_demo_label" />
<activity
android:name=".PolygonDemoActivity"
android:label="@string/polygon_demo_label"/>
<activity
android:name=".PolylineDemoActivity"
android:label="@string/polyline_demo_label"/>
android:label="@string/polygon_demo_label" />
<activity
android:name=".ProgrammaticDemoActivity"
android:label="@string/programmatic_demo_label"/>
android:label="@string/programmatic_demo_label" />
<activity
android:name=".RawMapViewDemoActivity"
android:label="@string/raw_map_view_demo_label"/>
android:label="@string/raw_map_view_demo_label" />
<activity
android:name=".RetainMapDemoActivity"
android:label="@string/retain_map_demo_label"/>
android:label="@string/retain_map_demo_label" />
<activity
android:name=".SaveStateDemoActivity"
android:label="@string/save_state_demo_label"/>
android:label="@string/save_state_demo_label" />
<activity
android:name=".SnapshotDemoActivity"
android:label="@string/snapshot_demo_label"/>
android:label="@string/snapshot_demo_label" />
<activity
android:name=".SplitStreetViewPanoramaAndMapDemoActivity"
android:label="@string/split_street_view_panorama_and_map_demo_label"/>
android:label="@string/split_street_view_panorama_and_map_demo_label" />
<activity
android:name=".StreetViewPanoramaBasicDemoActivity"
android:label="@string/street_view_panorama_basic_demo_label"/>
android:label="@string/street_view_panorama_basic_demo_label" />
<activity
android:name=".StreetViewPanoramaEventsDemoActivity"
android:label="@string/street_view_panorama_events_demo_label"/>
android:label="@string/street_view_panorama_events_demo_label" />
<activity
android:name=".StreetViewPanoramaNavigationDemoActivity"
android:label="@string/street_view_panorama_navigation_demo_label"/>
android:label="@string/street_view_panorama_navigation_demo_label" />
<activity
android:name=".StreetViewPanoramaOptionsDemoActivity"
android:label="@string/street_view_panorama_options_demo_label"/>
android:label="@string/street_view_panorama_options_demo_label" />
<activity
android:name=".StreetViewPanoramaViewDemoActivity"
android:label="@string/street_view_panorama_view_demo_label"/>
android:label="@string/street_view_panorama_view_demo_label" />
<activity
android:name=".StyledMapDemoActivity"
android:label="@string/styled_map_demo_label"/>
android:label="@string/styled_map_demo_label" />
<activity
android:name=".TagsDemoActivity"
android:label="@string/tags_demo_label"/>
android:label="@string/tags_demo_label" />
<activity
android:name=".TileCoordinateDemoActivity"
android:label="@string/tile_coordinate_demo_label"/>
android:label="@string/tile_coordinate_demo_label" />
<activity
android:name=".TileOverlayDemoActivity"
android:label="@string/tile_overlay_demo_label"/>
android:label="@string/tile_overlay_demo_label" />
<activity
android:name=".UiSettingsDemoActivity"
android:label="@string/ui_settings_demo_label"/>
android:label="@string/ui_settings_demo_label" />
<activity
android:name=".VisibleRegionDemoActivity"
android:label="@string/visible_region_demo_label"/>
android:label="@string/visible_region_demo_label" />
</application>

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -93,10 +93,6 @@
<string name="normal">Normal</string>
<string name="options_demo_label">Options</string>
<string name="options_demo_description">Demonstrates how to use Options to initialize a map.</string>
<string name="polygon_demo_label">Polygons</string>
<string name="polygon_demo_description">Demonstrates how to add Polygons to a map.</string>
<string name="polyline_demo_label">Polylines</string>
<string name="polyline_demo_description">Demonstrates how to add Polylines to a map.</string>
<string name="programmatic_demo_label">Programmatically add map</string>
<string name="programmatic_demo_description">Demonstrates how to add a MapFragment programmatically.</string>
<string name="properties_circle">Properties for Circle(s)</string>
@ -159,23 +155,6 @@
<string name="zoom_in">+</string>
<string name="zoom_out">-</string>
<!-- Polyline/polygon styling -->
<string name="start_cap">Start cap</string>
<string name="end_cap">End cap</string>
<string name="joint_type">Joint Type</string>
<string name="pattern">Pattern</string>
<string name="cap_butt">Butt</string>
<string name="cap_square">Square</string>
<string name="cap_round">Round</string>
<string name="cap_image">Image</string>
<string name="joint_type_default">Default</string>
<string name="joint_type_bevel">Bevel</string>
<string name="joint_type_round">Round</string>
<string name="pattern_solid">Solid</string>
<string name="pattern_dotted">Dotted</string>
<string name="pattern_dashed">Dashed</string>
<string name="pattern_mixed">Mixed</string>
<!-- Lite Mode -->
<string name="grid">Grid</string>
<string name="lite_demo_label">Lite Mode</string>
@ -239,4 +218,56 @@
<string name="location_permission_denied">This sample requires location permission to enable the \'my location\' layer. Please try again and grant access to use the location.\nIf the permission has been permanently denied, it can be enabled from the System Settings &gt; Apps &gt; \'Google Maps API Demos\'.</string>
<string name="permission_required_toast">Location permission is required for this demo.</string>
<!-- Cloud Styling -->
<string name="cloud_styling_basic_map_id">26a66b031807a453</string>
<string name="lite_styling_normal_mode">Normal</string>
<string name="lite_styling_satellite_mode">Satellite</string>
<string name="lite_styling_hybrid_mode">Hybrid</string>
<string name="lite_styling_terrain_mode">Terrain</string>
<string name="cloud_styling_label">Cloud Styling</string>
<string name="cloud_styling_description">Demonstrates how to use a simple map using Cloud Styling.</string>
<!-- Polyline/polygon styling -->
<string name="polygon_demo_label">Polygons</string>
<string name="polygon_demo_description">Demonstrates how to add Polygons to a map.</string>
<string name="start_cap">Start cap</string>
<string name="end_cap">End cap</string>
<string name="joint_type">Joint Type</string>
<string name="pattern">Pattern</string>
<string name="cap_butt">Butt</string>
<string name="cap_square">Square</string>
<string name="cap_round">Round</string>
<string name="cap_image">Image</string>
<string name="joint_type_default">Default</string>
<string name="joint_type_bevel">Bevel</string>
<string name="joint_type_round">Round</string>
<string name="pattern_solid">Solid</string>
<string name="pattern_dotted">Dotted</string>
<string name="pattern_dashed">Dashed</string>
<string name="pattern_mixed">Mixed</string>
<string name="polyline_demo_label">Polylines</string>
<string name="polyline_demo_description">Demonstrates how to add and configure Polylines to a map.</string>
<string name="polyline_selection">Select polyline</string>
<string name="polyline_sydney">Sydney</string>
<string name="polyline_melbourne">Melbourne</string>
<string name="polyline_australia">Australia</string>
<string name="polyline_world">World</string>
<string name="argb">ARGB</string>
<string name="cap_custom_chevron">Chevron</string>
<string name="cap_custom_ook">Ook</string>
<string name="joint_default">Default</string>
<string name="joint_bevel">Bevel</string>
<string name="joint_round">Round</string>
<string name="solid" desc="Label of a toggle button indicating that the selected polyline should have solid color.">Solid color</string>
<string name="gradient" desc="Label of a toggle button indicating that the selected polyline should have a color gradient.">Gradient color</string>
<string name="textured" desc="Label of a checkbox indicating whether or not the selected polyline has texture.">Textured</string>
<string name="point_sprite" desc="Label of a checkbox indicating whether or not the point sprite rendering technique is applied on textured polyline.">Point sprite</string>
<string name="default_style" desc="Label of a radio group indicating whether or not default style is applied.">Default</string>
<string name="geodesic">Geodesic</string>
<string name="visible">Visible</string>
<!-- Marker Collision -->
<string name="marker_collision_label">Marker Collision</string>
<string name="marker_collision_description">Demonstrates different supported marker collision behaviors.</string>
</resources>

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -28,7 +21,6 @@ import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -19,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.CameraUpdateFactory;
@ -32,12 +24,11 @@ import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.LatLngBounds;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
/**
* This shows how to constrain the camera to specific boundaries and zoom levels.
*/

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -19,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.example.mapdemo;
import android.graphics.Color;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -0,0 +1,58 @@
package com.example.mapdemo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.libraries.maps.GoogleMap;
import com.google.android.libraries.maps.OnMapReadyCallback;
import com.google.android.libraries.maps.SupportMapFragment;
/**
* This shows how to use Cloud-based Map Styling in a simple Activity. For more information on how
* to style a map using this method, see:
* https://developers.google.com/maps/documentation/android-sdk/cloud-styling-android
**/
public class CloudBasedMapStylingDemoActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final String MAP_TYPE_KEY = "map_type";
private GoogleMap map;
private int currentMapType = GoogleMap.MAP_TYPE_NORMAL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentMapType = savedInstanceState.getInt(MAP_TYPE_KEY);
}
// The underlying style the map will use has been set in the layout
// `cloud_styling_basic_demo` under the SupportMapFragment's `map:mapId` attribute.
setContentView(R.layout.cloud_styling_basic_demo);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
setUpButtonListeners();
}
@Override
public void onMapReady(GoogleMap map) {
this.map = map;
map.setMapType(currentMapType);
}
private void setUpButtonListeners() {
findViewById(R.id.styling_normal_mode).setOnClickListener(
v -> setMapType(GoogleMap.MAP_TYPE_NORMAL));
findViewById(R.id.styling_satellite_mode).setOnClickListener(
v -> setMapType(GoogleMap.MAP_TYPE_SATELLITE));
findViewById(R.id.styling_hybrid_mode).setOnClickListener(
v -> setMapType(GoogleMap.MAP_TYPE_HYBRID));
findViewById(R.id.styling_terrain_mode).setOnClickListener(
v -> setMapType(GoogleMap.MAP_TYPE_TERRAIN));
}
private void setMapType(int mapType) {
currentMapType = mapType;
map.setMapType(mapType);
}
}

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -22,123 +15,136 @@
package com.example.mapdemo;
import com.example.mapdemo.polyline.PolylineDemoActivity;
/**
* A list of all the demos we have available.
*/
public final class DemoDetailsList {
/** This class should not be instantiated. */
/**
* This class should not be instantiated.
*/
private DemoDetailsList() {
}
public static final DemoDetails[] DEMOS = {
new DemoDetails(R.string.basic_map_demo_label,
R.string.basic_map_demo_description,
BasicMapDemoActivity.class),
new DemoDetails(R.string.camera_demo_label,
R.string.camera_demo_description,
CameraDemoActivity.class),
new DemoDetails(R.string.camera_clamping_demo_label,
R.string.camera_clamping_demo_description,
CameraClampingDemoActivity.class),
new DemoDetails(R.string.circle_demo_label,
R.string.circle_demo_description,
CircleDemoActivity.class),
new DemoDetails(R.string.events_demo_label,
R.string.events_demo_description,
EventsDemoActivity.class),
new DemoDetails(R.string.ground_overlay_demo_label,
R.string.ground_overlay_demo_description,
GroundOverlayDemoActivity.class),
new DemoDetails(R.string.indoor_demo_label,
R.string.indoor_demo_description,
IndoorDemoActivity.class),
new DemoDetails(R.string.layers_demo_label,
R.string.layers_demo_description,
LayersDemoActivity.class),
new DemoDetails(R.string.lite_demo_label,
R.string.lite_demo_description,
LiteDemoActivity.class),
new DemoDetails(R.string.lite_list_demo_label,
R.string.lite_list_demo_description,
LiteListDemoActivity.class),
new DemoDetails(R.string.location_source_demo_label,
R.string.location_source_demo_description,
LocationSourceDemoActivity.class),
new DemoDetails(R.string.map_in_pager_demo_label,
R.string.map_in_pager_demo_description,
MapInPagerDemoActivity.class),
new DemoDetails(R.string.marker_demo_label,
R.string.marker_demo_description,
MarkerDemoActivity.class),
new DemoDetails(R.string.marker_close_info_window_on_retap_demo_label,
R.string.marker_close_info_window_on_retap_demo_description,
MarkerCloseInfoWindowOnRetapDemoActivity.class),
new DemoDetails(R.string.multi_map_demo_label,
R.string.multi_map_demo_description,
MultiMapDemoActivity.class),
new DemoDetails(R.string.my_location_demo_label,
R.string.my_location_demo_description,
MyLocationDemoActivity.class),
new DemoDetails(R.string.options_demo_label,
R.string.options_demo_description,
OptionsDemoActivity.class),
new DemoDetails(R.string.polygon_demo_label,
R.string.polygon_demo_description,
PolygonDemoActivity.class),
new DemoDetails(R.string.polyline_demo_label,
R.string.polyline_demo_description,
PolylineDemoActivity.class),
new DemoDetails(R.string.programmatic_demo_label,
R.string.programmatic_demo_description,
ProgrammaticDemoActivity.class),
new DemoDetails(R.string.raw_map_view_demo_label,
R.string.raw_map_view_demo_description,
RawMapViewDemoActivity.class),
new DemoDetails(R.string.retain_map_demo_label,
R.string.retain_map_demo_description,
RetainMapDemoActivity.class),
new DemoDetails(R.string.save_state_demo_label,
R.string.save_state_demo_description,
SaveStateDemoActivity.class),
new DemoDetails(R.string.snapshot_demo_label,
R.string.snapshot_demo_description,
SnapshotDemoActivity.class),
new DemoDetails(R.string.split_street_view_panorama_and_map_demo_label,
R.string.split_street_view_panorama_and_map_demo_description,
SplitStreetViewPanoramaAndMapDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_basic_demo_label,
R.string.street_view_panorama_basic_demo_description,
StreetViewPanoramaBasicDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_events_demo_label,
R.string.street_view_panorama_events_demo_description,
StreetViewPanoramaEventsDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_navigation_demo_label,
R.string.street_view_panorama_navigation_demo_description,
StreetViewPanoramaNavigationDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_options_demo_label,
R.string.street_view_panorama_options_demo_description,
StreetViewPanoramaOptionsDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_view_demo_label,
R.string.street_view_panorama_view_demo_description,
StreetViewPanoramaViewDemoActivity.class),
new DemoDetails(R.string.styled_map_demo_label,
R.string.styled_map_demo_description,
StyledMapDemoActivity.class),
new DemoDetails(R.string.tags_demo_label,
R.string.tags_demo_description,
TagsDemoActivity.class),
new DemoDetails(R.string.tile_coordinate_demo_label,
R.string.tile_coordinate_demo_description,
TileCoordinateDemoActivity.class),
new DemoDetails(R.string.tile_overlay_demo_label,
R.string.tile_overlay_demo_description,
TileOverlayDemoActivity.class),
new DemoDetails(R.string.ui_settings_demo_label,
R.string.ui_settings_demo_description,
UiSettingsDemoActivity.class),
new DemoDetails(R.string.visible_region_demo_label,
R.string.visible_region_demo_description,
VisibleRegionDemoActivity.class),
new DemoDetails(R.string.basic_map_demo_label,
R.string.basic_map_demo_description,
BasicMapDemoActivity.class),
new DemoDetails(R.string.camera_demo_label,
R.string.camera_demo_description,
CameraDemoActivity.class),
new DemoDetails(R.string.camera_clamping_demo_label,
R.string.camera_clamping_demo_description,
CameraClampingDemoActivity.class),
new DemoDetails(R.string.circle_demo_label,
R.string.circle_demo_description,
CircleDemoActivity.class),
new DemoDetails(R.string.cloud_styling_label,
R.string.cloud_styling_description,
CloudBasedMapStylingDemoActivity.class),
new DemoDetails(R.string.events_demo_label,
R.string.events_demo_description,
EventsDemoActivity.class),
new DemoDetails(R.string.ground_overlay_demo_label,
R.string.ground_overlay_demo_description,
GroundOverlayDemoActivity.class),
new DemoDetails(R.string.indoor_demo_label,
R.string.indoor_demo_description,
IndoorDemoActivity.class),
new DemoDetails(R.string.layers_demo_label,
R.string.layers_demo_description,
LayersDemoActivity.class),
new DemoDetails(R.string.lite_demo_label,
R.string.lite_demo_description,
LiteDemoActivity.class),
new DemoDetails(R.string.lite_list_demo_label,
R.string.lite_list_demo_description,
LiteListDemoActivity.class),
new DemoDetails(R.string.location_source_demo_label,
R.string.location_source_demo_description,
LocationSourceDemoActivity.class),
new DemoDetails(R.string.map_in_pager_demo_label,
R.string.map_in_pager_demo_description,
MapInPagerDemoActivity.class),
new DemoDetails(R.string.marker_demo_label,
R.string.marker_demo_description,
MarkerDemoActivity.class),
new DemoDetails(R.string.marker_collision_label,
R.string.marker_collision_description,
MarkerCollisionDemoActivity.class),
new DemoDetails(R.string.marker_close_info_window_on_retap_demo_label,
R.string.marker_close_info_window_on_retap_demo_description,
MarkerCloseInfoWindowOnRetapDemoActivity.class),
new DemoDetails(R.string.polyline_demo_label,
R.string.polyline_demo_description,
PolylineDemoActivity.class),
new DemoDetails(R.string.multi_map_demo_label,
R.string.multi_map_demo_description,
MultiMapDemoActivity.class),
new DemoDetails(R.string.my_location_demo_label,
R.string.my_location_demo_description,
MyLocationDemoActivity.class),
new DemoDetails(R.string.options_demo_label,
R.string.options_demo_description,
OptionsDemoActivity.class),
new DemoDetails(R.string.polygon_demo_label,
R.string.polygon_demo_description,
PolygonDemoActivity.class),
new DemoDetails(R.string.polyline_demo_label,
R.string.polyline_demo_description,
PolylineDemoActivity.class),
new DemoDetails(R.string.programmatic_demo_label,
R.string.programmatic_demo_description,
ProgrammaticDemoActivity.class),
new DemoDetails(R.string.raw_map_view_demo_label,
R.string.raw_map_view_demo_description,
RawMapViewDemoActivity.class),
new DemoDetails(R.string.retain_map_demo_label,
R.string.retain_map_demo_description,
RetainMapDemoActivity.class),
new DemoDetails(R.string.save_state_demo_label,
R.string.save_state_demo_description,
SaveStateDemoActivity.class),
new DemoDetails(R.string.snapshot_demo_label,
R.string.snapshot_demo_description,
SnapshotDemoActivity.class),
new DemoDetails(R.string.split_street_view_panorama_and_map_demo_label,
R.string.split_street_view_panorama_and_map_demo_description,
SplitStreetViewPanoramaAndMapDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_basic_demo_label,
R.string.street_view_panorama_basic_demo_description,
StreetViewPanoramaBasicDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_events_demo_label,
R.string.street_view_panorama_events_demo_description,
StreetViewPanoramaEventsDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_navigation_demo_label,
R.string.street_view_panorama_navigation_demo_description,
StreetViewPanoramaNavigationDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_options_demo_label,
R.string.street_view_panorama_options_demo_description,
StreetViewPanoramaOptionsDemoActivity.class),
new DemoDetails(R.string.street_view_panorama_view_demo_label,
R.string.street_view_panorama_view_demo_description,
StreetViewPanoramaViewDemoActivity.class),
new DemoDetails(R.string.styled_map_demo_label,
R.string.styled_map_demo_description,
StyledMapDemoActivity.class),
new DemoDetails(R.string.tags_demo_label,
R.string.tags_demo_description,
TagsDemoActivity.class),
new DemoDetails(R.string.tile_coordinate_demo_label,
R.string.tile_coordinate_demo_description,
TileCoordinateDemoActivity.class),
new DemoDetails(R.string.tile_overlay_demo_label,
R.string.tile_overlay_demo_description,
TileOverlayDemoActivity.class),
new DemoDetails(R.string.ui_settings_demo_label,
R.string.ui_settings_demo_description,
UiSettingsDemoActivity.class),
new DemoDetails(R.string.visible_region_demo_label,
R.string.visible_region_demo_description,
VisibleRegionDemoActivity.class),
};
}

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -20,6 +13,7 @@
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.GoogleMap;
@ -31,9 +25,8 @@ import com.google.android.libraries.maps.SupportMapFragment;
import com.google.android.libraries.maps.model.LatLng;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.TextView;
/**
* This shows how to listen to some {@link GoogleMap} events.

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -20,6 +13,7 @@
// limitations under the License.
package com.example.mapdemo;
import android.content.Context;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -20,6 +13,7 @@
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.CameraUpdateFactory;
@ -33,13 +27,12 @@ import com.google.android.libraries.maps.model.GroundOverlayOptions;
import com.google.android.libraries.maps.model.LatLng;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -31,11 +24,10 @@ import com.google.android.libraries.maps.model.IndoorLevel;
import com.google.android.libraries.maps.model.LatLng;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.List;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -29,6 +22,9 @@ import com.google.android.libraries.maps.SupportMapFragment;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
@ -38,10 +34,6 @@ import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import static com.google.android.libraries.maps.GoogleMap.MAP_TYPE_HYBRID;
import static com.google.android.libraries.maps.GoogleMap.MAP_TYPE_NONE;
import static com.google.android.libraries.maps.GoogleMap.MAP_TYPE_NORMAL;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -20,6 +13,7 @@
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.CameraUpdateFactory;
@ -34,9 +28,8 @@ import com.google.android.libraries.maps.model.PolylineOptions;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
/**
* This demo shows some features supported in lite mode.

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -31,16 +24,16 @@ import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* This shows to include a map in lite mode in a ListView.

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -20,6 +13,7 @@
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.GoogleMap;
@ -31,7 +25,6 @@ import com.google.android.libraries.maps.model.LatLng;
import android.location.Location;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -84,7 +77,7 @@ public final class MainActivity extends AppCompatActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView list = (ListView) findViewById(R.id.list);
ListView list = findViewById(R.id.list);
ListAdapter adapter = new CustomArrayAdapter(this, DemoDetailsList.DEMOS);
@ -93,7 +86,7 @@ public final class MainActivity extends AppCompatActivity
list.setEmptyView(findViewById(R.id.empty));
if (getString(R.string.maps_api_key).isEmpty()) {
Toast.makeText(this, "Add your own API key in ApiDemos/java/secure.properties as MAPS_API_KEY=YOUR_API_KEY", Toast.LENGTH_LONG).show();
Toast.makeText(this, "Add your own API key in ApiDemos/java/app/secure.properties as MAPS_API_KEY=YOUR_API_KEY", Toast.LENGTH_LONG).show();
}
}

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -25,34 +18,38 @@ package com.example.mapdemo;
import com.google.android.libraries.maps.SupportMapFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* This shows how to add a map to a ViewPager. Note the use of
* {@link ViewGroup#requestTransparentRegion(View)} to reduce jankiness.
*/
public class MapInPagerDemoActivity extends AppCompatActivity {
private MyAdapter mAdapter;
private ViewPager mPager;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_in_pager_demo);
MyAdapter adapter = new MyAdapter(getSupportFragmentManager());
mAdapter = new MyAdapter(getSupportFragmentManager());
ViewPager pager = findViewById(R.id.pager);
pager.setAdapter(adapter);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
// This is required to avoid a black flash when the map is loaded. The flash is due
// to the use of a SurfaceView as the underlying view of the map.
pager.requestTransparentRegion(pager);
mPager.requestTransparentRegion(mPager);
}
/** A simple fragment that displays a TextView. */
@ -68,7 +65,7 @@ public class MapInPagerDemoActivity extends AppCompatActivity {
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
super(fm);
}
@Override

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -33,7 +26,6 @@ import com.google.android.libraries.maps.model.Marker;
import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -0,0 +1,84 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.libraries.maps.CameraUpdateFactory;
import com.google.android.libraries.maps.GoogleMap;
import com.google.android.libraries.maps.OnMapReadyCallback;
import com.google.android.libraries.maps.SupportMapFragment;
import com.google.android.libraries.maps.model.BitmapDescriptorFactory;
import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.Marker;
import com.google.android.libraries.maps.model.MarkerOptions;
/** This shows how to set collision behavior for the marker. */
public class MarkerCollisionDemoActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
private GoogleMap map = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.marker_collision_demo);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap map) {
this.map = map;
addMarkersToMap();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 3));
}
private void addMarkersToMap() {
MarkerOptions defaultMarkerOptions = new MarkerOptions();
// Add 100 markers to the map.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
defaultMarkerOptions
.position(new LatLng(SYDNEY.latitude + i, SYDNEY.longitude - j))
.zIndex(i * 10 + j)
.title("zIndex:" + (i * 10 + j))
.draggable(true);
if ((i + j) % 3 == 0) {
defaultMarkerOptions.icon(
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
defaultMarkerOptions.collisionBehavior(
Marker.CollisionBehavior.OPTIONAL_AND_HIDES_LOWER_PRIORITY);
} else if ((i + j) % 3 == 1) {
defaultMarkerOptions.icon(
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
defaultMarkerOptions.collisionBehavior(Marker.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL);
} else {
defaultMarkerOptions.icon(
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
defaultMarkerOptions.collisionBehavior(Marker.CollisionBehavior.REQUIRED);
}
map.addMarker(defaultMarkerOptions);
}
}
}
}

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -19,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.CameraUpdateFactory;
@ -44,12 +38,11 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.View;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -23,7 +16,6 @@
package com.example.mapdemo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -22,6 +15,7 @@
package com.example.mapdemo;
import android.location.Location;
import com.google.android.libraries.maps.GoogleMap;
import com.google.android.libraries.maps.GoogleMap.OnMyLocationButtonClickListener;
import com.google.android.libraries.maps.GoogleMap.OnMyLocationClickListener;
@ -30,27 +24,25 @@ import com.google.android.libraries.maps.SupportMapFragment;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Toast;
/**
* This demo shows how GMS Location can be used to check for changes to the users location. The
* "My Location" button uses GMS Location to set the blue dot representing the users location.
* Permission for {@link android.Manifest.permission#ACCESS_FINE_LOCATION} is requested at run
* time. If the permission has not been granted, the Activity is finished with an error message.
* This demo shows how GMS Location can be used to check for changes to the users location. The "My
* Location" button uses GMS Location to set the blue dot representing the users location.
* Permission for {@link android.Manifest.permission#ACCESS_FINE_LOCATION} is requested at run time.
* If the permission has not been granted, the Activity is finished with an error message.
*/
public class MyLocationDemoActivity extends AppCompatActivity
implements
OnMyLocationButtonClickListener,
OnMyLocationClickListener,
OnMapReadyCallback,
ActivityCompat.OnRequestPermissionsResultCallback {
implements
OnMyLocationButtonClickListener,
OnMyLocationClickListener,
OnMapReadyCallback,
ActivityCompat.OnRequestPermissionsResultCallback {
/**
* Request code for location permission request.
@ -60,8 +52,8 @@ public class MyLocationDemoActivity extends AppCompatActivity
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
/**
* Flag indicating whether a requested permission has been denied after returning in
* {@link #onRequestPermissionsResult(int, String[], int[])}.
* Flag indicating whether a requested permission has been denied after returning in {@link
* #onRequestPermissionsResult(int, String[], int[])}.
*/
private boolean permissionDenied = false;
@ -73,7 +65,7 @@ public class MyLocationDemoActivity extends AppCompatActivity
setContentView(R.layout.my_location_demo);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@ -91,7 +83,7 @@ public class MyLocationDemoActivity extends AppCompatActivity
private void enableMyLocation() {
// [START maps_check_location_permission]
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
== PackageManager.PERMISSION_GRANTED) {
if (map != null) {
map.setMyLocationEnabled(true);
}
@ -118,12 +110,14 @@ public class MyLocationDemoActivity extends AppCompatActivity
// [START maps_check_location_permission_result]
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
return;
}
if (PermissionUtils.isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION)) {
if (PermissionUtils.isPermissionGranted(permissions, grantResults,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Enable the my location layer if the permission has been granted.
enableMyLocation();
} else {
@ -151,7 +145,7 @@ public class MyLocationDemoActivity extends AppCompatActivity
*/
private void showMissingPermissionError() {
PermissionUtils.PermissionDeniedDialog
.newInstance(true).show(getSupportFragmentManager(), "dialog");
.newInstance(true).show(getSupportFragmentManager(), "dialog");
}
}
}

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -19,11 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.example.mapdemo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -28,10 +21,9 @@ import android.app.Dialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Toast;
/**
@ -44,7 +36,7 @@ public abstract class PermissionUtils {
* be shown to the user, displays a dialog that triggers the request.
*/
public static void requestPermission(AppCompatActivity activity, int requestId,
String permission, boolean finishActivity) {
String permission, boolean finishActivity) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
// Display a dialog with rationale.
PermissionUtils.RationaleDialog.newInstance(requestId, finishActivity)

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -24,6 +17,7 @@ package com.example.mapdemo;
import android.graphics.Color;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
@ -33,8 +27,6 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.libraries.maps.CameraUpdateFactory;
import com.google.android.libraries.maps.GoogleMap;
import com.google.android.libraries.maps.OnMapReadyCallback;

View File

@ -1,332 +0,0 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.example.mapdemo;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.libraries.maps.CameraUpdateFactory;
import com.google.android.libraries.maps.GoogleMap;
import com.google.android.libraries.maps.OnMapReadyCallback;
import com.google.android.libraries.maps.SupportMapFragment;
import com.google.android.libraries.maps.model.BitmapDescriptorFactory;
import com.google.android.libraries.maps.model.ButtCap;
import com.google.android.libraries.maps.model.Cap;
import com.google.android.libraries.maps.model.CustomCap;
import com.google.android.libraries.maps.model.Dash;
import com.google.android.libraries.maps.model.Dot;
import com.google.android.libraries.maps.model.Gap;
import com.google.android.libraries.maps.model.JointType;
import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.PatternItem;
import com.google.android.libraries.maps.model.Polyline;
import com.google.android.libraries.maps.model.PolylineOptions;
import com.google.android.libraries.maps.model.RoundCap;
import com.google.android.libraries.maps.model.SquareCap;
import java.util.Arrays;
import java.util.List;
/**
* This shows how to draw polylines on a map.
*/
public class PolylineDemoActivity extends AppCompatActivity
implements OnSeekBarChangeListener, OnItemSelectedListener, OnMapReadyCallback {
// City locations for mutable polyline.
private static final LatLng ADELAIDE = new LatLng(-34.92873, 138.59995);
private static final LatLng DARWIN = new LatLng(-12.4258647, 130.7932231);
private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298);
private static final LatLng PERTH = new LatLng(-31.95285, 115.85734);
// Airport locations for geodesic polyline.
private static final LatLng AKL = new LatLng(-37.006254, 174.783018);
private static final LatLng JFK = new LatLng(40.641051, -73.777485);
private static final LatLng LAX = new LatLng(33.936524, -118.377686);
private static final LatLng LHR = new LatLng(51.471547, -0.460052);
private static final int MAX_WIDTH_PX = 100;
private static final int MAX_HUE_DEGREES = 360;
private static final int MAX_ALPHA = 255;
private static final int CUSTOM_CAP_IMAGE_REF_WIDTH_PX = 50;
private static final int INITIAL_STROKE_WIDTH_PX = 5;
private static final int PATTERN_DASH_LENGTH_PX = 50;
private static final int PATTERN_GAP_LENGTH_PX = 20;
private static final Dot DOT = new Dot();
private static final Dash DASH = new Dash(PATTERN_DASH_LENGTH_PX);
private static final Gap GAP = new Gap(PATTERN_GAP_LENGTH_PX);
private static final List<PatternItem> PATTERN_DOTTED = Arrays.asList(DOT, GAP);
private static final List<PatternItem> PATTERN_DASHED = Arrays.asList(DASH, GAP);
private static final List<PatternItem> PATTERN_MIXED = Arrays.asList(DOT, GAP, DOT, DASH, GAP);
private Polyline mutablePolyline;
private SeekBar hueBar;
private SeekBar alphaBar;
private SeekBar widthBar;
private Spinner startCapSpinner;
private Spinner endCapSpinner;
private Spinner jointTypeSpinner;
private Spinner patternSpinner;
private CheckBox clickabilityCheckbox;
// These are the options for polyline caps, joints and patterns. We use their
// string resource IDs as identifiers.
private static final int[] CAP_TYPE_NAME_RESOURCE_IDS = {
R.string.cap_butt, // Default
R.string.cap_round,
R.string.cap_square,
R.string.cap_image,
};
private static final int[] JOINT_TYPE_NAME_RESOURCE_IDS = {
R.string.joint_type_default, // Default
R.string.joint_type_bevel,
R.string.joint_type_round,
};
private static final int[] PATTERN_TYPE_NAME_RESOURCE_IDS = {
R.string.pattern_solid, // Default
R.string.pattern_dashed,
R.string.pattern_dotted,
R.string.pattern_mixed,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.polyline_demo);
hueBar = findViewById(R.id.hueSeekBar);
hueBar.setMax(MAX_HUE_DEGREES);
hueBar.setProgress(0);
alphaBar = findViewById(R.id.alphaSeekBar);
alphaBar.setMax(MAX_ALPHA);
alphaBar.setProgress(MAX_ALPHA);
widthBar = findViewById(R.id.widthSeekBar);
widthBar.setMax(MAX_WIDTH_PX);
widthBar.setProgress(MAX_WIDTH_PX / 2);
startCapSpinner = findViewById(R.id.startCapSpinner);
startCapSpinner.setAdapter(new ArrayAdapter<>(
this, android.R.layout.simple_spinner_item,
getResourceStrings(CAP_TYPE_NAME_RESOURCE_IDS)));
endCapSpinner = findViewById(R.id.endCapSpinner);
endCapSpinner.setAdapter(new ArrayAdapter<>(
this, android.R.layout.simple_spinner_item,
getResourceStrings(CAP_TYPE_NAME_RESOURCE_IDS)));
jointTypeSpinner = findViewById(R.id.jointTypeSpinner);
jointTypeSpinner.setAdapter(new ArrayAdapter<>(
this, android.R.layout.simple_spinner_item,
getResourceStrings(JOINT_TYPE_NAME_RESOURCE_IDS)));
patternSpinner = findViewById(R.id.patternSpinner);
patternSpinner.setAdapter(new ArrayAdapter<>(
this, android.R.layout.simple_spinner_item,
getResourceStrings(PATTERN_TYPE_NAME_RESOURCE_IDS)));
clickabilityCheckbox = findViewById(R.id.toggleClickability);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
private String[] getResourceStrings(int[] resourceIds) {
String[] strings = new String[resourceIds.length];
for (int i = 0; i < resourceIds.length; i++) {
strings[i] = getString(resourceIds[i]);
}
return strings;
}
@Override
public void onMapReady(GoogleMap map) {
// Override the default content description on the view, for accessibility mode.
map.setContentDescription(getString(R.string.polyline_demo_description));
// A geodesic polyline that goes around the world.
map.addPolyline(new PolylineOptions()
.add(LHR, AKL, LAX, JFK, LHR)
.width(INITIAL_STROKE_WIDTH_PX)
.color(Color.BLUE)
.geodesic(true)
.clickable(clickabilityCheckbox.isChecked()));
// A simple polyline across Australia. This polyline will be mutable.
int color = Color.HSVToColor(
alphaBar.getProgress(), new float[]{hueBar.getProgress(), 1, 1});
mutablePolyline = map.addPolyline(new PolylineOptions()
.color(color)
.width(widthBar.getProgress())
.clickable(clickabilityCheckbox.isChecked())
.add(MELBOURNE, ADELAIDE, PERTH, DARWIN));
hueBar.setOnSeekBarChangeListener(this);
alphaBar.setOnSeekBarChangeListener(this);
widthBar.setOnSeekBarChangeListener(this);
startCapSpinner.setOnItemSelectedListener(this);
endCapSpinner.setOnItemSelectedListener(this);
jointTypeSpinner.setOnItemSelectedListener(this);
patternSpinner.setOnItemSelectedListener(this);
mutablePolyline.setStartCap(getSelectedCap(startCapSpinner.getSelectedItemPosition()));
mutablePolyline.setEndCap(getSelectedCap(endCapSpinner.getSelectedItemPosition()));
mutablePolyline.setJointType(getSelectedJointType(jointTypeSpinner.getSelectedItemPosition()));
mutablePolyline.setPattern(getSelectedPattern(patternSpinner.getSelectedItemPosition()));
// Move the map so that it is centered on the mutable polyline.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(MELBOURNE, 3));
// Add a listener for polyline clicks that changes the clicked polyline's color.
map.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
@Override
public void onPolylineClick(Polyline polyline) {
// Flip the values of the red, green and blue components of the polyline's color.
polyline.setColor(polyline.getColor() ^ 0x00ffffff);
}
});
}
private Cap getSelectedCap(int pos) {
switch (CAP_TYPE_NAME_RESOURCE_IDS[pos]) {
case R.string.cap_butt:
return new ButtCap();
case R.string.cap_square:
return new SquareCap();
case R.string.cap_round:
return new RoundCap();
case R.string.cap_image:
return new CustomCap(
BitmapDescriptorFactory.fromResource(R.drawable.chevron),
CUSTOM_CAP_IMAGE_REF_WIDTH_PX);
}
return null;
}
private int getSelectedJointType(int pos) {
switch (JOINT_TYPE_NAME_RESOURCE_IDS[pos]) {
case R.string.joint_type_bevel:
return JointType.BEVEL;
case R.string.joint_type_round:
return JointType.ROUND;
case R.string.joint_type_default:
return JointType.DEFAULT;
}
return 0;
}
private List<PatternItem> getSelectedPattern(int pos) {
switch (PATTERN_TYPE_NAME_RESOURCE_IDS[pos]) {
case R.string.pattern_solid:
return null;
case R.string.pattern_dotted:
return PATTERN_DOTTED;
case R.string.pattern_dashed:
return PATTERN_DASHED;
case R.string.pattern_mixed:
return PATTERN_MIXED;
default:
return null;
}
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
switch (parent.getId()) {
case R.id.startCapSpinner:
mutablePolyline.setStartCap(getSelectedCap(pos));
break;
case R.id.endCapSpinner:
mutablePolyline.setEndCap(getSelectedCap(pos));
break;
case R.id.jointTypeSpinner:
mutablePolyline.setJointType(getSelectedJointType(pos));
break;
case R.id.patternSpinner:
mutablePolyline.setPattern(getSelectedPattern(pos));
break;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Don't do anything here.
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mutablePolyline == null) {
return;
}
if (seekBar == hueBar) {
mutablePolyline.setColor(Color.HSVToColor(
Color.alpha(mutablePolyline.getColor()), new float[]{progress, 1, 1}));
} else if (seekBar == alphaBar) {
float[] prevHSV = new float[3];
Color.colorToHSV(mutablePolyline.getColor(), prevHSV);
mutablePolyline.setColor(Color.HSVToColor(progress, prevHSV));
} else if (seekBar == widthBar) {
mutablePolyline.setWidth(progress);
}
}
/**
* Toggles the clickability of the polyline based on the state of the View that triggered this
* call.
* This callback is defined on the CheckBox in the layout for this Activity.
*/
public void toggleClickability(View view) {
if (mutablePolyline != null) {
mutablePolyline.setClickable(((CheckBox) view).isChecked());
}
}
}

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -29,9 +22,8 @@ import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import androidx.appcompat.app.AppCompatActivity;
/**
* Demonstrates how to instantiate a SupportMapFragment programmatically and add a marker to it.

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -29,7 +22,6 @@ import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -29,7 +22,6 @@ import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -36,7 +29,6 @@ import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Random;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -30,12 +23,11 @@ import com.google.android.libraries.maps.SupportMapFragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
/**
* This shows how to take a snapshot of the map.
*/

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -37,7 +30,6 @@ import com.google.android.libraries.maps.model.MarkerOptions;
import com.google.android.libraries.maps.model.StreetViewPanoramaLocation;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -28,7 +21,6 @@ import com.google.android.libraries.maps.SupportStreetViewPanoramaFragment;
import com.google.android.libraries.maps.model.LatLng;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
/**

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -31,13 +24,11 @@ import com.google.android.libraries.maps.model.StreetViewPanoramaLink;
import com.google.android.libraries.maps.model.StreetViewPanoramaLocation;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.SeekBar;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
/**
* This shows how to create an activity with access to all the options in Panorama
* which can be adjusted dynamically

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -23,12 +16,11 @@
package com.example.mapdemo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.libraries.maps.StreetViewPanorama;
import com.google.android.libraries.maps.SupportStreetViewPanoramaFragment;
import com.google.android.libraries.maps.model.LatLng;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -31,14 +24,13 @@ import com.google.android.libraries.maps.model.MapStyleOptions;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -24,10 +17,8 @@ package com.example.mapdemo;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.TextView;
import com.google.android.libraries.maps.CameraUpdateFactory;
import com.google.android.libraries.maps.GoogleMap;
import com.google.android.libraries.maps.GoogleMap.OnCircleClickListener;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -34,7 +27,6 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import java.io.ByteArrayOutputStream;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -20,6 +13,7 @@
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.GoogleMap;
@ -31,13 +25,12 @@ import com.google.android.libraries.maps.model.TileProvider;
import com.google.android.libraries.maps.model.UrlTileProvider;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import androidx.appcompat.app.AppCompatActivity;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
@ -52,7 +45,7 @@ public class TileOverlayDemoActivity extends AppCompatActivity
/** This returns moon tiles. */
private static final String MOON_MAP_URL_FORMAT =
"https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw/%d/%d/%d.jpg";
"http://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw/%d/%d/%d.jpg";
private TileOverlay mMoonTiles;
private SeekBar mTransparencyBar;
@ -116,4 +109,4 @@ public class TileOverlayDemoActivity extends AppCompatActivity
mMoonTiles.setTransparency((float) progress / (float) TRANSPARENCY_MAX);
}
}
}
}

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -19,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.example.mapdemo;
import com.google.android.libraries.maps.GoogleMap;
@ -29,11 +24,10 @@ import com.google.android.libraries.maps.UiSettings;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;

View File

@ -1,10 +1,3 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -32,14 +25,13 @@ import com.google.android.libraries.maps.model.MarkerOptions;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
/**
* This shows how to use setPadding to allow overlays that obscure part of the map without
* obscuring the map UI or copyright notices.

View File

@ -0,0 +1,81 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.anim;
import android.os.Handler;
import android.os.Looper;
/** Simple manager for UI-thread animation. All methods must be invoked on the UI thread only. */
public class AnimationManager {
private static final double INITIAL_FRAME_RATE_FPS = 60.0;
private final Handler animationHandler;
private final Runnable animationRunnable;
private double frameRateFps;
private boolean running;
public AnimationManager(final Runnable frameRunnable) {
frameRateFps = INITIAL_FRAME_RATE_FPS;
running = false;
animationHandler = new Handler(Looper.getMainLooper());
animationRunnable =
() -> {
if (!running) {
return;
}
frameRunnable.run();
requestAnimationFrame();
};
}
private void requestAnimationFrame() {
if (frameRateFps <= 0.0) {
return;
}
long delayMs = (long) Math.floor(1000.0 / frameRateFps);
animationHandler.postDelayed(animationRunnable, delayMs);
}
public void startAnimation() {
if (running) {
return;
}
requestAnimationFrame();
running = true;
}
public void stopAnimation() {
if (!running) {
return;
}
animationHandler.removeCallbacks(animationRunnable);
running = false;
}
public void setFrameRateFps(double frameRateFps) {
this.frameRateFps = frameRateFps;
}
public double getFrameRateFps() {
return frameRateFps;
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.model;
import com.google.android.libraries.maps.model.LatLng;
import java.util.ArrayList;
import java.util.List;
/**
* Helper to translate all given LatLngs by the same amount in one of the predefined directions.
*/
public enum MoveDirection {
UP(1, 0),
DOWN(-1, 0),
LEFT(0, -1),
RIGHT(0, 1);
private final int numLatSteps;
private final int numLngSteps;
MoveDirection(int numLatSteps, int numLngSteps) {
this.numLatSteps = numLatSteps;
this.numLngSteps = numLngSteps;
}
public double getLatDistance(double stepSizeDeg) {
return numLatSteps * stepSizeDeg;
}
public double getLngDistance(double stepSizeDeg) {
return numLngSteps * stepSizeDeg;
}
private static LatLng movePoint(LatLng oldPoint, double latMoveDistance,
double lngMoveDistance) {
return new LatLng(oldPoint.latitude + latMoveDistance,
oldPoint.longitude + lngMoveDistance);
}
public static List<LatLng> movePointsInList(
List<LatLng> oldPoints, double latMoveDistance, double lngMoveDistance) {
List<LatLng> newPoints = new ArrayList<>(oldPoints.size());
for (LatLng oldPoint : oldPoints) {
newPoints.add(movePoint(oldPoint, latMoveDistance, lngMoveDistance));
}
return newPoints;
}
public static List<List<LatLng>> movePointsInNestedList(
List<List<LatLng>> oldPointLists, double latMoveDistance, double lngMoveDistance) {
List<List<LatLng>> newPointLists = new ArrayList<>(oldPointLists.size());
for (List<LatLng> oldPointList : oldPointLists) {
newPointLists.add(movePointsInList(oldPointList, latMoveDistance, lngMoveDistance));
}
return newPointLists;
}
}

View File

@ -0,0 +1,168 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import com.example.mapdemo.R;
import com.google.android.libraries.maps.model.BitmapDescriptorFactory;
import com.google.android.libraries.maps.model.ButtCap;
import com.google.android.libraries.maps.model.Cap;
import com.google.android.libraries.maps.model.CustomCap;
import com.google.android.libraries.maps.model.RoundCap;
import com.google.android.libraries.maps.model.SquareCap;
import java.util.HashMap;
import java.util.Map;
/**
* Fragment with "cap" UI controls for Polylines, to be used in ViewPager.
*/
public class PolylineCapControlFragment extends PolylineControlFragment implements
OnCheckedChangeListener {
// We require Ook's refWidth > chevron's refWidth so isOok(CustomCap) can distinguish
// between the two CustomCaps by simple comparison of CustomCap.getBitmapRefWidth() against
// CHEVRON_VERSUS_OOK_REF_WIDTH_THRESHOLD, for the purpose of refreshing "cap" UI radio
// buttons. See isOok() for details on why this is necessary.
private static final float CHEVRON_REF_WIDTH = 15.0f;
private static final float OOK_REF_WIDTH = 32.0f;
private static final float CHEVRON_VERSUS_OOK_REF_WIDTH_THRESHOLD =
0.5f * (CHEVRON_REF_WIDTH + OOK_REF_WIDTH);
private final Map<Integer, Cap> radioIdToStartCap = new HashMap<>();
private final Map<Integer, Cap> radioIdToEndCap = new HashMap<>();
private RadioGroup startCapRadioGroup;
private RadioGroup endCapRadioGroup;
public PolylineCapControlFragment() {
radioIdToStartCap.put(R.id.start_cap_radio_butt, new ButtCap());
radioIdToStartCap.put(R.id.start_cap_radio_square, new SquareCap());
radioIdToStartCap.put(R.id.start_cap_radio_round, new RoundCap());
radioIdToStartCap.put(
R.id.start_cap_radio_custom_chevron,
new CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.chevron),
CHEVRON_REF_WIDTH));
radioIdToStartCap.put(
R.id.start_cap_radio_custom_ook,
new CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.ook), OOK_REF_WIDTH));
radioIdToEndCap.put(R.id.end_cap_radio_butt, new ButtCap());
radioIdToEndCap.put(R.id.end_cap_radio_square, new SquareCap());
radioIdToEndCap.put(R.id.end_cap_radio_round, new RoundCap());
radioIdToEndCap.put(
R.id.end_cap_radio_custom_chevron,
new CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.chevron),
CHEVRON_REF_WIDTH));
radioIdToEndCap.put(
R.id.end_cap_radio_custom_ook,
new CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.ook), OOK_REF_WIDTH));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_cap_control_fragment, container, false);
startCapRadioGroup = view.findViewById(R.id.start_cap_radio);
endCapRadioGroup = view.findViewById(R.id.end_cap_radio);
startCapRadioGroup.setOnCheckedChangeListener(this);
endCapRadioGroup.setOnCheckedChangeListener(this);
return view;
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (polyline == null) {
return;
}
int groupId = group.getId();
if (groupId == R.id.start_cap_radio) {
Cap startCap = radioIdToStartCap.get(checkedId);
if (startCap != null) {
polyline.setStartCap(startCap);
}
} else if (groupId == R.id.end_cap_radio) {
Cap endCap = radioIdToEndCap.get(checkedId);
if (endCap != null) {
polyline.setEndCap(endCap);
}
}
}
@Override
public void refresh() {
if (polyline == null) {
startCapRadioGroup.clearCheck();
for (int i = 0; i < startCapRadioGroup.getChildCount(); i++) {
startCapRadioGroup.getChildAt(i).setEnabled(false);
}
endCapRadioGroup.clearCheck();
for (int i = 0; i < endCapRadioGroup.getChildCount(); i++) {
endCapRadioGroup.getChildAt(i).setEnabled(false);
}
return;
}
for (int i = 0; i < startCapRadioGroup.getChildCount(); i++) {
startCapRadioGroup.getChildAt(i).setEnabled(true);
}
Cap startCap = polyline.getStartCap();
if (startCap instanceof ButtCap) {
startCapRadioGroup.check(R.id.start_cap_radio_butt);
} else if (startCap instanceof SquareCap) {
startCapRadioGroup.check(R.id.start_cap_radio_square);
} else if (startCap instanceof RoundCap) {
startCapRadioGroup.check(R.id.start_cap_radio_round);
} else if (startCap instanceof CustomCap) {
startCapRadioGroup.check(
isOok((CustomCap) startCap)
? R.id.start_cap_radio_custom_ook
: R.id.start_cap_radio_custom_chevron);
} else {
startCapRadioGroup.clearCheck();
}
for (int i = 0; i < endCapRadioGroup.getChildCount(); i++) {
endCapRadioGroup.getChildAt(i).setEnabled(true);
}
Cap endCap = polyline.getEndCap();
if (endCap instanceof ButtCap) {
endCapRadioGroup.check(R.id.end_cap_radio_butt);
} else if (endCap instanceof SquareCap) {
endCapRadioGroup.check(R.id.end_cap_radio_square);
} else if (endCap instanceof RoundCap) {
endCapRadioGroup.check(R.id.end_cap_radio_round);
} else if (endCap instanceof CustomCap) {
endCapRadioGroup.check(
isOok((CustomCap) endCap)
? R.id.end_cap_radio_custom_ook
: R.id.end_cap_radio_custom_chevron);
} else {
endCapRadioGroup.clearCheck();
}
}
private static boolean isOok(CustomCap customCap) {
return (customCap.refWidth >= CHEVRON_VERSUS_OOK_REF_WIDTH_THRESHOLD);
}
}

View File

@ -0,0 +1,104 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.example.mapdemo.R;
/** Fragment with "color" UI controls for Polylines, to be used in ViewPager. */
public class PolylineColorControlFragment extends PolylineControlFragment implements OnSeekBarChangeListener {
private static final int HUE_MAX = 359;
private static final int ALPHA_MAX = 255;
private SeekBar alphaBar;
private SeekBar hueBar;
private TextView argbTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_color_control_fragment, container, false);
alphaBar = view.findViewById(R.id.alphaSeekBar);
alphaBar.setMax(ALPHA_MAX);
alphaBar.setOnSeekBarChangeListener(this);
hueBar = view.findViewById(R.id.hueSeekBar);
hueBar.setMax(HUE_MAX);
hueBar.setOnSeekBarChangeListener(this);
argbTextView = (TextView) view.findViewById(R.id.argbTextView);
return view;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (polyline == null || !fromUser) {
return;
}
if (seekBar == hueBar) {
polyline.setColor(
Color.HSVToColor(Color.alpha(polyline.getColor()), new float[] {progress, 1, 1}));
} else if (seekBar == alphaBar) {
float[] prevHSV = new float[3];
Color.colorToHSV(polyline.getColor(), prevHSV);
polyline.setColor(Color.HSVToColor(progress, prevHSV));
}
argbTextView.setText(String.format("0x%08X", polyline.getColor()));
}
@Override
public void refresh() {
if (polyline == null) {
alphaBar.setEnabled(false);
alphaBar.setProgress(0);
hueBar.setEnabled(false);
hueBar.setProgress(0);
argbTextView.setText("");
return;
}
int color = polyline.getColor();
alphaBar.setEnabled(true);
alphaBar.setProgress(Color.alpha(color));
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hueBar.setEnabled(true);
hueBar.setProgress((int) hsv[0]);
argbTextView.setText(String.format("0x%08X", color));
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import androidx.fragment.app.Fragment;
import com.google.android.libraries.maps.model.Polyline;
public abstract class PolylineControlFragment extends Fragment {
protected Polyline polyline;
public void setPolyline(Polyline polyline) {
this.polyline = polyline;
refresh();
}
public abstract void refresh();
}

View File

@ -0,0 +1,109 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.HashMap;
import java.util.Map;
public class PolylineControlFragmentPagerAdapter extends FragmentPagerAdapter {
private static final int NUM_ITEMS = 8;
private final Map<Integer, PolylineControlFragment> positionsToFragments;
private final boolean isLiteMode;
public PolylineControlFragmentPagerAdapter(FragmentManager fragmentManager, boolean isLiteMode) {
super(fragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
positionsToFragments = new HashMap<>();
this.isLiteMode = isLiteMode;
}
@Override
public int getCount() {
return NUM_ITEMS;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
PolylineControlFragment fragment =
(PolylineControlFragment) super.instantiateItem(container, position);
positionsToFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
positionsToFragments.remove(position);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new PolylineColorControlFragment();
case 1:
return new PolylineWidthControlFragment();
case 2:
return new PolylineCapControlFragment();
case 3:
return new PolylineJointControlFragment();
case 4:
return new PolylinePatternControlFragment();
case 5:
return new PolylinePointsControlFragment();
case 6:
return PolylineSpansControlFragment.newInstance(isLiteMode);
case 7:
return new PolylineOtherOptionsControlFragment();
default:
return new Fragment();
}
}
@Override
public CharSequence getPageTitle(int position) {
// Ideally these strings should be localised, but let's not bother for a demo app.
switch (position) {
case 0:
return "Color";
case 1:
return "Width";
case 2:
return "Cap";
case 3:
return "Joint";
case 4:
return "Pattern";
case 5:
return "Points";
case 6:
return "Spans";
case 7:
return "Other Options";
default:
return null;
}
}
public PolylineControlFragment getFragmentAtPosition(int position) {
return positionsToFragments.get(position);
}
}

View File

@ -0,0 +1,215 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
import com.example.mapdemo.R;
import com.google.android.libraries.maps.CameraUpdateFactory;
import com.google.android.libraries.maps.GoogleMap;
import com.google.android.libraries.maps.GoogleMap.OnPolylineClickListener;
import com.google.android.libraries.maps.OnMapReadyCallback;
import com.google.android.libraries.maps.SupportMapFragment;
import com.google.android.libraries.maps.model.Dash;
import com.google.android.libraries.maps.model.Dot;
import com.google.android.libraries.maps.model.Gap;
import com.google.android.libraries.maps.model.LatLng;
import com.google.android.libraries.maps.model.Polyline;
import com.google.android.libraries.maps.model.PolylineOptions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* This shows how to apply multiple colors on a polyline.
*/
public class PolylineDemoActivity extends AppCompatActivity implements
OnMapReadyCallback, OnPageChangeListener, OnCheckedChangeListener, OnPolylineClickListener {
public static final String TAG = PolylineDemoActivity.class.getSimpleName();
private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298);
private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
private static final LatLng ADELAIDE = new LatLng(-34.92873, 138.59995);
private static final LatLng PERTH = new LatLng(-31.95285, 115.85734);
private static final LatLng LONDON = new LatLng(51.471547, -0.460052);
private static final LatLng LOS_ANGELES = new LatLng(33.936524, -118.377686);
private static final LatLng NEW_YORK = new LatLng(40.641051, -73.777485);
private static final LatLng AUCKLAND = new LatLng(-37.006254, 174.783018);
private Polyline australiaPolyline;
private Polyline melbournePolyline;
private Polyline sydneyPolyline;
private Polyline worldPolyline;
private Polyline selectedPolyline;
private ViewPager pager; // TODO use ViewPager2
private PolylineControlFragmentPagerAdapter pagerAdapter;
private RadioGroup polylineRadio;
private final Set<Polyline> spanResetPolylines = new HashSet<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.polyline_demo);
pagerAdapter =
new PolylineControlFragmentPagerAdapter(
getSupportFragmentManager(), /* isLiteMode= */ false);
pager = findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
// onPageSelected(0) isn't invoked once views are ready, so post a Runnable to
// refreshControlPanel() for the first time instead...
pager.post(this::refreshControlPanel);
polylineRadio = findViewById(R.id.polyline_radio);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap map) {
// For accessibility mode. Ideally this string would be localised.
map.setContentDescription("Google Map with polylines.");
// Non-loop polyline that goes past Australian cities. Added before sydneyPolyline and would
// normally be underneath, but increase Z-Index so that this line is on top.
australiaPolyline =
map.addPolyline(
new PolylineOptions()
.add(PERTH, ADELAIDE, SYDNEY, MELBOURNE)
.pattern(Arrays.asList(new Dot(), new Gap(20.0f)))
.color(Color.MAGENTA)
.zIndex(1));
// Geodesic polyline that goes around the world.
worldPolyline =
map.addPolyline(
new PolylineOptions()
.add(LONDON, AUCKLAND, LOS_ANGELES, NEW_YORK, LONDON)
.width(5)
.color(Color.BLUE)
.geodesic(true)
.clickable(true));
// Loop polyline centered at Sydney.
int radius = 4;
sydneyPolyline =
map.addPolyline(
new PolylineOptions()
.add(new LatLng(SYDNEY.latitude + radius, SYDNEY.longitude + radius))
.add(new LatLng(SYDNEY.latitude + radius, SYDNEY.longitude - radius))
.add(new LatLng(SYDNEY.latitude - radius, SYDNEY.longitude - radius))
.add(new LatLng(SYDNEY.latitude - radius, SYDNEY.longitude))
.add(new LatLng(SYDNEY.latitude - radius, SYDNEY.longitude + radius))
.add(new LatLng(SYDNEY.latitude + radius, SYDNEY.longitude + radius))
.pattern(Arrays.asList(new Dash(45.0f), new Gap(10.0f)))
.color(Color.RED)
.width(5)
.clickable(true));
// Create Melbourne polyline to show layering of polylines with same Z-Index. This is added
// second so it will be layered on top of the Sydney polyline (both have Z-Index == 0).
melbournePolyline =
map.addPolyline(
new PolylineOptions()
.add(new LatLng(MELBOURNE.latitude + radius, MELBOURNE.longitude + radius))
.add(new LatLng(MELBOURNE.latitude + radius, MELBOURNE.longitude - radius))
.add(new LatLng(MELBOURNE.latitude - radius, MELBOURNE.longitude - radius))
.add(new LatLng(MELBOURNE.latitude - radius, MELBOURNE.longitude))
.add(new LatLng(MELBOURNE.latitude - radius, MELBOURNE.longitude + radius))
.add(new LatLng(MELBOURNE.latitude + radius, MELBOURNE.longitude + radius))
.color(Color.GREEN)
.width(5)
.clickable(true));
map.moveCamera(CameraUpdateFactory.newLatLng(SYDNEY));
selectedPolyline = australiaPolyline;
polylineRadio.check(R.id.polyline_radio_australia);
pager.addOnPageChangeListener(this);
polylineRadio.setOnCheckedChangeListener(this);
map.setOnPolylineClickListener(this);
}
@Override
public void onPolylineClick(Polyline polyline) {
// Flip the values of the r, g and b components of the polyline's color.
int strokeColor = polyline.getColor() ^ 0x00ffffff;
polyline.setColor(strokeColor);
polyline.setSpans(new ArrayList<>());
spanResetPolylines.add(polyline);
refreshControlPanel();
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.polyline_radio_australia) {
selectedPolyline = australiaPolyline;
} else if (checkedId == R.id.polyline_radio_sydney) {
selectedPolyline = sydneyPolyline;
} else if (checkedId == R.id.polyline_radio_melbourne) {
selectedPolyline = melbournePolyline;
} else if (checkedId == R.id.polyline_radio_world) {
selectedPolyline = worldPolyline;
}
refreshControlPanel();
}
@Override
public void onPageSelected(int position) {
refreshControlPanel();
}
private void refreshControlPanel() {
PolylineControlFragment fragment = pagerAdapter.getFragmentAtPosition(pager.getCurrentItem());
if (fragment != null) {
if (fragment instanceof PolylineSpansControlFragment
&& spanResetPolylines.contains(selectedPolyline)) {
PolylineSpansControlFragment spansControlFragment = (PolylineSpansControlFragment) fragment;
spansControlFragment.resetSpanState(selectedPolyline);
spanResetPolylines.remove(selectedPolyline);
}
fragment.setPolyline(selectedPolyline);
}
}
@Override
public void onPageScrollStateChanged(int state) {
// Don't do anything here.
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Don't do anything here.
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import com.example.mapdemo.R;
import com.google.android.libraries.maps.model.JointType;
import java.util.HashMap;
import java.util.Map;
/**
* Fragment with "joint" UI controls for Polylines, to be used in ViewPager.
*/
public class PolylineJointControlFragment extends PolylineControlFragment implements
OnCheckedChangeListener {
private final Map<Integer, Integer> radioIdToJointType = new HashMap<>();
private RadioGroup jointRadioGroup;
public PolylineJointControlFragment() {
radioIdToJointType.put(R.id.joint_radio_default, JointType.DEFAULT);
radioIdToJointType.put(R.id.joint_radio_bevel, JointType.BEVEL);
radioIdToJointType.put(R.id.joint_radio_round, JointType.ROUND);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_joint_control_fragment, container, false);
jointRadioGroup = view.findViewById(R.id.joint_radio);
jointRadioGroup.setOnCheckedChangeListener(this);
return view;
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (polyline == null) {
return;
}
Integer jointType = radioIdToJointType.get(checkedId);
if (jointType != null) {
polyline.setJointType(jointType);
}
}
@Override
public void refresh() {
if (polyline == null) {
jointRadioGroup.clearCheck();
for (int i = 0; i < jointRadioGroup.getChildCount(); i++) {
jointRadioGroup.getChildAt(i).setEnabled(false);
}
return;
}
for (int i = 0; i < jointRadioGroup.getChildCount(); i++) {
jointRadioGroup.getChildAt(i).setEnabled(true);
}
switch (polyline.getJointType()) {
case JointType.DEFAULT:
jointRadioGroup.check(R.id.joint_radio_default);
break;
case JointType.BEVEL:
jointRadioGroup.check(R.id.joint_radio_bevel);
break;
case JointType.ROUND:
jointRadioGroup.check(R.id.joint_radio_round);
break;
default:
jointRadioGroup.clearCheck();
}
}
}

View File

@ -0,0 +1,54 @@
package com.example.mapdemo.polyline;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import com.example.mapdemo.R;
/**
* Fragment with clickability, geodesic, and visibility UI controls for Polylines, to be used in
* ViewPager.
*/
public class PolylineOtherOptionsControlFragment extends PolylineControlFragment
implements View.OnClickListener {
private CheckBox clickabilityCheckBox;
private CheckBox geodesicCheckBox;
private CheckBox visibilityCheckBox;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_other_options_control_fragment, container, false);
clickabilityCheckBox = view.findViewById(R.id.clickabilityCheckBox);
clickabilityCheckBox.setOnClickListener(this);
geodesicCheckBox = view.findViewById(R.id.geodesicCheckBox);
geodesicCheckBox.setOnClickListener(this);
visibilityCheckBox = view.findViewById(R.id.visibilityCheckBox);
visibilityCheckBox.setOnClickListener(this);
return view;
}
@Override
public void onClick(View view) {
if (polyline == null) {
return;
}
if (view == clickabilityCheckBox) {
polyline.setClickable(clickabilityCheckBox.isChecked());
} else if (view == geodesicCheckBox) {
polyline.setGeodesic(geodesicCheckBox.isChecked());
} else if (view == visibilityCheckBox) {
polyline.setVisible(visibilityCheckBox.isChecked());
}
}
@Override
public void refresh() {
clickabilityCheckBox.setChecked((polyline != null) && polyline.isClickable());
geodesicCheckBox.setChecked((polyline != null) && polyline.isGeodesic());
visibilityCheckBox.setChecked((polyline != null) && polyline.isVisible());
}
}

View File

@ -0,0 +1,133 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.example.mapdemo.R;
import com.google.android.libraries.maps.model.Dash;
import com.google.android.libraries.maps.model.Dot;
import com.google.android.libraries.maps.model.Gap;
import com.google.android.libraries.maps.model.PatternItem;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/** Fragment with "pattern" UI controls for Polylines, to be used in ViewPager. */
public class PolylinePatternControlFragment extends PolylineControlFragment implements
OnClickListener {
private static final int MAX_PATTERN_SIZE = 6;
private static final int MAX_DASH_LENGTH = 200;
private static final int MAX_GAP_LENGTH = 100;
private static final Random RANDOM = new Random();
private Button patternSolidBtn;
private Button patternDottedBtn;
private Button patternDashedBtn;
private Button patternMixedBtn;
private TextView patternTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_pattern_control_fragment, container, false);
patternTextView = view.findViewById(R.id.patternTextView);
patternSolidBtn = view.findViewById(R.id.patternSolidBtn);
patternDottedBtn = view.findViewById(R.id.patternDottedBtn);
patternDashedBtn = view.findViewById(R.id.patternDashedBtn);
patternMixedBtn = view.findViewById(R.id.patternMixedBtn);
patternSolidBtn.setOnClickListener(this);
patternDottedBtn.setOnClickListener(this);
patternDashedBtn.setOnClickListener(this);
patternMixedBtn.setOnClickListener(this);
return view;
}
@Override
public void onClick(View view) {
if (polyline == null) {
return;
}
int id = view.getId();
List<PatternItem> pattern;
if (id == R.id.patternSolidBtn) {
pattern = null;
} else if (id == R.id.patternDottedBtn) {
pattern = Arrays.asList(new Dot(), new Gap(RANDOM.nextFloat() * MAX_GAP_LENGTH));
} else if (id == R.id.patternDashedBtn) {
pattern =
Arrays.asList(
new Dash(RANDOM.nextFloat() * MAX_DASH_LENGTH),
new Gap(RANDOM.nextFloat() * MAX_GAP_LENGTH));
} else if (id == R.id.patternMixedBtn) {
int size = 2 * (1 + RANDOM.nextInt(MAX_PATTERN_SIZE / 2));
pattern = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
if ((i % 2) == 0) {
pattern.add(
RANDOM.nextBoolean() ? new Dot() : new Dash(RANDOM.nextFloat() * MAX_DASH_LENGTH));
} else {
pattern.add(new Gap(RANDOM.nextFloat() * MAX_GAP_LENGTH));
}
}
} else {
throw new IllegalStateException("Unknown button");
}
polyline.setPattern(pattern);
patternTextView.setText(toString(pattern));
}
@Override
public void refresh() {
boolean enabled = (polyline != null);
patternSolidBtn.setEnabled(enabled);
patternDottedBtn.setEnabled(enabled);
patternDashedBtn.setEnabled(enabled);
patternMixedBtn.setEnabled(enabled);
patternTextView.setText((polyline == null) ? "" : toString(polyline.getPattern()));
}
private static String toString(List<PatternItem> pattern) {
if (pattern == null) {
return "<SOLID>";
}
StringBuilder sb = new StringBuilder("");
for (PatternItem item : pattern) {
if (item instanceof Dot) {
sb.append("DOT");
} else if (item instanceof Dash) {
sb.append(String.format("%.1fpx-DASH", ((Dash) item).length));
} else if (item instanceof Gap) {
sb.append(String.format("%.1fpx-GAP", ((Gap) item).length));
}
sb.append(" ");
}
sb.append("<repeat>");
return sb.toString();
}
}

View File

@ -0,0 +1,169 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import com.example.mapdemo.R;
import com.example.mapdemo.anim.AnimationManager;
import com.example.mapdemo.model.MoveDirection;
import com.google.android.libraries.maps.model.LatLng;
import java.util.List;
/** Fragment with "points" UI controls for Polylines, to be used in ViewPager. */
public class PolylinePointsControlFragment extends PolylineControlFragment implements View.OnTouchListener, View.OnFocusChangeListener, TextView.OnEditorActionListener {
private MoveDirection moveDirection;
private double stepSizeDeg;
private List<LatLng> originalPoints;
private double latDistance = 0;
private double lngDistance = 0;
private final AnimationManager animationManager =
new AnimationManager(
new Runnable() {
@Override
public void run() {
if ((polyline == null) || (moveDirection == null)) {
return;
}
// When the polyline moves offscreen, its coordinates will be clamped and caused the
// shape to change. Using the original points for computing new points to make sure
// the shape can be retained after the polyline moves offscreen.
latDistance += moveDirection.getLatDistance(stepSizeDeg);
lngDistance += moveDirection.getLngDistance(stepSizeDeg);
polyline.setPoints(
MoveDirection.movePointsInList(originalPoints, latDistance, lngDistance));
}
});
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_points_control_fragment, container, false);
view.findViewById(R.id.move_up).setOnTouchListener(this);
view.findViewById(R.id.move_down).setOnTouchListener(this);
view.findViewById(R.id.move_left).setOnTouchListener(this);
view.findViewById(R.id.move_right).setOnTouchListener(this);
EditText fpsEditText = (EditText) view.findViewById(R.id.fps_edittext);
fpsEditText.setOnEditorActionListener(this);
fpsEditText.setOnFocusChangeListener(this);
setFrameRate(fpsEditText);
EditText stepEditText = (EditText) view.findViewById(R.id.step_edittext);
stepEditText.setOnEditorActionListener(this);
stepEditText.setOnFocusChangeListener(this);
setStepSize(stepEditText);
moveDirection = null;
return view;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
setMoveDirection(view.getId());
animationManager.startAnimation();
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
moveDirection = null;
animationManager.stopAnimation();
return true;
default:
return false;
}
}
private void setMoveDirection(int buttonId) {
if (buttonId == R.id.move_up) {
moveDirection = MoveDirection.UP;
} else if (buttonId == R.id.move_down) {
moveDirection = MoveDirection.DOWN;
} else if (buttonId == R.id.move_left) {
moveDirection = MoveDirection.LEFT;
} else if (buttonId == R.id.move_right) {
moveDirection = MoveDirection.RIGHT;
} else {
moveDirection = null;
}
}
@Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent event) {
// Only handle "Done" action triggered by the user tapping "Enter" on the keyboard.
if (actionId != EditorInfo.IME_ACTION_DONE) {
return false;
}
int textViewId = textView.getId();
if (textViewId == R.id.fps_edittext) {
setFrameRate(textView);
} else if (textViewId == R.id.step_edittext) {
setStepSize(textView);
}
return false;
}
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
return;
}
int viewId = view.getId();
if (viewId == R.id.fps_edittext) {
setFrameRate((TextView) view);
} else if (viewId == R.id.step_edittext) {
setStepSize((TextView) view);
}
}
private void setFrameRate(TextView textView) {
String newValue = String.valueOf(textView.getText());
try {
animationManager.setFrameRateFps(Double.parseDouble(newValue));
} catch (NumberFormatException e) {
textView.setText(Double.toString(animationManager.getFrameRateFps()));
}
}
private void setStepSize(TextView textView) {
String newValue = String.valueOf(textView.getText());
try {
stepSizeDeg = Double.parseDouble(newValue);
} catch (NumberFormatException e) {
textView.setText(Double.toString(stepSizeDeg));
}
}
@Override
public void refresh() {
latDistance = 0;
lngDistance = 0;
originalPoints = polyline.getPoints();
}
}

View File

@ -0,0 +1,207 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import com.example.mapdemo.R;
import com.google.android.libraries.maps.model.BitmapDescriptorFactory;
import com.google.android.libraries.maps.model.Polyline;
import com.google.android.libraries.maps.model.StrokeStyle;
import com.google.android.libraries.maps.model.StyleSpan;
import com.google.android.libraries.maps.model.TextureStyle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Fragment with span count UI controls for {@link com.google.android.libraries.maps.model.Polyline}, to
* be used in ViewPager.
*
* <p>When span count is updated from the slider, the selected polyline will be updated with that
* number of spans. Each span will either have polyline color or the inverted color, and span
* lengths are equally divided by number of segments in the polyline.
*/
public class PolylineSpansControlFragment extends PolylineControlFragment
implements SeekBar.OnSeekBarChangeListener, RadioGroup.OnCheckedChangeListener {
private static final String IS_LITE_MODE_KEY = "isLiteMode";
private static final int SPAN_COUNT_MAX = 20;
private SeekBar spanCountBar;
private TextView spanCountTextView;
private CompoundButton gradientToggle;
private int spanCount = 0;
private final Map<Polyline, Integer> polylineSpanCounts = new HashMap<>();
private final Map<Polyline, Boolean> polylineGradientStates = new HashMap<>();
private boolean isLiteMode = false;
private int selectedStampStyleId;
private RadioGroup polylineStampStyleRadioGroup;
static PolylineSpansControlFragment newInstance(boolean isLiteMode) {
PolylineSpansControlFragment polylineSpansControlFragment = new PolylineSpansControlFragment();
Bundle args = new Bundle();
args.putBoolean(IS_LITE_MODE_KEY, isLiteMode);
polylineSpansControlFragment.setArguments(args);
return polylineSpansControlFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isLiteMode = getArguments().getBoolean(IS_LITE_MODE_KEY);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_spans_control_fragment, container, false);
spanCountBar = view.findViewById(R.id.spansSeekBar);
spanCountBar.setMax(SPAN_COUNT_MAX);
spanCountBar.setOnSeekBarChangeListener(this);
spanCountTextView = view.findViewById(R.id.spansTextView);
gradientToggle = view.findViewById(R.id.gradientToggle);
gradientToggle.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
polylineGradientStates.put(polyline, isChecked);
updateSpans();
});
polylineStampStyleRadioGroup = view.findViewById(R.id.polyline_stamp_style_radio_group);
polylineStampStyleRadioGroup.setVisibility(View.INVISIBLE);
if (isLiteMode) {
gradientToggle.setVisibility(View.INVISIBLE);
polylineStampStyleRadioGroup.setVisibility(View.INVISIBLE);
}
polylineSpanCounts.clear();
polylineGradientStates.clear();
selectedStampStyleId = 0;
polylineStampStyleRadioGroup.setOnCheckedChangeListener(this);
return view;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
spanCount = progress;
polylineSpanCounts.put(polyline, spanCount);
spanCountTextView.setText(String.valueOf(spanCount));
updateSpans();
}
private List<StyleSpan> generateSpans(int count) {
int invertedPolylineColor = polyline.getColor() ^ 0x00ffffff;
List<StyleSpan> newSpans = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
int color = i % 2 == 0 ? polyline.getColor() : invertedPolylineColor;
double segmentCount = (double) (polyline.getPoints().size() - 1) / count;
StrokeStyle.Builder strokeStyleBuilder =
gradientToggle.isChecked()
? StrokeStyle.gradientBuilder(polyline.getColor(), invertedPolylineColor)
: StrokeStyle.colorBuilder(color);
if (selectedStampStyleId == R.id.polyline_texture_style) {
strokeStyleBuilder.stamp(
TextureStyle.newBuilder(BitmapDescriptorFactory.fromResource(R.drawable.ook))
.build());
}
newSpans.add(new StyleSpan(strokeStyleBuilder.build(), segmentCount));
}
return newSpans;
}
private void updateSpans() {
if (polyline == null) {
return;
}
polyline.setSpans(generateSpans(spanCount));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void refresh() {
if (polyline == null) {
spanCountBar.setEnabled(false);
spanCountBar.setProgress(0);
spanCountTextView.setText("");
gradientToggle.setChecked(false);
gradientToggle.setEnabled(false);
polylineStampStyleRadioGroup.clearCheck();
polylineStampStyleRadioGroup.setEnabled(false);
return;
}
if (!polylineSpanCounts.containsKey(polyline)) {
polylineSpanCounts.put(polyline, 0);
}
if (!polylineGradientStates.containsKey(polyline)) {
polylineGradientStates.put(polyline, false);
}
spanCountBar.setEnabled(true);
spanCountBar.setProgress(polylineSpanCounts.get(polyline));
spanCountTextView.setText(String.valueOf(polylineSpanCounts.get(polyline)));
if (!isLiteMode) {
gradientToggle.setEnabled(true);
gradientToggle.setChecked(polylineGradientStates.get(polyline));
polylineStampStyleRadioGroup.setEnabled(true);
polylineStampStyleRadioGroup.check(selectedStampStyleId);
}
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
selectedStampStyleId = checkedId;
updateSpans();
}
/**
* Resets the span states of a polyline.
*
* <p>Because there's no getter for polyline spans, this is needed for the polyline demo
* activity
* to update span control UI components.
*/
void resetSpanState(Polyline polyline) {
polylineSpanCounts.remove(polyline);
polylineGradientStates.remove(polyline);
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mapdemo.polyline;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import com.example.mapdemo.R;
/**
* Fragment with "width" UI controls for Polylines, to be used in ViewPager.
*/
public class PolylineWidthControlFragment extends PolylineControlFragment implements
SeekBar.OnSeekBarChangeListener {
private static final int WIDTH_MAX = 50;
private SeekBar widthBar;
private TextView widthTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
View view = inflater.inflate(R.layout.polyline_width_control_fragment, container, false);
widthBar = view.findViewById(R.id.widthSeekBar);
widthBar.setMax(WIDTH_MAX);
widthBar.setOnSeekBarChangeListener(this);
widthTextView = view.findViewById(R.id.widthTextView);
return view;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Don't do anything here.
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (polyline == null) {
return;
}
polyline.setWidth(progress);
widthTextView.setText(polyline.getWidth() + "px");
}
@Override
public void refresh() {
if (polyline == null) {
widthBar.setEnabled(false);
widthBar.setProgress(0);
widthTextView.setText("");
return;
}
widthBar.setEnabled(true);
float width = polyline.getWidth();
widthBar.setProgress((int) width);
widthTextView.setText(width + "px");
}
}

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/map"
class="com.google.android.libraries.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="47.6089945"
map:cameraTargetLng="-122.3410462"
map:cameraZoom="14"
map:mapId="@string/cloud_styling_basic_map_id" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#D000"
android:orientation="vertical"
android:padding="5dp">
<LinearLayout
android:id="@+id/cloud_styling_basic_demo_mode_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/styling_normal_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_normal_mode" />
<Button
android:id="@+id/styling_satellite_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_satellite_mode" />
<Button
android:id="@+id/styling_hybrid_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_hybrid_mode" />
<Button
android:id="@+id/styling_terrain_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_terrain_mode" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
class="com.google.android.libraries.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:scrollbarFadeDuration="0"
android:scrollbarSize="5dip">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stretchColumns="1">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/start_cap" />
<RadioGroup
android:id="@+id/start_cap_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:orientation="horizontal">
<RadioButton
android:id="@+id/start_cap_radio_butt"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_butt" />
<RadioButton
android:id="@+id/start_cap_radio_square"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_square" />
<RadioButton
android:id="@+id/start_cap_radio_round"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_round" />
<RadioButton
android:id="@+id/start_cap_radio_custom_chevron"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_custom_chevron" />
<RadioButton
android:id="@+id/start_cap_radio_custom_ook"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_custom_ook" />
</RadioGroup>
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/end_cap" />
<RadioGroup
android:id="@+id/end_cap_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:orientation="horizontal">
<RadioButton
android:id="@+id/end_cap_radio_butt"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_butt" />
<RadioButton
android:id="@+id/end_cap_radio_square"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_square" />
<RadioButton
android:id="@+id/end_cap_radio_round"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_round" />
<RadioButton
android:id="@+id/end_cap_radio_custom_chevron"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_custom_chevron" />
<RadioButton
android:id="@+id/end_cap_radio_custom_ook"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/cap_custom_ook" />
</RadioGroup>
</TableRow>
</TableLayout>
</HorizontalScrollView>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="1">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/hue" />
<SeekBar android:id="@+id/hueSeekBar" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/alpha" />
<SeekBar android:id="@+id/alphaSeekBar" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/argb" />
<TextView
android:id="@+id/argbTextView"
android:gravity="center" />
</TableRow>
</TableLayout>

View File

@ -1,118 +1,80 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TableLayout
android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="1">
<TableRow
android:layout_height="150dp"
android:layout_alignParentTop="true">
<!-- Hardcode layout_height because it's convoluted to work around a limitation of ViewPager to
make "wrap_content" works). Let's not bother for a demo app. -->
<androidx.viewpager.widget.PagerTitleStrip
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/hue" />
<SeekBar android:id="@+id/hueSeekBar" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/alpha" />
<SeekBar android:id="@+id/alphaSeekBar" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:text="@string/width" />
<SeekBar android:id="@+id/widthSeekBar" />
</TableRow>
</TableLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="@string/start_cap"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/startCapSpinner"
android:spinnerMode="dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@string/end_cap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Spinner
android:id="@+id/endCapSpinner"
android:spinnerMode="dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="@string/joint_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Spinner
android:id="@+id/jointTypeSpinner"
android:spinnerMode="dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@string/pattern"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Spinner
android:id="@+id/patternSpinner"
android:spinnerMode="dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<CheckBox
android:id="@+id/toggleClickability"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:onClick="toggleClickability"
android:text="@string/clickable" />
android:layout_gravity="top" />
</androidx.viewpager.widget.ViewPager>
<fragment
android:id="@+id/map"
class="com.google.android.libraries.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
android:layout_height="match_parent"
android:layout_above="@+id/scroll"
android:layout_below="@id/pager" />
<HorizontalScrollView
android:id="@id/scroll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:scrollbarSize="5dip">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/polyline_selection" />
<RadioGroup
android:id="@+id/polyline_radio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/polyline_radio_australia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/polyline_australia" />
<RadioButton
android:id="@+id/polyline_radio_sydney"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/polyline_sydney" />
<RadioButton
android:id="@+id/polyline_radio_melbourne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/polyline_melbourne" />
<RadioButton
android:id="@+id/polyline_radio_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/polyline_world" />
</RadioGroup>
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:scrollbarFadeDuration="0"
android:scrollbarSize="5dip">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<RadioGroup
android:id="@+id/joint_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:orientation="horizontal">
<RadioButton
android:id="@+id/joint_radio_default"
android:text="@string/joint_default" />
<RadioButton
android:id="@+id/joint_radio_bevel"
android:text="@string/joint_bevel" />
<RadioButton
android:id="@+id/joint_radio_round"
android:text="@string/joint_round" />
</RadioGroup>
</LinearLayout>
</HorizontalScrollView>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<CheckBox
android:id="@+id/clickabilityCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clickable" />
<CheckBox
android:id="@+id/geodesicCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/geodesic" />
<CheckBox
android:id="@+id/visibilityCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/visible" />
</LinearLayout>

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:scrollbarFadeDuration="0"
android:scrollbarSize="5dip">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/patternSolidBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="setPatternSolid"
android:text="@string/pattern_solid" />
<Button
android:id="@+id/patternDottedBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="setPatternDotted"
android:text="@string/pattern_dotted" />
<Button
android:id="@+id/patternDashedBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="setPatternDashed"
android:text="@string/pattern_dashed" />
<Button
android:id="@+id/patternMixedBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="setPatternMixed"
android:text="@string/pattern_mixed" />
</LinearLayout>
<TextView
android:id="@+id/patternTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</HorizontalScrollView>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:text="Frame rate:" />
<EditText
android:id="@+id/fps_edittext"
android:layout_height="wrap_content"
android:gravity="right"
android:imeOptions="actionDone"
android:inputType="numberDecimal"
android:minWidth="64dp"
android:text="60.0" />
<TextView android:text="fps" />
<TextView
android:minWidth="48dp"
android:visibility="invisible" />
<Button
android:id="@+id/move_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:text="@string/up_arrow" />
<TextView
android:minWidth="48dp"
android:visibility="invisible" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:text="LatLng step:" />
<EditText
android:id="@+id/step_edittext"
android:layout_height="wrap_content"
android:gravity="right"
android:imeOptions="actionDone"
android:inputType="numberDecimal"
android:minWidth="64dp"
android:text="0.05" />
<TextView android:text="\u00B0" />
<Button
android:id="@+id/move_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:text="@string/left_arrow" />
<Button
android:id="@+id/move_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:text="@string/down_arrow" />
<Button
android:id="@+id/move_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:text="@string/right_arrow" />
</TableRow>
</TableLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_horizontal|top"
android:singleLine="false"
android:text="HOLD\narrow\nto\nmove\npoly" />
</LinearLayout>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SeekBar
android:id="@+id/spansSeekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/spansTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ToggleButton
android:id="@+id/gradientToggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:textOff="@string/solid"
android:textOn="@string/gradient" />
<RadioGroup
android:id="@+id/polyline_stamp_style_radio_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/polyline_default_style"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/default_style" />
<RadioButton
android:id="@+id/polyline_texture_style"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/textured" />
</RadioGroup>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SeekBar
android:id="@+id/widthSeekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/widthTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" />
</LinearLayout>

View File

@ -29,7 +29,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignTop="@+id/streetviewpanorama"
android:layout_alignTop="@id/map"
android:padding="6dp"
android:background="@color/white"
android:orientation="vertical">

View File

@ -51,14 +51,17 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
gmsImplementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation 'androidx.multidex:multidex:2.0.1'
v3Implementation name:'maps-sdk-3.0.0-beta', ext:'aar'
// GMS
gmsImplementation 'com.google.android.gms:play-services-maps:17.0.0'
// V3
v3Implementation 'com.google.android.libraries.maps:maps:3.1.0-beta'
v3Implementation 'com.google.android.gms:play-services-basement:17.3.0'
v3Implementation 'com.google.android.gms:play-services-base:17.3.0'
v3Implementation 'com.google.android.gms:play-services-gcm:17.0.0'

View File

@ -48,11 +48,13 @@
<activity android:name=".CameraDemoActivity"/>
<activity android:name=".CircleDemoActivity" />
<activity android:name=".CloseInfoWindowDemoActivity" />
<activity android:name=".CloudBasedMapStylingDemoActivity" />
<activity android:name=".LayersDemoActivity"/>
<activity android:name=".LiteListDemoActivity" />
<activity android:name=".MarkerCollisionDemoActivity" />
<activity android:name=".MarkerDemoActivity"/>
<activity android:name=".polyline.PolylineDemoActivity" />
<activity android:name=".PolygonDemoActivity"/>
<activity android:name=".PolylineDemoActivity"/>
<activity android:name=".StreetViewPanoramaNavigationDemoActivity" />
<activity android:name=".TagsDemoActivity"/>
<activity android:name=".UiSettingsDemoActivity" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -151,21 +151,6 @@
<string name="stroke_pattern">Stroke Pattern</string>
<string name="stroke_width">Stroke Width</string>
<!-- Polylines Demo -->
<string name="alpha">Alpha</string>
<string name="cap_butt">Butt</string>
<string name="cap_image">Image</string>
<string name="cap_round">Round</string>
<string name="cap_square">Square</string>
<string name="end_cap">End Cap</string>
<string name="hue">Hue</string>
<string name="joint_type">Joint Type</string>
<string name="pattern">Pattern</string>
<string name="polyline_demo_description">Demonstrates how to add Polylines to a map</string>
<string name="polyline_demo_label">Polyline</string>
<string name="start_cap">Start Cap</string>
<string name="width">Width</string>
<!-- StreetView Panorama Navigation Demo -->
<string name="street_view_panorama_navigation_demo_label">Street View Panorama Navigation Demo</string>
<string name="street_view_panorama_navigation_demo_details">Street View Panorama with programmatic navigation</string>
@ -232,4 +217,50 @@
<string name="vr_opera_house_button">SOH</string>
<string name="vr_sfo_button">SFO</string>
<string name="vr_australia_button">AUS</string>
<!-- Cloud Styling -->
<string name="cloud_styling_basic_map_id">26a66b031807a453</string>
<string name="lite_styling_normal_mode">Normal</string>
<string name="lite_styling_satellite_mode">Satellite</string>
<string name="lite_styling_hybrid_mode">Hybrid</string>
<string name="lite_styling_terrain_mode">Terrain</string>
<string name="cloud_styling_label">Cloud Styling</string>
<string name="cloud_styling_description">Demonstrates how to use a simple map using Cloud Styling.</string>
<!-- Polylines Demo -->
<string name="alpha">Alpha</string>
<string name="cap_butt">Butt</string>
<string name="cap_image">Image</string>
<string name="cap_round">Round</string>
<string name="cap_square">Square</string>
<string name="end_cap">End Cap</string>
<string name="hue">Hue</string>
<string name="joint_type">Joint Type</string>
<string name="pattern">Pattern</string>
<string name="polyline_demo_description">Demonstrates how to add and configure Polylines to a map</string>
<string name="polyline_demo_label">Polyline</string>
<string name="start_cap">Start Cap</string>
<string name="width">Width</string>
<string name="polyline_selection">Select polyline</string>
<string name="polyline_sydney">Sydney</string>
<string name="polyline_melbourne">Melbourne</string>
<string name="polyline_australia">Australia</string>
<string name="polyline_world">World</string>
<string name="argb">ARGB</string>
<string name="cap_custom_chevron">Chevron</string>
<string name="cap_custom_ook">Ook</string>
<string name="joint_default">Default</string>
<string name="joint_bevel">Bevel</string>
<string name="joint_round">Round</string>
<string name="solid" desc="Label of a toggle button indicating that the selected polyline should have solid color.">Solid color</string>
<string name="gradient" desc="Label of a toggle button indicating that the selected polyline should have a color gradient.">Gradient color</string>
<string name="textured" desc="Label of a checkbox indicating whether or not the selected polyline has texture.">Textured</string>
<string name="point_sprite" desc="Label of a checkbox indicating whether or not the point sprite rendering technique is applied on textured polyline.">Point sprite</string>
<string name="default_style" desc="Label of a radio group indicating whether or not default style is applied.">Default</string>
<string name="geodesic">Geodesic</string>
<string name="visible">Visible</string>
<!-- Marker Collision -->
<string name="marker_collision_label">Marker Collision</string>
<string name="marker_collision_description">Demonstrates different supported marker collision behaviors.</string>
</resources>

View File

@ -0,0 +1,74 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.google.android.libraries.maps.GoogleMap
import com.google.android.libraries.maps.OnMapReadyCallback
import com.google.android.libraries.maps.SupportMapFragment
/**
* This shows how to use Cloud-based Map Styling in a simple Activity. For more information on how
* to style a map using this method, see:
* https://developers.google.com/maps/documentation/android-sdk/cloud-styling-android
*/
class CloudBasedMapStylingDemoActivity : AppCompatActivity(), OnMapReadyCallback {
private var map: GoogleMap? = null
private var currentMapType = GoogleMap.MAP_TYPE_NORMAL
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
currentMapType = savedInstanceState.getInt(MAP_TYPE_KEY)
}
// The underlying style the map will use has been set in the layout
// `cloud_styling_basic_demo` under the SupportMapFragment's `map:mapId` attribute.
setContentView(R.layout.cloud_styling_basic_demo)
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
mapFragment!!.getMapAsync(this)
setUpButtonListeners()
}
override fun onMapReady(map: GoogleMap) {
this.map = map
map.mapType = currentMapType
}
private fun setUpButtonListeners() {
findViewById<View>(R.id.styling_normal_mode).setOnClickListener { setMapType(GoogleMap.MAP_TYPE_NORMAL) }
findViewById<View>(R.id.styling_satellite_mode).setOnClickListener { setMapType(GoogleMap.MAP_TYPE_SATELLITE) }
findViewById<View>(R.id.styling_hybrid_mode).setOnClickListener { setMapType(GoogleMap.MAP_TYPE_HYBRID) }
findViewById<View>(R.id.styling_terrain_mode).setOnClickListener { setMapType(GoogleMap.MAP_TYPE_TERRAIN) }
}
private fun setMapType(mapType: Int) {
currentMapType = mapType
map?.mapType = mapType
}
companion object {
private const val MAP_TYPE_KEY = "map_type"
}
}

View File

@ -23,76 +23,49 @@
package com.example.kotlindemos
import com.example.kotlindemos.polyline.PolylineDemoActivity;
/**
* A list of all the demos we have available.
*/
class DemoDetailsList {
companion object {
val DEMOS = listOf<DemoDetails>(
DemoDetails(R.string.basic_demo_label, R.string.basic_demo_details,
BasicMapDemoActivity::class.java),
DemoDetails(R.string.camera_demo_label, R.string.camera_demo_description,
CameraDemoActivity::class.java),
DemoDetails(R.string.circle_demo_label, R.string.circle_demo_details,
CircleDemoActivity::class.java),
DemoDetails(R.string.close_info_window_demo_label,
R.string.close_info_window_demo_details,
CloseInfoWindowDemoActivity::class.java),
DemoDetails(
R.string.events_demo_label,
R.string.events_demo_details,
EventsDemoActivity::class.java),
DemoDetails(
R.string.ground_overlay_demo_label,
R.string.ground_overlay_demo_details,
GroundOverlayDemoActivity::class.java),
DemoDetails(R.string.indoor_demo_label, R.string.indoor_demo_details,
IndoorDemoActivity::class.java),
DemoDetails(R.string.layers_demo_label, R.string.layers_demo_description,
LayersDemoActivity::class.java),
DemoDetails(R.string.lite_demo_label, R.string.lite_demo_details,
LiteDemoActivity::class.java),
DemoDetails(R.string.lite_list_demo_label, R.string.lite_list_demo_details,
LiteListDemoActivity::class.java),
DemoDetails(R.string.markers_demo_label, R.string.markers_demo_description,
MarkerDemoActivity::class.java),
DemoDetails(R.string.my_location_demo_label, R.string.my_location_demo_details,
MyLocationDemoActivity::class.java),
DemoDetails(R.string.polygon_demo_label, R.string.polygon_demo_details,
PolygonDemoActivity::class.java),
DemoDetails(R.string.polyline_demo_label, R.string.polyline_demo_description,
PolylineDemoActivity::class.java),
DemoDetails(
R.string.street_view_panorama_basic_demo_label,
R.string.street_view_panorama_basic_demo_details,
StreetViewPanoramaBasicDemoActivity::class.java),
DemoDetails(
R.string.street_view_panorama_navigation_demo_label,
R.string.street_view_panorama_navigation_demo_details,
StreetViewPanoramaNavigationDemoActivity::class.java),
DemoDetails(
R.string.split_street_view_panorama_and_map_demo_label,
R.string.split_street_view_panorama_and_map_demo_details,
SplitStreetViewPanoramaAndMapDemoActivity::class.java),
DemoDetails(
R.string.street_view_panorama_options_demo_label,
R.string.street_view_panorama_options_demo_details,
StreetViewPanoramaOptionsDemoActivity::class.java),
DemoDetails(
R.string.street_view_panorama_events_demo_label,
R.string.street_view_panorama_events_demo_details,
StreetViewPanoramaEventsDemoActivity::class.java),
DemoDetails(
R.string.street_view_panorama_view_demo_label,
R.string.street_view_panorama_view_demo_details,
StreetViewPanoramaViewDemoActivity::class.java
),
DemoDetails(R.string.tags_demo_label, R.string.tags_demo_details,
TagsDemoActivity::class.java),
DemoDetails(R.string.ui_settings_demo_label, R.string.ui_settings_demo_details,
UiSettingsDemoActivity::class.java),
DemoDetails(R.string.region_demo_label, R.string.region_demo_details,
VisibleRegionDemoActivity::class.java)
DemoDetails(R.string.basic_demo_label, R.string.basic_demo_details,
BasicMapDemoActivity::class.java),
DemoDetails(R.string.camera_demo_label, R.string.camera_demo_description,
CameraDemoActivity::class.java),
DemoDetails(R.string.circle_demo_label, R.string.circle_demo_details,
CircleDemoActivity::class.java),
DemoDetails(R.string.close_info_window_demo_label,
R.string.close_info_window_demo_details,
CloseInfoWindowDemoActivity::class.java),
DemoDetails(R.string.cloud_styling_label,
R.string.cloud_styling_description,
CloudBasedMapStylingDemoActivity::class.java),
DemoDetails(R.string.layers_demo_label, R.string.layers_demo_description,
LayersDemoActivity::class.java),
DemoDetails(R.string.lite_list_demo_label, R.string.lite_list_demo_details,
LiteListDemoActivity::class.java),
DemoDetails(R.string.marker_collision_label,
R.string.marker_collision_description,
MarkerCollisionDemoActivity::class.java),
DemoDetails(R.string.markers_demo_label, R.string.markers_demo_description,
MarkerDemoActivity::class.java),
DemoDetails(R.string.polygon_demo_label, R.string.polygon_demo_details,
PolygonDemoActivity::class.java),
DemoDetails(R.string.polyline_demo_label, R.string.polyline_demo_description,
PolylineDemoActivity::class.java),
DemoDetails(
R.string.street_view_panorama_navigation_demo_label,
R.string.street_view_panorama_navigation_demo_details,
StreetViewPanoramaNavigationDemoActivity::class.java),
DemoDetails(R.string.tags_demo_label, R.string.tags_demo_details,
TagsDemoActivity::class.java),
DemoDetails(R.string.ui_settings_demo_label, R.string.ui_settings_demo_details,
UiSettingsDemoActivity::class.java),
DemoDetails(R.string.region_demo_label, R.string.region_demo_details,
VisibleRegionDemoActivity::class.java)
)
}
}

View File

@ -0,0 +1,85 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.google.android.libraries.maps.CameraUpdateFactory
import com.google.android.libraries.maps.GoogleMap
import com.google.android.libraries.maps.OnMapReadyCallback
import com.google.android.libraries.maps.SupportMapFragment
import com.google.android.libraries.maps.model.BitmapDescriptorFactory
import com.google.android.libraries.maps.model.LatLng
import com.google.android.libraries.maps.model.Marker
import com.google.android.libraries.maps.model.MarkerOptions
/** This shows how to set collision behavior for the marker. */
class MarkerCollisionDemoActivity : AppCompatActivity(), OnMapReadyCallback {
private var map: GoogleMap? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.marker_collision_demo)
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
mapFragment!!.getMapAsync(this)
}
override fun onMapReady(map: GoogleMap) {
this.map = map
addMarkersToMap()
map.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 3f))
}
private fun addMarkersToMap() {
val defaultMarkerOptions = MarkerOptions()
// Add 100 markers to the map.
for (i in 0..9) {
for (j in 0..9) {
defaultMarkerOptions
.position(LatLng(SYDNEY.latitude + i, SYDNEY.longitude - j))
.zIndex(i * 10 + j.toFloat())
.title("zIndex:" + (i * 10 + j))
.draggable(true)
if ((i + j) % 3 == 0) {
defaultMarkerOptions.icon(
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))
defaultMarkerOptions.collisionBehavior(
Marker.CollisionBehavior.OPTIONAL_AND_HIDES_LOWER_PRIORITY)
} else if ((i + j) % 3 == 1) {
defaultMarkerOptions.icon(
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))
defaultMarkerOptions.collisionBehavior(Marker.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL)
} else {
defaultMarkerOptions.icon(
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
defaultMarkerOptions.collisionBehavior(Marker.CollisionBehavior.REQUIRED)
}
map!!.addMarker(defaultMarkerOptions)
}
}
}
companion object {
private val SYDNEY = LatLng(-33.87365, 151.20689)
}
}

View File

@ -1,296 +0,0 @@
/**
* DO NOT EDIT THIS FILE.
*
* This source code was autogenerated from source code within the `app/src/gms` directory
* and is not intended for modifications. If any edits should be made, please do so in the
* corresponding file under the `app/src/gms` directory.
*/
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos
import com.google.android.libraries.maps.CameraUpdateFactory
import com.google.android.libraries.maps.GoogleMap
import com.google.android.libraries.maps.OnMapReadyCallback
import com.google.android.libraries.maps.SupportMapFragment
import com.google.android.libraries.maps.model.BitmapDescriptorFactory
import com.google.android.libraries.maps.model.ButtCap
import com.google.android.libraries.maps.model.Cap
import com.google.android.libraries.maps.model.CustomCap
import com.google.android.libraries.maps.model.Dash
import com.google.android.libraries.maps.model.Dot
import com.google.android.libraries.maps.model.Gap
import com.google.android.libraries.maps.model.JointType
import com.google.android.libraries.maps.model.LatLng
import com.google.android.libraries.maps.model.PatternItem
import com.google.android.libraries.maps.model.Polyline
import com.google.android.libraries.maps.model.PolylineOptions
import com.google.android.libraries.maps.model.RoundCap
import com.google.android.libraries.maps.model.SquareCap
import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.SeekBar
import android.widget.Spinner
import androidx.appcompat.app.AppCompatActivity
import java.util.Arrays
/**
* This shows how to draw polylines on a map.
*/
class PolylineDemoActivity :
AppCompatActivity(),
OnMapReadyCallback,
SeekBar.OnSeekBarChangeListener,
AdapterView.OnItemSelectedListener {
private val CUSTOM_CAP_IMAGE_REF_WIDTH_PX = 50
private val INITIAL_STROKE_WIDTH_PX = 5
private val MAX_WIDTH_PX = 100
private val MAX_HUE_DEGREES = 360
private val MAX_ALPHA = 255
private val PATTERN_DASH_LENGTH_PX = 50
private val PATTERN_GAP_LENGTH_PX = 20
// City locations for mutable polyline.
private val adelaideLatLng = LatLng(-34.92873, 138.59995)
private val darwinLatLng = LatLng(-12.4258647, 130.7932231)
private val melbourneLatLng = LatLng(-37.81319, 144.96298)
private val perthLatLng = LatLng(-31.95285, 115.85734)
// Airport locations for geodesic polyline.
private val aklLatLng = LatLng(-37.006254, 174.783018)
private val jfkLatLng = LatLng(40.641051, -73.777485)
private val laxLatLng = LatLng(33.936524, -118.377686)
private val lhrLatLng = LatLng(51.471547, -0.460052)
private val dot = Dot()
private val dash = Dash(PATTERN_DASH_LENGTH_PX.toFloat())
private val gap = Gap(PATTERN_GAP_LENGTH_PX.toFloat())
private val patternDotted = Arrays.asList(dot, gap)
private val patternDashed = Arrays.asList(dash, gap)
private val patternMixed = Arrays.asList(dot, gap, dot, dash, gap)
private lateinit var mutablePolyline: Polyline
private lateinit var hueBar: SeekBar
private lateinit var alphaBar: SeekBar
private lateinit var widthBar: SeekBar
private lateinit var startCapSpinner: Spinner
private lateinit var endCapSpinner: Spinner
private lateinit var jointTypeSpinner: Spinner
private lateinit var patternSpinner: Spinner
private lateinit var clickabilityCheckbox: CheckBox
// These are the options for polyline caps, joints and patterns. We use their
// string resource IDs as identifiers.
private val capTypeNameResourceIds = intArrayOf(R.string.cap_butt,
R.string.cap_round, R.string.cap_square, R.string.cap_image)
private val jointTypeNameResourceIds = intArrayOf(R.string.joint_type_default,
R.string.joint_type_bevel, R.string.joint_type_round)
private val patternTypeNameResourceIds = intArrayOf(R.string.pattern_solid,
R.string.pattern_dashed, R.string.pattern_dotted, R.string.pattern_mixed)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.polyline_demo)
hueBar = findViewById<SeekBar>(R.id.hueSeekBar).apply {
max = MAX_HUE_DEGREES
progress = 0
}
alphaBar = findViewById<SeekBar>(R.id.alphaSeekBar).apply {
max = MAX_ALPHA
progress = MAX_ALPHA
}
widthBar = findViewById<SeekBar>(R.id.widthSeekBar).apply {
max = MAX_WIDTH_PX
progress = MAX_WIDTH_PX / 2
}
startCapSpinner = findViewById<Spinner>(R.id.startCapSpinner).apply {
adapter = ArrayAdapter(this@PolylineDemoActivity,
android.R.layout.simple_spinner_item,
getResourceStrings(capTypeNameResourceIds))
}
endCapSpinner = findViewById<Spinner>(R.id.endCapSpinner).apply {
adapter = ArrayAdapter(this@PolylineDemoActivity,
android.R.layout.simple_spinner_item,
getResourceStrings(capTypeNameResourceIds))
}
jointTypeSpinner = findViewById<Spinner>(R.id.jointTypeSpinner).apply {
adapter = ArrayAdapter(this@PolylineDemoActivity,
android.R.layout.simple_spinner_item,
getResourceStrings(jointTypeNameResourceIds))
}
patternSpinner = findViewById<Spinner>(R.id.patternSpinner).apply {
adapter = ArrayAdapter(
this@PolylineDemoActivity, android.R.layout.simple_spinner_item,
getResourceStrings(patternTypeNameResourceIds))
}
clickabilityCheckbox = findViewById<CheckBox>(R.id.toggleClickability)
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}
private fun getResourceStrings(resourceIds: IntArray): List<String> {
return resourceIds.map { getString(it) }
}
override fun onMapReady(googleMap: GoogleMap?) {
// exit early if the map was not initialised properly
googleMap ?: return
with(googleMap) {
// Override the default content description on the view, for accessibility mode.
setContentDescription(getString(R.string.polyline_demo_description))
// A geodesic polyline that goes around the world.
addPolyline(PolylineOptions().apply {
add(lhrLatLng, aklLatLng, laxLatLng, jfkLatLng, lhrLatLng)
width(INITIAL_STROKE_WIDTH_PX.toFloat())
color(Color.BLUE)
geodesic(true)
clickable(clickabilityCheckbox.isChecked)
})
// Move the googleMap so that it is centered on the mutable polyline.
moveCamera(CameraUpdateFactory.newLatLngZoom(melbourneLatLng, 3f))
// Add a listener for polyline clicks that changes the clicked polyline's color.
setOnPolylineClickListener { polyline ->
// Flip the values of the red, green and blue components of the polyline's color.
polyline.color = polyline.color xor 0x00ffffff
}
}
// A simple polyline across Australia. This polyline will be mutable.
mutablePolyline = googleMap.addPolyline(PolylineOptions().apply{
color(Color.HSVToColor(
alphaBar.progress, floatArrayOf(hueBar.progress.toFloat(), 1f, 1f)))
width(widthBar.progress.toFloat())
clickable(clickabilityCheckbox.isChecked)
add(melbourneLatLng, adelaideLatLng, perthLatLng, darwinLatLng)
})
arrayOf(hueBar, alphaBar, widthBar).map {
it.setOnSeekBarChangeListener(this)
}
arrayOf(startCapSpinner, endCapSpinner, jointTypeSpinner, patternSpinner).map {
it.onItemSelectedListener = this
}
with(mutablePolyline) {
startCap = getSelectedCap(startCapSpinner.selectedItemPosition) ?: ButtCap()
endCap = getSelectedCap(endCapSpinner.selectedItemPosition) ?: ButtCap()
jointType = getSelectedJointType(jointTypeSpinner.selectedItemPosition)
pattern = getSelectedPattern(patternSpinner.selectedItemPosition)
}
clickabilityCheckbox.setOnClickListener {
view -> mutablePolyline.isClickable = (view as CheckBox).isChecked
}
}
private fun getSelectedCap(pos: Int): Cap? {
return when (capTypeNameResourceIds[pos]) {
R.string.cap_butt -> ButtCap()
R.string.cap_square -> SquareCap()
R.string.cap_round -> RoundCap()
R.string.cap_image -> CustomCap(
BitmapDescriptorFactory.fromResource(R.drawable.chevron),
CUSTOM_CAP_IMAGE_REF_WIDTH_PX.toFloat())
else -> null
}
}
private fun getSelectedJointType(pos: Int): Int {
return when (jointTypeNameResourceIds[pos]) {
R.string.joint_type_bevel -> JointType.BEVEL
R.string.joint_type_round -> JointType.ROUND
R.string.joint_type_default -> JointType.DEFAULT
else -> 0
}
}
private fun getSelectedPattern(pos: Int): List<PatternItem>? {
return when (patternTypeNameResourceIds[pos]) {
R.string.pattern_solid -> null
R.string.pattern_dotted -> patternDotted
R.string.pattern_dashed -> patternDashed
R.string.pattern_mixed -> patternMixed
else -> null
}
}
/**
* Listener for changes in a seekbar's position.
* Can change polyline color, width and transparency.
*/
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
when(seekBar) {
hueBar -> mutablePolyline.color = Color.HSVToColor(
Color.alpha(mutablePolyline.color), floatArrayOf(progress.toFloat(), 1f, 1f))
alphaBar -> {
val prevHSV = FloatArray(3)
Color.colorToHSV(mutablePolyline.color, prevHSV)
mutablePolyline.color = Color.HSVToColor(progress, prevHSV)
}
widthBar -> mutablePolyline.width = progress.toFloat()
}
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
// Don't do anything here.
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
// Don't do anything here.
}
/**
* Listener for changes in a spinner's position.
* Can change the polyline's start and end caps, pattern and joint type.
*/
override fun onItemSelected(parent: AdapterView<*>, view: View, pos: Int, id: Long) {
when (parent.id) {
R.id.startCapSpinner -> mutablePolyline.startCap = getSelectedCap(pos) ?: ButtCap()
R.id.endCapSpinner -> mutablePolyline.endCap = getSelectedCap(pos) ?: ButtCap()
R.id.jointTypeSpinner -> mutablePolyline.jointType = getSelectedJointType(pos)
R.id.patternSpinner -> mutablePolyline.pattern = getSelectedPattern(pos)
}
}
override fun onNothingSelected(parent: AdapterView<*>) {
// Don't do anything here.
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.anim
import android.os.Handler
import android.os.Looper
import kotlin.math.floor
/** Simple manager for UI-thread animation. All methods must be invoked on the UI thread only. */
class AnimationManager(frameRunnable: Runnable) {
private val animationHandler: Handler
private val animationRunnable: Runnable
var frameRateFps: Double
private var running: Boolean
init {
frameRateFps = INITIAL_FRAME_RATE_FPS
running = false
animationHandler = Handler(Looper.getMainLooper())
animationRunnable = object : Runnable {
override fun run() {
if (!running) {
return
}
frameRunnable.run()
requestAnimationFrame()
}
}
}
private fun requestAnimationFrame() {
if (frameRateFps <= 0.0) {
return
}
val delayMs = floor(1000.0 / frameRateFps) as Long
animationHandler.postDelayed(animationRunnable, delayMs)
}
fun startAnimation() {
if (running) {
return
}
requestAnimationFrame()
running = true
}
fun stopAnimation() {
if (!running) {
return
}
animationHandler.removeCallbacks(animationRunnable)
running = false
}
companion object {
private const val INITIAL_FRAME_RATE_FPS = 60.0
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.model
import com.google.android.libraries.maps.model.LatLng
/**
* Helper to translate all given LatLngs by the same amount in one of the predefined directions.
*/
enum class MoveDirection(private val numLatSteps: Int, private val numLngSteps: Int) {
UP(1, 0),
DOWN(-1, 0),
LEFT(0, -1),
RIGHT(0, 1);
fun getLatDistance(stepSizeDeg: Double): Double {
return numLatSteps * stepSizeDeg
}
fun getLngDistance(stepSizeDeg: Double): Double {
return numLngSteps * stepSizeDeg
}
companion object {
private fun movePoint(
oldPoint: LatLng,
latMoveDistance: Double,
lngMoveDistance: Double
): LatLng {
return LatLng(oldPoint.latitude + latMoveDistance, oldPoint.longitude + lngMoveDistance)
}
fun movePointsInList(
oldPoints: List<LatLng>,
latMoveDistance: Double,
lngMoveDistance: Double
): List<LatLng> {
val newPoints = mutableListOf<LatLng>()
for (oldPoint in oldPoints) {
newPoints.add(movePoint(oldPoint, latMoveDistance, lngMoveDistance))
}
return newPoints
}
fun movePointsInNestedList(
oldPointLists: List<List<LatLng>>,
latMoveDistance: Double,
lngMoveDistance: Double
): List<List<LatLng>> {
val newPointLists = mutableListOf<List<LatLng>>()
for (oldPointList in oldPointLists) {
newPointLists.add(movePointsInList(oldPointList, latMoveDistance, lngMoveDistance))
}
return newPointLists
}
}
}

View File

@ -0,0 +1,150 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioGroup
import android.widget.RadioGroup.OnCheckedChangeListener
import com.example.kotlindemos.R
import com.google.android.libraries.maps.model.BitmapDescriptorFactory
import com.google.android.libraries.maps.model.ButtCap
import com.google.android.libraries.maps.model.Cap
import com.google.android.libraries.maps.model.CustomCap
import com.google.android.libraries.maps.model.RoundCap
import com.google.android.libraries.maps.model.SquareCap
/**
* Fragment with "cap" UI controls for Polylines, to be used in ViewPager.
*/
class PolylineCapControlFragment : PolylineControlFragment(), OnCheckedChangeListener {
private val radioIdToStartCap = mutableMapOf<Int, Cap>()
private val radioIdToEndCap = mutableMapOf<Int, Cap>()
private lateinit var startCapRadioGroup: RadioGroup
private lateinit var endCapRadioGroup: RadioGroup
init {
radioIdToStartCap[R.id.start_cap_radio_butt] = ButtCap()
radioIdToStartCap[R.id.start_cap_radio_square] = SquareCap()
radioIdToStartCap[R.id.start_cap_radio_round] = RoundCap()
radioIdToStartCap[R.id.start_cap_radio_custom_chevron] = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.chevron), CHEVRON_REF_WIDTH)
radioIdToStartCap[R.id.start_cap_radio_custom_ook] = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.ook), OOK_REF_WIDTH)
radioIdToEndCap[R.id.end_cap_radio_butt] = ButtCap()
radioIdToEndCap[R.id.end_cap_radio_square] = SquareCap()
radioIdToEndCap[R.id.end_cap_radio_round] = RoundCap()
radioIdToEndCap[R.id.end_cap_radio_custom_chevron] = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.chevron),
CHEVRON_REF_WIDTH)
radioIdToEndCap[R.id.end_cap_radio_custom_ook] = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.ook), OOK_REF_WIDTH)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view: View = inflater.inflate(R.layout.polyline_cap_control_fragment, container, false)
startCapRadioGroup = view.findViewById(R.id.start_cap_radio)
endCapRadioGroup = view.findViewById(R.id.end_cap_radio)
startCapRadioGroup.setOnCheckedChangeListener(this)
endCapRadioGroup.setOnCheckedChangeListener(this)
return view
}
override fun onCheckedChanged(group: RadioGroup, checkedId: Int) {
if (polyline == null) {
return
}
val groupId = group.getId()
if (groupId == R.id.start_cap_radio) {
val startCap = radioIdToStartCap[checkedId]
startCap?.let {
polyline?.setStartCap(it)
}
} else if (groupId == R.id.end_cap_radio) {
val endCap = radioIdToEndCap[checkedId]
endCap?.let {
polyline?.setEndCap(it)
}
}
}
override fun refresh() {
if (polyline == null) {
startCapRadioGroup.clearCheck()
for (i in 0 until startCapRadioGroup.getChildCount()) {
startCapRadioGroup.getChildAt(i).setEnabled(false)
}
endCapRadioGroup.clearCheck()
for (i in 0 until endCapRadioGroup.getChildCount()) {
endCapRadioGroup.getChildAt(i).setEnabled(false)
}
return
}
for (i in 0 until startCapRadioGroup.getChildCount()) {
startCapRadioGroup.getChildAt(i).setEnabled(true)
}
when (val startCap = polyline?.startCap) {
is ButtCap -> {
startCapRadioGroup.check(R.id.start_cap_radio_butt)
}
is SquareCap -> {
startCapRadioGroup.check(R.id.start_cap_radio_square)
}
is RoundCap -> {
startCapRadioGroup.check(R.id.start_cap_radio_round)
}
is CustomCap -> {
startCapRadioGroup.check(
if (isOok(startCap)) R.id.start_cap_radio_custom_ook else R.id.start_cap_radio_custom_chevron)
}
else -> {
startCapRadioGroup.clearCheck()
}
}
for (i in 0 until endCapRadioGroup.getChildCount()) {
endCapRadioGroup.getChildAt(i).isEnabled = true
}
when (val endCap = polyline?.endCap) {
is ButtCap -> {
endCapRadioGroup.check(R.id.end_cap_radio_butt)
}
is SquareCap -> {
endCapRadioGroup.check(R.id.end_cap_radio_square)
}
is RoundCap -> {
endCapRadioGroup.check(R.id.end_cap_radio_round)
}
is CustomCap -> {
endCapRadioGroup.check(
if (isOok(endCap)) R.id.end_cap_radio_custom_ook else R.id.end_cap_radio_custom_chevron)
}
else -> {
endCapRadioGroup.clearCheck()
}
}
}
companion object {
// We require Ook's refWidth > chevron's refWidth so isOok(CustomCap) can distinguish
// between the two CustomCaps by simple comparison of CustomCap.getBitmapRefWidth() against
// CHEVRON_VERSUS_OOK_REF_WIDTH_THRESHOLD, for the purpose of refreshing "cap" UI radio
// buttons. See isOok() for details on why this is necessary.
private const val CHEVRON_REF_WIDTH = 15.0f
private const val OOK_REF_WIDTH = 32.0f
private const val CHEVRON_VERSUS_OOK_REF_WIDTH_THRESHOLD = 0.5f * (CHEVRON_REF_WIDTH + OOK_REF_WIDTH)
private fun isOok(customCap: CustomCap): Boolean {
return customCap.refWidth >= CHEVRON_VERSUS_OOK_REF_WIDTH_THRESHOLD
}
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView
import com.example.kotlindemos.R
/** Fragment with "color" UI controls for Polylines, to be used in ViewPager. */
class PolylineColorControlFragment : PolylineControlFragment(), OnSeekBarChangeListener {
private lateinit var alphaBar: SeekBar
private lateinit var hueBar: SeekBar
private lateinit var argbTextView: TextView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view: View = inflater.inflate(R.layout.polyline_color_control_fragment, container, false)
alphaBar = view.findViewById(R.id.alphaSeekBar)
alphaBar.max = ALPHA_MAX
alphaBar.setOnSeekBarChangeListener(this)
hueBar = view.findViewById(R.id.hueSeekBar)
hueBar.max = HUE_MAX
hueBar.setOnSeekBarChangeListener(this)
argbTextView = view.findViewById(R.id.argbTextView) as TextView
return view
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
// Don't do anything here.
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
// Don't do anything here.
}
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
val polyline = polyline
if (polyline == null || !fromUser) {
return
}
if (seekBar === hueBar) {
polyline.color = Color.HSVToColor(Color.alpha(polyline.color), floatArrayOf(progress.toFloat(), 1f, 1f))
} else if (seekBar === alphaBar) {
val prevHSV = FloatArray(3)
Color.colorToHSV(polyline.color, prevHSV)
polyline.color = Color.HSVToColor(progress, prevHSV)
}
argbTextView.text = String.format("0x%08X", polyline.color)
}
override fun refresh() {
val polyline = polyline
if (polyline == null) {
alphaBar.isEnabled = false
alphaBar.progress = 0
hueBar.isEnabled = false
hueBar.progress = 0
argbTextView.text = ""
return
}
val color: Int = polyline.color
alphaBar.isEnabled = true
alphaBar.progress = Color.alpha(color)
val hsv = FloatArray(3)
Color.colorToHSV(color, hsv)
hueBar.isEnabled = true
hueBar.progress = hsv[0].toInt()
argbTextView.text = String.format("0x%08X", color)
}
companion object {
private const val HUE_MAX = 359
private const val ALPHA_MAX = 255
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import androidx.fragment.app.Fragment
import com.google.android.libraries.maps.model.Polyline
abstract class PolylineControlFragment : Fragment() {
var polyline: Polyline? = null
set(value) {
field = value
refresh()
}
abstract fun refresh()
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
class PolylineControlFragmentPagerAdapter(
fragmentManager: FragmentManager,
private val isLiteMode: Boolean
) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private val positionsToFragments = mutableMapOf<Int, PolylineControlFragment>()
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val fragment: PolylineControlFragment = super.instantiateItem(container, position) as PolylineControlFragment
positionsToFragments.put(position, fragment)
return fragment
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
super.destroyItem(container, position, `object`)
positionsToFragments.remove(position)
}
override fun getItem(position: Int): Fragment {
return when (position) {
0 -> PolylineColorControlFragment()
1 -> PolylineWidthControlFragment()
2 -> PolylineCapControlFragment()
3 -> PolylineJointControlFragment()
4 -> PolylinePatternControlFragment()
5 -> PolylinePointsControlFragment()
6 -> PolylineSpansControlFragment.newInstance(isLiteMode)
7 -> PolylineOtherOptionsControlFragment()
else -> Fragment()
}
}
override fun getCount(): Int = 8
override fun getPageTitle(position: Int): CharSequence? {
// Ideally these strings should be localised, but let's not bother for a demo app.
return when (position) {
0 -> "Color"
1 -> "Width"
2 -> "Cap"
3 -> "Joint"
4 -> "Pattern"
5 -> "Points"
6 -> "Spans"
7 -> "Other Options"
else -> null
}
}
fun getFragmentAtPosition(position: Int): PolylineControlFragment? {
return positionsToFragments[position]
}
}

View File

@ -0,0 +1,197 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.graphics.Color
import android.os.Bundle
import android.widget.RadioGroup
import android.widget.RadioGroup.OnCheckedChangeListener
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
import com.example.kotlindemos.R
import com.google.android.libraries.maps.CameraUpdateFactory
import com.google.android.libraries.maps.GoogleMap
import com.google.android.libraries.maps.GoogleMap.OnPolylineClickListener
import com.google.android.libraries.maps.OnMapReadyCallback
import com.google.android.libraries.maps.SupportMapFragment
import com.google.android.libraries.maps.model.Dash
import com.google.android.libraries.maps.model.Dot
import com.google.android.libraries.maps.model.Gap
import com.google.android.libraries.maps.model.LatLng
import com.google.android.libraries.maps.model.Polyline
import com.google.android.libraries.maps.model.PolylineOptions
import java.util.ArrayList
import java.util.Arrays
/**
* This shows how to apply multiple colors on a polyline.
*/
class PolylineDemoActivity : AppCompatActivity(), OnMapReadyCallback, OnPageChangeListener, OnCheckedChangeListener, OnPolylineClickListener {
private var australiaPolyline: Polyline? = null
private var melbournePolyline: Polyline? = null
private var sydneyPolyline: Polyline? = null
private var worldPolyline: Polyline? = null
private var selectedPolyline: Polyline? = null
private lateinit var pagerAdapter: PolylineControlFragmentPagerAdapter
private val spanResetPolylines = mutableSetOf<Polyline>()
private lateinit var polylineRadio: RadioGroup
private lateinit var pager: ViewPager // TODO use ViewPager2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.multicolor_polyline_demo)
pagerAdapter = PolylineControlFragmentPagerAdapter(
supportFragmentManager,
/* isLiteMode= */false
)
pager = findViewById(R.id.pager)
pager.adapter = pagerAdapter
// onPageSelected(0) isn't invoked once views are ready, so post a Runnable to
// refreshControlPanel() for the first time instead...
pager.post { refreshControlPanel() }
polylineRadio = findViewById(R.id.polyline_radio)
val mapFragment: SupportMapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}
override fun onMapReady(map: GoogleMap) {
// For accessibility mode. Ideally this string would be localised.
map.setContentDescription("Google Map with polylines.")
// Non-loop polyline that goes past Australian cities. Added before sydneyPolyline and would
// normally be underneath, but increase Z-Index so that this line is on top.
australiaPolyline = map.addPolyline(
PolylineOptions()
.add(PERTH, ADELAIDE, SYDNEY, MELBOURNE)
.pattern(Arrays.asList(Dot(), Gap(20.0f)))
.color(Color.MAGENTA)
.zIndex(1F))
// Geodesic polyline that goes around the world.
worldPolyline = map.addPolyline(
PolylineOptions()
.add(LONDON, AUCKLAND, LOS_ANGELES, NEW_YORK, LONDON)
.width(5F)
.color(Color.BLUE)
.geodesic(true)
.clickable(true))
// Loop polyline centered at Sydney.
val radius = 4
sydneyPolyline = map.addPolyline(
PolylineOptions()
.add(LatLng(SYDNEY.latitude + radius, SYDNEY.longitude + radius))
.add(LatLng(SYDNEY.latitude + radius, SYDNEY.longitude - radius))
.add(LatLng(SYDNEY.latitude - radius, SYDNEY.longitude - radius))
.add(LatLng(SYDNEY.latitude - radius, SYDNEY.longitude))
.add(LatLng(SYDNEY.latitude - radius, SYDNEY.longitude + radius))
.add(LatLng(SYDNEY.latitude + radius, SYDNEY.longitude + radius))
.pattern(listOf(Dash(45.0f), Gap(10.0f)))
.color(Color.RED)
.width(5F)
.clickable(true))
// Create Melbourne polyline to show layering of polylines with same Z-Index. This is added
// second so it will be layered on top of the Sydney polyline (both have Z-Index == 0).
melbournePolyline = map.addPolyline(
PolylineOptions()
.add(LatLng(MELBOURNE.latitude + radius, MELBOURNE.longitude + radius))
.add(LatLng(MELBOURNE.latitude + radius, MELBOURNE.longitude - radius))
.add(LatLng(MELBOURNE.latitude - radius, MELBOURNE.longitude - radius))
.add(LatLng(MELBOURNE.latitude - radius, MELBOURNE.longitude))
.add(LatLng(MELBOURNE.latitude - radius, MELBOURNE.longitude + radius))
.add(LatLng(MELBOURNE.latitude + radius, MELBOURNE.longitude + radius))
.color(Color.GREEN)
.width(5F)
.clickable(true))
map.moveCamera(CameraUpdateFactory.newLatLng(SYDNEY))
selectedPolyline = australiaPolyline
polylineRadio.check(R.id.polyline_radio_australia)
pager.addOnPageChangeListener(this)
polylineRadio.setOnCheckedChangeListener(this)
map.setOnPolylineClickListener(this)
}
override fun onPolylineClick(polyline: Polyline) {
// Flip the values of the r, g and b components of the polyline's color.
val strokeColor: Int = polyline.color xor 0x00ffffff
polyline.color = strokeColor
polyline.setSpans(ArrayList())
spanResetPolylines.add(polyline)
refreshControlPanel()
}
override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
when (checkedId) {
R.id.polyline_radio_australia -> {
selectedPolyline = australiaPolyline
}
R.id.polyline_radio_sydney -> {
selectedPolyline = sydneyPolyline
}
R.id.polyline_radio_melbourne -> {
selectedPolyline = melbournePolyline
}
R.id.polyline_radio_world -> {
selectedPolyline = worldPolyline
}
}
refreshControlPanel()
}
override fun onPageSelected(position: Int) {
refreshControlPanel()
}
private fun refreshControlPanel() {
val fragment: PolylineControlFragment? = pagerAdapter.getFragmentAtPosition(pager.getCurrentItem())
if (fragment != null) {
if (fragment is PolylineSpansControlFragment
&& spanResetPolylines.contains(selectedPolyline)) {
val spansControlFragment: PolylineSpansControlFragment = fragment as PolylineSpansControlFragment
spansControlFragment.resetSpanState(selectedPolyline)
spanResetPolylines.remove(selectedPolyline)
}
fragment.polyline = selectedPolyline
}
}
override fun onPageScrollStateChanged(state: Int) {
// Don't do anything here.
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
// Don't do anything here.
}
override fun onPointerCaptureChanged(hasCapture: Boolean) {
}
companion object {
val TAG: String = PolylineDemoActivity::class.java.getSimpleName()
private val MELBOURNE: LatLng = LatLng(-37.81319, 144.96298)
private val SYDNEY: LatLng = LatLng(-33.87365, 151.20689)
private val ADELAIDE: LatLng = LatLng(-34.92873, 138.59995)
private val PERTH: LatLng = LatLng(-31.95285, 115.85734)
private val LONDON: LatLng = LatLng(51.471547, -0.460052)
private val LOS_ANGELES: LatLng = LatLng(33.936524, -118.377686)
private val NEW_YORK: LatLng = LatLng(40.641051, -73.777485)
private val AUCKLAND: LatLng = LatLng(-37.006254, 174.783018)
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioGroup
import android.widget.RadioGroup.OnCheckedChangeListener
import com.example.kotlindemos.R
import com.google.android.libraries.maps.model.JointType
/**
* Fragment with "joint" UI controls for Polylines, to be used in ViewPager.
*/
class PolylineJointControlFragment : PolylineControlFragment(), OnCheckedChangeListener {
private val radioIdToJointType = mutableMapOf<Int, Int>()
private lateinit var jointRadioGroup: RadioGroup
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view = inflater.inflate(R.layout.polyline_joint_control_fragment, container, false)
jointRadioGroup = view.findViewById(R.id.joint_radio)
jointRadioGroup.setOnCheckedChangeListener(this)
return view
}
override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
if (polyline == null) {
return
}
val jointType = radioIdToJointType[checkedId]
if (jointType != null) {
polyline?.jointType = jointType
}
}
override fun refresh() {
if (polyline == null) {
jointRadioGroup.clearCheck()
for (i in 0 until jointRadioGroup.childCount) {
jointRadioGroup.getChildAt(i).isEnabled = false
}
return
}
for (i in 0 until jointRadioGroup.childCount) {
jointRadioGroup.getChildAt(i).isEnabled = true
}
when (polyline?.jointType) {
JointType.DEFAULT -> jointRadioGroup.check(R.id.joint_radio_default)
JointType.BEVEL -> jointRadioGroup.check(R.id.joint_radio_bevel)
JointType.ROUND -> jointRadioGroup.check(R.id.joint_radio_round)
else -> jointRadioGroup.clearCheck()
}
}
init {
radioIdToJointType[R.id.joint_radio_default] = JointType.DEFAULT
radioIdToJointType[R.id.joint_radio_bevel] = JointType.BEVEL
radioIdToJointType[R.id.joint_radio_round] = JointType.ROUND
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import com.example.kotlindemos.R
/**
* Fragment with clickability, geodesic, and visibility UI controls for Polylines, to be used in
* ViewPager.
*/
class PolylineOtherOptionsControlFragment : PolylineControlFragment(), View.OnClickListener {
private lateinit var clickabilityCheckBox: CheckBox
private lateinit var geodesicCheckBox: CheckBox
private lateinit var visibilityCheckBox: CheckBox
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view = inflater.inflate(R.layout.polyline_other_options_control_fragment, container, false)
clickabilityCheckBox = view.findViewById(R.id.clickabilityCheckBox)
clickabilityCheckBox.setOnClickListener(this)
geodesicCheckBox = view.findViewById(R.id.geodesicCheckBox)
geodesicCheckBox.setOnClickListener(this)
visibilityCheckBox = view.findViewById(R.id.visibilityCheckBox)
visibilityCheckBox.setOnClickListener(this)
return view
}
override fun onClick(view: View) {
val polyline = polyline ?: return
when {
view === clickabilityCheckBox -> {
polyline.isClickable = clickabilityCheckBox.isChecked
}
view === geodesicCheckBox -> {
polyline.isGeodesic = geodesicCheckBox.isChecked
}
view === visibilityCheckBox -> {
polyline.isVisible = visibilityCheckBox.isChecked
}
}
}
override fun refresh() {
clickabilityCheckBox.isChecked = polyline != null && polyline?.isClickable ?: false
geodesicCheckBox.isChecked = polyline != null && polyline?.isGeodesic ?: false
visibilityCheckBox.isChecked = polyline != null && polyline?.isVisible ?: false
}
}

View File

@ -0,0 +1,130 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import com.example.kotlindemos.R
import com.google.android.libraries.maps.model.Dash
import com.google.android.libraries.maps.model.Dot
import com.google.android.libraries.maps.model.Gap
import com.google.android.libraries.maps.model.PatternItem
import java.util.ArrayList
import java.util.Random
/** Fragment with "pattern" UI controls for Polylines, to be used in ViewPager. */
class PolylinePatternControlFragment : PolylineControlFragment(), OnClickListener {
private lateinit var patternSolidBtn: Button
private lateinit var patternDottedBtn: Button
private lateinit var patternDashedBtn: Button
private lateinit var patternMixedBtn: Button
private lateinit var patternTextView: TextView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view = inflater.inflate(R.layout.polyline_pattern_control_fragment, container, false)
patternTextView = view.findViewById(R.id.patternTextView)
patternSolidBtn = view.findViewById(R.id.patternSolidBtn)
patternDottedBtn = view.findViewById(R.id.patternDottedBtn)
patternDashedBtn = view.findViewById(R.id.patternDashedBtn)
patternMixedBtn = view.findViewById(R.id.patternMixedBtn)
patternSolidBtn.setOnClickListener(this)
patternDottedBtn.setOnClickListener(this)
patternDashedBtn.setOnClickListener(this)
patternMixedBtn.setOnClickListener(this)
return view
}
override fun onClick(view: View) {
if (polyline == null) {
return
}
val id: Int = view.id
val pattern: List<PatternItem>?
when (id) {
R.id.patternSolidBtn -> {
pattern = null
}
R.id.patternDottedBtn -> {
pattern = listOf(Dot(), Gap(RANDOM.nextFloat() * MAX_GAP_LENGTH))
}
R.id.patternDashedBtn -> {
pattern = listOf(
Dash(RANDOM.nextFloat() * MAX_DASH_LENGTH),
Gap(RANDOM.nextFloat() * MAX_GAP_LENGTH))
}
R.id.patternMixedBtn -> {
val size: Int = 2 * (1 + RANDOM.nextInt(MAX_PATTERN_SIZE / 2))
pattern = ArrayList(size)
for (i in 0 until size) {
if (i % 2 == 0) {
pattern.add(
if (RANDOM.nextBoolean()) Dot() else Dash(RANDOM.nextFloat() * MAX_DASH_LENGTH))
} else {
pattern.add(Gap(RANDOM.nextFloat() * MAX_GAP_LENGTH))
}
}
}
else -> {
throw IllegalStateException("Unknown button")
}
}
polyline?.pattern = pattern
patternTextView.text = toString(pattern)
}
override fun refresh() {
val enabled = polyline != null
patternSolidBtn.isEnabled = enabled
patternDottedBtn.isEnabled = enabled
patternDashedBtn.isEnabled = enabled
patternMixedBtn.isEnabled = enabled
patternTextView.text = if (polyline == null) "" else polyline?.pattern.toString()
}
companion object {
private const val MAX_PATTERN_SIZE = 6
private const val MAX_DASH_LENGTH = 200
private const val MAX_GAP_LENGTH = 100
private val RANDOM: Random = Random()
private fun toString(pattern: List<PatternItem>?): String {
if (pattern == null) {
return "<SOLID>"
}
val sb = StringBuilder("")
for (item in pattern) {
when (item) {
is Dot -> {
sb.append("DOT")
}
is Dash -> {
sb.append(String.format("%.1fpx-DASH", (item as Dash).length))
}
is Gap -> {
sb.append(String.format("%.1fpx-GAP", (item as Gap).length))
}
}
sb.append(" ")
}
sb.append("<repeat>")
return sb.toString()
}
}
}

View File

@ -0,0 +1,157 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.os.Bundle
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.TextView
import com.example.kotlindemos.R
import com.example.kotlindemos.anim.AnimationManager
import com.example.kotlindemos.model.MoveDirection
import com.google.android.libraries.maps.model.LatLng
/** Fragment with "points" UI controls for Polylines, to be used in ViewPager. */
class PolylinePointsControlFragment : PolylineControlFragment(), View.OnTouchListener, View.OnFocusChangeListener, TextView.OnEditorActionListener {
private var moveDirection: MoveDirection? = null
private var stepSizeDeg = 0.0
private var originalPoints: List<LatLng>? = null
private var latDistance = 0.0
private var lngDistance = 0.0
private val animationManager: AnimationManager = AnimationManager(
object : Runnable {
override fun run() {
if (polyline == null || moveDirection == null) {
return
}
// When the polyline moves offscreen, its coordinates will be clamped and caused the
// shape to change. Using the original points for computing new points to make sure
// the shape can be retained after the polyline moves offscreen.
latDistance += moveDirection?.getLatDistance(stepSizeDeg) ?: 0.0
lngDistance += moveDirection?.getLngDistance(stepSizeDeg) ?: 0.0
polyline?.points = MoveDirection.movePointsInList(originalPoints ?: mutableListOf(), latDistance, lngDistance)
}
})
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view: View = inflater.inflate(R.layout.polyline_points_control_fragment, container, false)
(view.findViewById(R.id.move_up) as View).setOnTouchListener(this)
(view.findViewById(R.id.move_down) as View).setOnTouchListener(this)
(view.findViewById(R.id.move_left) as View).setOnTouchListener(this)
(view.findViewById(R.id.move_right) as View).setOnTouchListener(this)
val fpsEditText: EditText = view.findViewById(R.id.fps_edittext) as EditText
fpsEditText.setOnEditorActionListener(this)
fpsEditText.onFocusChangeListener = this
setFrameRate(fpsEditText)
val stepEditText: EditText = view.findViewById(R.id.step_edittext) as EditText
stepEditText.setOnEditorActionListener(this)
stepEditText.onFocusChangeListener = this
setStepSize(stepEditText)
moveDirection = null
return view
}
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
return when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
setMoveDirection(view.id)
animationManager.startAnimation()
true
}
MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
moveDirection = null
animationManager.stopAnimation()
true
}
else -> false
}
}
private fun setMoveDirection(buttonId: Int) {
moveDirection = when (buttonId) {
R.id.move_up -> {
MoveDirection.UP
}
R.id.move_down -> {
MoveDirection.DOWN
}
R.id.move_left -> {
MoveDirection.LEFT
}
R.id.move_right -> {
MoveDirection.RIGHT
}
else -> {
null
}
}
}
override fun onEditorAction(textView: TextView, actionId: Int, event: KeyEvent?): Boolean {
// Only handle "Done" action triggered by the user tapping "Enter" on the keyboard.
if (actionId != EditorInfo.IME_ACTION_DONE) {
return false
}
val textViewId: Int = textView.getId()
if (textViewId == R.id.fps_edittext) {
setFrameRate(textView)
} else if (textViewId == R.id.step_edittext) {
setStepSize(textView)
}
return false
}
override fun onFocusChange(view: View, hasFocus: Boolean) {
if (hasFocus) {
return
}
val viewId: Int = view.getId()
if (viewId == R.id.fps_edittext) {
setFrameRate(view as TextView)
} else if (viewId == R.id.step_edittext) {
setStepSize(view as TextView)
}
}
private fun setFrameRate(textView: TextView) {
val newValue: String = textView.text.toString()
try {
animationManager.frameRateFps = newValue.toDouble()
} catch (e: NumberFormatException) {
textView.text = animationManager.frameRateFps.toString()
}
}
private fun setStepSize(textView: TextView) {
val newValue: String = textView.text.toString()
try {
stepSizeDeg = newValue.toDouble()
} catch (e: NumberFormatException) {
textView.text = stepSizeDeg.toString()
}
}
override fun refresh() {
latDistance = 0.0
lngDistance = 0.0
originalPoints = polyline?.points
}
}

View File

@ -0,0 +1,182 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import android.widget.RadioGroup
import android.widget.SeekBar
import android.widget.TextView
import com.example.kotlindemos.R
import com.google.android.libraries.maps.model.BitmapDescriptorFactory
import com.google.android.libraries.maps.model.Polyline
import com.google.android.libraries.maps.model.StrokeStyle
import com.google.android.libraries.maps.model.StyleSpan
import com.google.android.libraries.maps.model.TextureStyle
/**
* Fragment with span count UI controls for [com.google.android.libraries.maps.model.Polyline], to
* be used in ViewPager.
*
*
* When span count is updated from the slider, the selected polyline will be updated with that
* number of spans. Each span will either have polyline color or the inverted color, and span
* lengths are equally divided by number of segments in the polyline.
*/
class PolylineSpansControlFragment : PolylineControlFragment(), SeekBar.OnSeekBarChangeListener, RadioGroup.OnCheckedChangeListener {
private lateinit var spanCountBar: SeekBar
private lateinit var spanCountTextView: TextView
private lateinit var gradientToggle: CompoundButton
private lateinit var polylineStampStyleRadioGroup: RadioGroup
private var spanCount = 0
private val polylineSpanCounts = mutableMapOf<Polyline, Int>()
private val polylineGradientStates = mutableMapOf<Polyline, Boolean>()
private var isLiteMode = false
private var selectedStampStyleId = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
isLiteMode = arguments?.getBoolean(IS_LITE_MODE_KEY) ?: false
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view = inflater.inflate(R.layout.polyline_spans_control_fragment, container, false)
spanCountBar = view.findViewById(R.id.spansSeekBar)
spanCountBar.max = SPAN_COUNT_MAX
spanCountBar.setOnSeekBarChangeListener(this)
spanCountTextView = view.findViewById(R.id.spansTextView)
gradientToggle = view.findViewById(R.id.gradientToggle)
gradientToggle.setOnCheckedChangeListener { _, isChecked ->
polyline?.let {
polylineGradientStates[it] = isChecked
}
updateSpans()
}
polylineStampStyleRadioGroup = view.findViewById(R.id.polyline_stamp_style_radio_group)
polylineStampStyleRadioGroup.visibility = View.INVISIBLE
if (isLiteMode) {
gradientToggle.visibility = View.INVISIBLE
polylineStampStyleRadioGroup.visibility = View.INVISIBLE
}
polylineSpanCounts.clear()
polylineGradientStates.clear()
selectedStampStyleId = 0
polylineStampStyleRadioGroup.setOnCheckedChangeListener(this)
return view
}
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
spanCount = progress
polyline?.let {
polylineSpanCounts.put(it, spanCount)
}
spanCountTextView.text = spanCount.toString()
updateSpans()
}
private fun generateSpans(count: Int): List<StyleSpan> {
val polyline = polyline ?: return emptyList()
val invertedPolylineColor: Int = polyline.color xor 0x00ffffff
val newSpans = mutableListOf<StyleSpan>()
for (i in 0 until count) {
val color = if (i % 2 == 0) polyline.color else invertedPolylineColor
val segmentCount = (polyline.points.size - 1).toDouble() / count
val strokeStyleBuilder: StrokeStyle.Builder = if (gradientToggle.isChecked) StrokeStyle.gradientBuilder(polyline.color, invertedPolylineColor) else StrokeStyle.colorBuilder(color)
if (selectedStampStyleId == R.id.polyline_texture_style) {
strokeStyleBuilder.stamp(
TextureStyle.newBuilder(BitmapDescriptorFactory.fromResource(R.drawable.ook))
.build())
}
newSpans.add(StyleSpan(strokeStyleBuilder.build(), segmentCount))
}
return newSpans
}
private fun updateSpans() {
val polyline = polyline ?: return
polyline.setSpans(generateSpans(spanCount))
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
// Don't do anything here.
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
// Don't do anything here.
}
override fun refresh() {
val polyline = polyline
if (polyline == null) {
spanCountBar.isEnabled = false
spanCountBar.progress = 0
spanCountTextView.text = ""
gradientToggle.isChecked = false
gradientToggle.isEnabled = false
polylineStampStyleRadioGroup.clearCheck()
polylineStampStyleRadioGroup.isEnabled = false
return
}
if (!polylineSpanCounts.containsKey(polyline)) {
polylineSpanCounts[polyline] = 0
}
if (!polylineGradientStates.containsKey(polyline)) {
polylineGradientStates[polyline] = false
}
spanCountBar.isEnabled = true
spanCountBar.progress = polylineSpanCounts[polyline] ?: 0
spanCountTextView.text = polylineSpanCounts[polyline].toString()
if (!isLiteMode) {
gradientToggle.isEnabled = true
gradientToggle.isChecked = polylineGradientStates[polyline] ?: false
polylineStampStyleRadioGroup.isEnabled = true
polylineStampStyleRadioGroup.check(selectedStampStyleId)
}
}
override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
selectedStampStyleId = checkedId
updateSpans()
}
/**
* Resets the span states of a polyline.
*
*
* Because there's no getter for polyline spans, this is needed for the polyline demo
* activity
* to update span control UI components.
*/
fun resetSpanState(polyline: Polyline?) {
polylineSpanCounts.remove(polyline)
polylineGradientStates.remove(polyline)
}
companion object {
private const val IS_LITE_MODE_KEY = "isLiteMode"
private const val SPAN_COUNT_MAX = 20
fun newInstance(isLiteMode: Boolean): PolylineSpansControlFragment {
val polylineSpansControlFragment = PolylineSpansControlFragment()
val args = Bundle()
args.putBoolean(IS_LITE_MODE_KEY, isLiteMode)
polylineSpansControlFragment.arguments = args
return polylineSpansControlFragment
}
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.kotlindemos.polyline
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.SeekBar
import android.widget.TextView
import com.example.kotlindemos.R
/**
* Fragment with "width" UI controls for Polylines, to be used in ViewPager.
*/
class PolylineWidthControlFragment : PolylineControlFragment(), SeekBar.OnSeekBarChangeListener {
private lateinit var widthBar: SeekBar
private lateinit var widthTextView: TextView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, bundle: Bundle?): View {
val view = inflater.inflate(R.layout.polyline_width_control_fragment, container, false)
widthBar = view.findViewById(R.id.widthSeekBar)
widthBar.max = WIDTH_MAX
widthBar.setOnSeekBarChangeListener(this)
widthTextView = view.findViewById(R.id.widthTextView)
return view
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
// Don't do anything here.
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
// Don't do anything here.
}
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
val polyline = polyline ?: return
polyline.width = progress.toFloat()
widthTextView.text = polyline.width.toString() + "px"
}
override fun refresh() {
val polyline = polyline
if (polyline == null) {
widthBar.isEnabled = false
widthBar.progress = 0
widthTextView.text = ""
return
}
widthBar.isEnabled = true
val width: Float = polyline.width
widthBar.progress = width.toInt()
widthTextView.text = width.toString() + "px"
}
companion object {
private const val WIDTH_MAX = 50
}
}

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/map"
class="com.google.android.libraries.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="47.6089945"
map:cameraTargetLng="-122.3410462"
map:cameraZoom="14"
map:mapId="@string/cloud_styling_basic_map_id" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#D000"
android:orientation="vertical"
android:padding="5dp">
<LinearLayout
android:id="@+id/cloud_styling_basic_demo_mode_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/styling_normal_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_normal_mode" />
<Button
android:id="@+id/styling_satellite_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_satellite_mode" />
<Button
android:id="@+id/styling_hybrid_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_hybrid_mode" />
<Button
android:id="@+id/styling_terrain_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lite_styling_terrain_mode" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
class="com.google.android.libraries.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

Some files were not shown because too many files have changed in this diff Show More