В этом примере определяется местоположение на карте, где установлен маркер. Когда пользователь нажимает на маркер, появляется информационное окно.
Подробнее читайте в документации.
Начало работы
Прежде чем воспользоваться образцом кода, настройте среду разработки. Подробнее об образцах кода Maps SDK для Android…
Ознакомьтесь с кодом
class MarkerDemoActivity :
AppCompatActivity(),
OnMarkerClickListener,
OnInfoWindowClickListener,
OnMarkerDragListener,
OnInfoWindowLongClickListener,
OnInfoWindowCloseListener,
OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener {
private val TAG = MarkerDemoActivity::class.java.name
/** This is ok to be lateinit as it is initialised in onMapReady */
private lateinit var map: GoogleMap
/**
* Keeps track of the last selected marker (though it may no longer be selected). This is
* useful for refreshing the info window.
*
* Must be nullable as it is null when no marker has been selected
*/
private var lastSelectedMarker: Marker? = null
private val markerRainbow = ArrayList<Marker>()
/** map to store place names and locations */
private val places = mapOf(
"BRISBANE" to LatLng(-27.47093, 153.0235),
"MELBOURNE" to LatLng(-37.81319, 144.96298),
"DARWIN" to LatLng(-12.4634, 130.8456),
"SYDNEY" to LatLng(-33.87365, 151.20689),
"ADELAIDE" to LatLng(-34.92873, 138.59995),
"PERTH" to LatLng(-31.952854, 115.857342),
"ALICE_SPRINGS" to LatLng(-24.6980, 133.8807)
)
/** These can be lateinit as they are set in onCreate */
private lateinit var topText: TextView
private lateinit var rotationBar: SeekBar
private lateinit var flatBox: CheckBox
private lateinit var options: RadioGroup
private val random = Random()
/** Demonstrates customizing the info window and/or its contents. */
internal inner class CustomInfoWindowAdapter : InfoWindowAdapter {
// These are both view groups containing an ImageView with id "badge" and two
// TextViews with id "title" and "snippet".
private val window: View = layoutInflater.inflate(R.layout.custom_info_window, null)
private val contents: View = layoutInflater.inflate(R.layout.custom_info_contents, null)
override fun getInfoWindow(marker: Marker): View? {
if (options.checkedRadioButtonId != R.id.custom_info_window) {
// This means that getInfoContents will be called.
return null
}
render(marker, window)
return window
}
override fun getInfoContents(marker: Marker): View? {
if (options.checkedRadioButtonId != R.id.custom_info_contents) {
// This means that the default info contents will be used.
return null
}
render(marker, contents)
return contents
}
private fun render(marker: Marker, view: View) {
val badge = when (marker.title!!) {
"Brisbane" -> R.drawable.badge_qld
"Adelaide" -> R.drawable.badge_sa
"Sydney" -> R.drawable.badge_nsw
"Melbourne" -> R.drawable.badge_victoria
"Perth" -> R.drawable.badge_wa
in "Darwin Marker 1".."Darwin Marker 4" -> R.drawable.badge_nt
else -> 0 // Passing 0 to setImageResource will clear the image view.
}
view.findViewById<ImageView>(R.id.badge).setImageResource(badge)
// Set the title and snippet for the custom info window
val title: String? = marker.title
val titleUi = view.findViewById<TextView>(R.id.title)
if (title != null) {
// Spannable string allows us to edit the formatting of the text.
titleUi.text = SpannableString(title).apply {
setSpan(ForegroundColorSpan(Color.RED), 0, length, 0)
}
} else {
titleUi.text = ""
}
val snippet: String? = marker.snippet
val snippetUi = view.findViewById<TextView>(R.id.snippet)
if (snippet != null && snippet.length > 12) {
snippetUi.text = SpannableString(snippet).apply {
setSpan(ForegroundColorSpan(Color.MAGENTA), 0, 10, 0)
setSpan(ForegroundColorSpan(Color.BLUE), 12, snippet.length, 0)
}
} else {
snippetUi.text = ""
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.marker_demo)
topText = findViewById(R.id.top_text)
rotationBar = findViewById<SeekBar>(R.id.rotationSeekBar).apply {
max = 360
setOnSeekBarChangeListener(object: OnSeekBarChangeListener {
/** Called when the Rotation progress bar is moved */
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
val rotation = seekBar?.progress?.toFloat()
checkReadyThen { markerRainbow.map { it.rotation = rotation ?: 0f } }
}
override fun onStartTrackingTouch(p0: SeekBar?) {
// do nothing
}
override fun onStopTrackingTouch(p0: SeekBar?) {
//do nothing
}
} )
}
flatBox = findViewById(R.id.flat)
options = findViewById<RadioGroup>(R.id.custom_info_window_options).apply {
setOnCheckedChangeListener { _, _ ->
if (lastSelectedMarker?.isInfoWindowShown == true) {
// Refresh the info window when the info window's content has changed.
// must deal with the possibility that lastSelectedMarker has changed in
// another thread between the null check and this line, do this with !!
lastSelectedMarker?.showInfoWindow()
}
}
}
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
OnMapAndViewReadyListener(mapFragment, this)
}
/**
* This is the callback that is triggered when the GoogleMap has loaded and is ready for use
*/
override fun onMapReady(googleMap: GoogleMap?) {
// return early if the map was not initialised properly
map = googleMap ?: return
// create bounds that encompass every location we reference
val boundsBuilder = LatLngBounds.Builder()
// include all places we have markers for on the map
places.keys.map { place -> boundsBuilder.include(places.getValue(place)) }
val bounds = boundsBuilder.build()
with(map) {
// Hide the zoom controls as the button panel will cover it.
uiSettings.isZoomControlsEnabled = false
// Setting an info window adapter allows us to change the both the contents and
// look of the info window.
setInfoWindowAdapter(CustomInfoWindowAdapter())
// Set listeners for marker events. See the bottom of this class for their behavior.
setOnMarkerClickListener(this@MarkerDemoActivity)
setOnInfoWindowClickListener(this@MarkerDemoActivity)
setOnMarkerDragListener(this@MarkerDemoActivity)
setOnInfoWindowCloseListener(this@MarkerDemoActivity)
setOnInfoWindowLongClickListener(this@MarkerDemoActivity)
// Override the default content description on the view, for accessibility mode.
// Ideally this string would be localised.
setContentDescription("Map with lots of markers.")
moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50))
}
// Add lots of markers to the googleMap.
addMarkersToMap()
}
/**
* Show all the specified markers on the map
*/
private fun addMarkersToMap() {
val placeDetailsMap = mutableMapOf(
// Uses a coloured icon
"BRISBANE" to PlaceDetails(
position = places.getValue("BRISBANE"),
title = "Brisbane",
snippet = "Population: 2,074,200",
icon = BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)
),
// Uses a custom icon with the info window popping out of the center of the icon.
"SYDNEY" to PlaceDetails(
position = places.getValue("SYDNEY"),
title = "Sydney",
snippet = "Population: 4,627,300",
icon = BitmapDescriptorFactory.fromResource(R.drawable.arrow),
infoWindowAnchorX = 0.5f,
infoWindowAnchorY = 0.5f
),
// Will create a draggable marker. Long press to drag.
"MELBOURNE" to PlaceDetails(
position = places.getValue("MELBOURNE"),
title = "Melbourne",
snippet = "Population: 4,137,400",
draggable = true
),
// Use a vector drawable resource as a marker icon.
"ALICE_SPRINGS" to PlaceDetails(
position = places.getValue("ALICE_SPRINGS"),
title = "Alice Springs",
icon = vectorToBitmap(
R.drawable.ic_android, Color.parseColor("#A4C639"))
),
// More markers for good measure
"PERTH" to PlaceDetails(
position = places.getValue("PERTH"),
title = "Perth",
snippet = "Population: 1,738,800"
),
"ADELAIDE" to PlaceDetails(
position = places.getValue("ADELAIDE"),
title = "Adelaide",
snippet = "Population: 1,213,000"
)
)
// add 4 markers on top of each other in Darwin with varying z-indexes
(0 until 4).map {
placeDetailsMap.put(
"DARWIN ${it + 1}", PlaceDetails(
position = places.getValue("DARWIN"),
title = "Darwin Marker ${it + 1}",
snippet = "z-index initially ${it + 1}",
zIndex = it.toFloat()
)
)
}
// place markers for each of the defined locations
placeDetailsMap.keys.map {
with(placeDetailsMap.getValue(it)) {
map.addMarker(MarkerOptions()
.position(position)
.title(title)
.snippet(snippet)
.icon(icon)
.infoWindowAnchor(infoWindowAnchorX, infoWindowAnchorY)
.draggable(draggable)
.zIndex(zIndex))
}
}
// Creates a marker rainbow demonstrating how to create default marker icons of different
// hues (colors).
val numMarkersInRainbow = 12
(0 until numMarkersInRainbow).mapTo(markerRainbow) {
map.addMarker(MarkerOptions().apply{
position(LatLng(
-30 + 10 * Math.sin(it * Math.PI / (numMarkersInRainbow - 1)),
135 - 10 * Math.cos(it * Math.PI / (numMarkersInRainbow - 1))))
title("Marker $it")
icon(BitmapDescriptorFactory.defaultMarker((it * 360 / numMarkersInRainbow)
.toFloat()))
flat(flatBox.isChecked)
rotation(rotationBar.progress.toFloat())
})!!
}
}
/**
* Demonstrates converting a [Drawable] to a [BitmapDescriptor],
* for use as a marker icon.
*/
private fun vectorToBitmap(@DrawableRes id : Int, @ColorInt color : Int): BitmapDescriptor {
val vectorDrawable: Drawable? = ResourcesCompat.getDrawable(resources, id, null)
if (vectorDrawable == null) {
Log.e(TAG, "Resource not found")
return BitmapDescriptorFactory.defaultMarker()
}
val bitmap = Bitmap.createBitmap(vectorDrawable.intrinsicWidth,
vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
vectorDrawable.setBounds(0, 0, canvas.width, canvas.height)
DrawableCompat.setTint(vectorDrawable, color)
vectorDrawable.draw(canvas)
return BitmapDescriptorFactory.fromBitmap(bitmap)
}
/** Called when the Clear button is clicked. */
@Suppress("UNUSED_PARAMETER")
fun onClearMap(view: View) {
checkReadyThen { map.clear() }
}
/** Called when the Reset button is clicked. */
@Suppress("UNUSED_PARAMETER")
fun onResetMap(view: View) {
checkReadyThen {
map.clear()
addMarkersToMap()
}
}
/** Called when the Flat check box is checked or unchecked */
@Suppress("UNUSED_PARAMETER")
fun onToggleFlat(view: View) {
checkReadyThen { markerRainbow.map { marker -> marker.isFlat = flatBox.isChecked } }
}
//
// Marker related listeners.
//
override fun onMarkerClick(marker : Marker): Boolean {
// Markers have a z-index that is settable and gettable.
marker.zIndex += 1.0f
Toast.makeText(this, "${marker.title} z-index set to ${marker.zIndex}",
Toast.LENGTH_SHORT).show()
lastSelectedMarker = marker
if (marker.position == places.getValue("PERTH")) {
// This causes the marker at Perth to bounce into position when it is clicked.
val handler = Handler()
val start = SystemClock.uptimeMillis()
val duration = 1500
val interpolator = BounceInterpolator()
handler.post(object : Runnable {
override fun run() {
val elapsed = SystemClock.uptimeMillis() - start
val t = Math.max(
1 - interpolator.getInterpolation(elapsed.toFloat() / duration), 0f)
marker.setAnchor(0.5f, 1.0f + 2 * t)
// Post again 16ms later.
if (t > 0.0) {
handler.postDelayed(this, 16)
}
}
})
} else if (marker.position == places.getValue("ADELAIDE")) {
// This causes the marker at Adelaide to change color and alpha.
marker.apply {
setIcon(BitmapDescriptorFactory.defaultMarker(random.nextFloat() * 360))
alpha = random.nextFloat()
}
}
// We return false to indicate that we have not consumed the event and that we wish
// for the default behavior to occur (which is for the camera to move such that the
// marker is centered and for the marker's info window to open, if it has one).
return false
}
override fun onInfoWindowClick(marker : Marker) {
Toast.makeText(this, "Click Info Window", Toast.LENGTH_SHORT).show()
}
override fun onInfoWindowClose(marker : Marker) {
Toast.makeText(this, "Close Info Window", Toast.LENGTH_SHORT).show()
}
override fun onInfoWindowLongClick(marker : Marker) {
Toast.makeText(this, "Info Window long click", Toast.LENGTH_SHORT).show()
}
override fun onMarkerDragStart(marker : Marker) {
topText.text = getString(R.string.on_marker_drag_start)
}
override fun onMarkerDragEnd(marker : Marker) {
topText.text = getString(R.string.on_marker_drag_end)
}
override fun onMarkerDrag(marker : Marker) {
topText.text = getString(R.string.on_marker_drag, marker.position.latitude, marker.position.longitude)
}
/**
* Checks if the map is ready, the executes the provided lambda function
*
* @param stuffToDo the code to be executed if the map is ready
*/
private fun checkReadyThen(stuffToDo : () -> Unit) {
if (!::map.isInitialized) {
Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show()
} else {
stuffToDo()
}
}
}
public class MarkerDemoActivity extends AppCompatActivity implements
OnMarkerClickListener,
OnInfoWindowClickListener,
OnMarkerDragListener,
OnSeekBarChangeListener,
OnInfoWindowLongClickListener,
OnInfoWindowCloseListener,
OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener {
private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);
private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298);
private static final LatLng DARWIN = new LatLng(-12.4634, 130.8456);
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.952854, 115.857342);
private static final LatLng ALICE_SPRINGS = new LatLng(-24.6980, 133.8807);
/** Demonstrates customizing the info window and/or its contents. */
class CustomInfoWindowAdapter implements InfoWindowAdapter {
// These are both viewgroups containing an ImageView with id "badge" and two TextViews with id
// "title" and "snippet".
private final View mWindow;
private final View mContents;
CustomInfoWindowAdapter() {
mWindow = getLayoutInflater().inflate(R.layout.custom_info_window, null);
mContents = getLayoutInflater().inflate(R.layout.custom_info_contents, null);
}
@Override
public View getInfoWindow(Marker marker) {
if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_window) {
// This means that getInfoContents will be called.
return null;
}
render(marker, mWindow);
return mWindow;
}
@Override
public View getInfoContents(Marker marker) {
if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_contents) {
// This means that the default info contents will be used.
return null;
}
render(marker, mContents);
return mContents;
}
private void render(Marker marker, View view) {
int badge;
// Use the equals() method on a Marker to check for equals. Do not use ==.
if (marker.equals(mBrisbane)) {
badge = R.drawable.badge_qld;
} else if (marker.equals(mAdelaide)) {
badge = R.drawable.badge_sa;
} else if (marker.equals(mSydney)) {
badge = R.drawable.badge_nsw;
} else if (marker.equals(mMelbourne)) {
badge = R.drawable.badge_victoria;
} else if (marker.equals(mPerth)) {
badge = R.drawable.badge_wa;
} else if (marker.equals(mDarwin1)) {
badge = R.drawable.badge_nt;
} else if (marker.equals(mDarwin2)) {
badge = R.drawable.badge_nt;
} else if (marker.equals(mDarwin3)) {
badge = R.drawable.badge_nt;
} else if (marker.equals(mDarwin4)) {
badge = R.drawable.badge_nt;
} else {
// Passing 0 to setImageResource will clear the image view.
badge = 0;
}
((ImageView) view.findViewById(R.id.badge)).setImageResource(badge);
String title = marker.getTitle();
TextView titleUi = ((TextView) view.findViewById(R.id.title));
if (title != null) {
// Spannable string allows us to edit the formatting of the text.
SpannableString titleText = new SpannableString(title);
titleText.setSpan(new ForegroundColorSpan(Color.RED), 0, titleText.length(), 0);
titleUi.setText(titleText);
} else {
titleUi.setText("");
}
String snippet = marker.getSnippet();
TextView snippetUi = ((TextView) view.findViewById(R.id.snippet));
if (snippet != null && snippet.length() > 12) {
SpannableString snippetText = new SpannableString(snippet);
snippetText.setSpan(new ForegroundColorSpan(Color.MAGENTA), 0, 10, 0);
snippetText.setSpan(new ForegroundColorSpan(Color.BLUE), 12, snippet.length(), 0);
snippetUi.setText(snippetText);
} else {
snippetUi.setText("");
}
}
}
private GoogleMap mMap;
private Marker mPerth;
private Marker mSydney;
private Marker mBrisbane;
private Marker mAdelaide;
private Marker mMelbourne;
private Marker mDarwin1;
private Marker mDarwin2;
private Marker mDarwin3;
private Marker mDarwin4;
/**
* Keeps track of the last selected marker (though it may no longer be selected). This is
* useful for refreshing the info window.
*/
private Marker mLastSelectedMarker;
private final List<Marker> mMarkerRainbow = new ArrayList<Marker>();
private TextView mTopText;
private SeekBar mRotationBar;
private CheckBox mFlatBox;
private RadioGroup mOptions;
private final Random mRandom = new Random();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.marker_demo);
mTopText = (TextView) findViewById(R.id.top_text);
mRotationBar = (SeekBar) findViewById(R.id.rotationSeekBar);
mRotationBar.setMax(360);
mRotationBar.setOnSeekBarChangeListener(this);
mFlatBox = (CheckBox) findViewById(R.id.flat);
mOptions = (RadioGroup) findViewById(R.id.custom_info_window_options);
mOptions.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mLastSelectedMarker != null && mLastSelectedMarker.isInfoWindowShown()) {
// Refresh the info window when the info window's content has changed.
mLastSelectedMarker.showInfoWindow();
}
}
});
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
new OnMapAndViewReadyListener(mapFragment, this);
}
@Override
public void onMapReady(GoogleMap map) {
mMap = map;
// Hide the zoom controls as the button panel will cover it.
mMap.getUiSettings().setZoomControlsEnabled(false);
// Add lots of markers to the map.
addMarkersToMap();
// Setting an info window adapter allows us to change the both the contents and look of the
// info window.
mMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());
// Set listeners for marker events. See the bottom of this class for their behavior.
mMap.setOnMarkerClickListener(this);
mMap.setOnInfoWindowClickListener(this);
mMap.setOnMarkerDragListener(this);
mMap.setOnInfoWindowCloseListener(this);
mMap.setOnInfoWindowLongClickListener(this);
// Override the default content description on the view, for accessibility mode.
// Ideally this string would be localised.
mMap.setContentDescription("Map with lots of markers.");
LatLngBounds bounds = new LatLngBounds.Builder()
.include(PERTH)
.include(SYDNEY)
.include(ADELAIDE)
.include(BRISBANE)
.include(MELBOURNE)
.include(DARWIN)
.build();
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
}
private void addMarkersToMap() {
// Uses a colored icon.
mBrisbane = mMap.addMarker(new MarkerOptions()
.position(BRISBANE)
.title("Brisbane")
.snippet("Population: 2,074,200")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
// Uses a custom icon with the info window popping out of the center of the icon.
mSydney = mMap.addMarker(new MarkerOptions()
.position(SYDNEY)
.title("Sydney")
.snippet("Population: 4,627,300")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow))
.infoWindowAnchor(0.5f, 0.5f));
// Creates a draggable marker. Long press to drag.
mMelbourne = mMap.addMarker(new MarkerOptions()
.position(MELBOURNE)
.title("Melbourne")
.snippet("Population: 4,137,400")
.draggable(true));
// Place four markers on top of each other with differing z-indexes.
mDarwin1 = mMap.addMarker(new MarkerOptions()
.position(DARWIN)
.title("Darwin Marker 1")
.snippet("z-index 1")
.zIndex(1));
mDarwin2 = mMap.addMarker(new MarkerOptions()
.position(DARWIN)
.title("Darwin Marker 2")
.snippet("z-index 2")
.zIndex(2));
mDarwin3 = mMap.addMarker(new MarkerOptions()
.position(DARWIN)
.title("Darwin Marker 3")
.snippet("z-index 3")
.zIndex(3));
mDarwin4 = mMap.addMarker(new MarkerOptions()
.position(DARWIN)
.title("Darwin Marker 4")
.snippet("z-index 4")
.zIndex(4));
// A few more markers for good measure.
mPerth = mMap.addMarker(new MarkerOptions()
.position(PERTH)
.title("Perth")
.snippet("Population: 1,738,800"));
mAdelaide = mMap.addMarker(new MarkerOptions()
.position(ADELAIDE)
.title("Adelaide")
.snippet("Population: 1,213,000"));
// Vector drawable resource as a marker icon.
mMap.addMarker(new MarkerOptions()
.position(ALICE_SPRINGS)
.icon(vectorToBitmap(R.drawable.ic_android, Color.parseColor("#A4C639")))
.title("Alice Springs"));
// Creates a marker rainbow demonstrating how to create default marker icons of different
// hues (colors).
float rotation = mRotationBar.getProgress();
boolean flat = mFlatBox.isChecked();
int numMarkersInRainbow = 12;
for (int i = 0; i < numMarkersInRainbow; i++) {
Marker marker = mMap.addMarker(new MarkerOptions()
.position(new LatLng(
-30 + 10 * Math.sin(i * Math.PI / (numMarkersInRainbow - 1)),
135 - 10 * Math.cos(i * Math.PI / (numMarkersInRainbow - 1))))
.title("Marker " + i)
.icon(BitmapDescriptorFactory.defaultMarker(i * 360 / numMarkersInRainbow))
.flat(flat)
.rotation(rotation));
mMarkerRainbow.add(marker);
}
}
/**
* Demonstrates converting a {@link Drawable} to a {@link BitmapDescriptor},
* for use as a marker icon.
*/
private BitmapDescriptor vectorToBitmap(@DrawableRes int id, @ColorInt int color) {
Drawable vectorDrawable = ResourcesCompat.getDrawable(getResources(), id, null);
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
DrawableCompat.setTint(vectorDrawable, color);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
private boolean checkReady() {
if (mMap == null) {
Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
/** Called when the Clear button is clicked. */
public void onClearMap(View view) {
if (!checkReady()) {
return;
}
mMap.clear();
}
/** Called when the Reset button is clicked. */
public void onResetMap(View view) {
if (!checkReady()) {
return;
}
// Clear the map because we don't want duplicates of the markers.
mMap.clear();
addMarkersToMap();
}
/** Called when the Reset button is clicked. */
public void onToggleFlat(View view) {
if (!checkReady()) {
return;
}
boolean flat = mFlatBox.isChecked();
for (Marker marker : mMarkerRainbow) {
marker.setFlat(flat);
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (!checkReady()) {
return;
}
float rotation = seekBar.getProgress();
for (Marker marker : mMarkerRainbow) {
marker.setRotation(rotation);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Do nothing.
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// Do nothing.
}
//
// Marker related listeners.
//
@Override
public boolean onMarkerClick(final Marker marker) {
if (marker.equals(mPerth)) {
// This causes the marker at Perth to bounce into position when it is clicked.
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final long duration = 1500;
final Interpolator interpolator = new BounceInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = Math.max(
1 - interpolator.getInterpolation((float) elapsed / duration), 0);
marker.setAnchor(0.5f, 1.0f + 2 * t);
if (t > 0.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
} else if (marker.equals(mAdelaide)) {
// This causes the marker at Adelaide to change color and alpha.
marker.setIcon(BitmapDescriptorFactory.defaultMarker(mRandom.nextFloat() * 360));
marker.setAlpha(mRandom.nextFloat());
}
// Markers have a z-index that is settable and gettable.
float zIndex = marker.getZIndex() + 1.0f;
marker.setZIndex(zIndex);
Toast.makeText(this, marker.getTitle() + " z-index set to " + zIndex,
Toast.LENGTH_SHORT).show();
mLastSelectedMarker = marker;
// We return false to indicate that we have not consumed the event and that we wish
// for the default behavior to occur (which is for the camera to move such that the
// marker is centered and for the marker's info window to open, if it has one).
return false;
}
@Override
public void onInfoWindowClick(Marker marker) {
Toast.makeText(this, "Click Info Window", Toast.LENGTH_SHORT).show();
}
@Override
public void onInfoWindowClose(Marker marker) {
//Toast.makeText(this, "Close Info Window", Toast.LENGTH_SHORT).show();
}
@Override
public void onInfoWindowLongClick(Marker marker) {
Toast.makeText(this, "Info Window long click", Toast.LENGTH_SHORT).show();
}
@Override
public void onMarkerDragStart(Marker marker) {
mTopText.setText("onMarkerDragStart");
}
@Override
public void onMarkerDragEnd(Marker marker) {
mTopText.setText("onMarkerDragEnd");
}
@Override
public void onMarkerDrag(Marker marker) {
mTopText.setText("onMarkerDrag. Current Position: " + marker.getPosition());
}
}
Клонирование и запуск образцов приложений
Для локального запуска образца вам потребуется Git. Используйте команду ниже, чтобы клонировать образец приложения в хранилище.
git clone git@github.com:googlemaps-samples/android-samples.git
Импортируйте образец проекта в Android Studio:
- В Android Studio откройте меню Файл > Создать > Импортировать проект.
Перейдите в директорию, куда вы добавили хранилище, и выберите каталог проекта для Kotlin или Java.
- Kotlin:
PATH-REPO/android-samples/ApiDemos/kotlin
- Java:
PATH-REPO/android-samples/ApiDemos/java
- Kotlin:
- Нажмите кнопку Открыть. Android Studio создаст проект с помощью Gradle.
- Создайте пустой файл
secrets.properties
в том же каталоге, где хранится файл проектаlocal.properties
. Подробнее о том, как добавить в проект ключ API… Добавьте в
secrets.properties
следующую строку, заменив YOUR_API_KEY на значение вашего ключа API:MAPS_API_KEY=
YOUR_API_KEY - Запустите приложение.