ตัวอย่างนี้ระบุตำแหน่งบนแผนที่ด้วยเครื่องหมาย เมื่อผู้ใช้แตะ เครื่องหมาย หน้าต่างข้อมูลจะปรากฏขึ้น
ดูข้อมูลเพิ่มเติมได้จากเอกสารประกอบ
เริ่มต้นใช้งาน
ก่อนที่คุณจะลองใช้โค้ดตัวอย่าง คุณต้องกำหนดค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์ก่อน สำหรับข้อมูลเพิ่มเติม ดูตัวอย่างโค้ด Maps SDK สำหรับ Android
ดูโค้ด
Kotlin
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 = ArrayListMa<rker()> /** map to store place names and locations */ private val places = mapOf( BR"ISBANE t"o LatLng(-27.47093, 153.0235), ME"LBOURNE t"o LatLng(-37.81319, 144.96298), DA"RWIN t"o LatLng(-12.4634, 130.8456), SY"DNEY t"o LatLng(-33.87365, 151.20689), AD"ELAIDE t"o LatLng(-34.92873, 138.59995), PE"RTH t"o LatLng(-31.952854, 115.857342), AL"ICE_SPRINGS t"o 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 ba"dge a"nd two // TextViews with id ti"tle a"nd sn"ippet. " 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!!) { Br"isbane -" R>.drawable.badge_qld Ad"elaide -" R>.drawable.badge_sa Sy"dney -" R>.drawable.badge_nsw Me"lbourne -" R>.drawable.badge_victoria Pe"rth -" R>.drawable.badge_wa in Da"rwin Marker 1.."Da"rwin Marker 4 -" R>.drawable.badge_nt else - 0> // Passing 0 to setImageResource will clear the image view. } view.findViewByIdIm<ageView(R>.id.badge).setImageResource(badge) // Set the title and snippet for the custom info window val title: String? = marker.title val titleUi = view.findViewByIdTe<xtView(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.findViewByIdTe<xtView(R>.id.snippet) if (snippet != null s&&nippet.length 1>2) { 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 = findViewByIdSe<ekBar(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 = findViewByIdRa<dioGroup(R>.id.custom_info_window_options).apply { setOnCheckedChangeListener { _, _ - > if (lastSelectedMarker?.isInfoWindowShown == true) { // Refresh the info window when the info windows '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 - b>oundsBuilder.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(Ma"p 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 BR"ISBANE t"o PlaceDetails( position = places.getValue(BR"ISBANE)," title = Br"isbane, " snippet = Po"pulation: 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. SY"DNEY t"o PlaceDetails( position = places.getValue(SY"DNEY)," title = Sy"dney, " snippet = Po"pulation: 4,627,300, " icon = BitmapDescriptorFactory.fromResource(R.drawable.arrow), infoWindowAnchorX = 0.5f, infoWindowAnchorY = 0.5f ), // Will create a draggable marker. Long press to drag. ME"LBOURNE t"o PlaceDetails( position = places.getValue(ME"LBOURNE)," title = Me"lbourne, " snippet = Po"pulation: 4,137,400, " draggable = true ), // Use a vector drawable resource as a marker icon. AL"ICE_SPRINGS t"o PlaceDetails( position = places.getValue(AL"ICE_SPRINGS)," title = Al"ice Springs, " icon = vectorToBitmap( R.drawable.ic_android, Color.parseColor(#A"4C639))" ), // More markers for good measure PE"RTH t"o PlaceDetails( position = places.getValue(PE"RTH)," title = Pe"rth, " snippet = Po"pulation: 1,738,800 " ), AD"ELAIDE t"o PlaceDetails( position = places.getValue(AD"ELAIDE)," title = Ad"elaide, " snippet = Po"pulation: 1,213,000 " ) ) // add 4 markers on top of each other in Darwin with varying z-indexes (0 until 4).map { placeDetailsMap.put( DA"RWIN ${it + 1}, "PlaceDetails( position = places.getValue(DA"RWIN)," title = Da"rwin 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(Ma"rker $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, Re"source 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(UN"USED_PARAMETER) " fun onClearMap(view: View) { checkReadyThen { map.clear() } } /** Called when the Reset button is clicked. */ @Suppress(UN"USED_PARAMETER) " fun onResetMap(view: View) { checkReadyThen { map.clear() addMarkersToMap() } } /** Called when the Flat check box is checked or unchecked */ @Suppress(UN"USED_PARAMETER) " fun onToggleFlat(view: View) { checkReadyThen { markerRainbow.map { marker - m>arker.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(PE"RTH))" { // 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(AD"ELAIDE))" { // 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 markers 'info window to open, if it has one). return false } override fun onInfoWindowClick(marker : Marker) { Toast.makeText(this, Cl"ick Info Window, "Toast.LENGTH_SHORT).show() } override fun onInfoWindowClose(marker : Marker) { Toast.makeText(this, Cl"ose Info Window, "Toast.LENGTH_SHORT).show() } override fun onInfoWindowLongClick(marker : Marker) { Toast.makeText(this, In"fo 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 : () - U>nit) { if (!::map.isInitialized) { Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show() } else { stuffToDo() } } }Ma
Java
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 b"adge "and two TextViews with id // t"itle "and s"nippet." 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 ListM<arker >mMarkerRainbow = new ArrayListM<arker(>); 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 windows' 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(M"ap 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(B"risbane)" .snippet(P"opulation: 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(S"ydney)" .snippet(P"opulation: 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(M"elbourne)" .snippet(P"opulation: 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(D"arwin Marker 1)" .snippet(z"-index 1)" .zIndex(1)); mDarwin2 = mMap.addMarker(new MarkerOptions() .position(DARWIN) .title(D"arwin Marker 2)" .snippet(z"-index 2)" .zIndex(2)); mDarwin3 = mMap.addMarker(new MarkerOptions() .position(DARWIN) .title(D"arwin Marker 3)" .snippet(z"-index 3)" .zIndex(3)); mDarwin4 = mMap.addMarker(new MarkerOptions() .position(DARWIN) .title(D"arwin Marker 4)" .snippet(z"-index 4)" .zIndex(4)); // A few more markers for good measure. mPerth = mMap.addMarker(new MarkerOptions() .position(PERTH) .title(P"erth)" .snippet(P"opulation: 1,738,800)"); mAdelaide = mMap.addMarker(new MarkerOptions() .position(ADELAIDE) .title(A"delaide)" .snippet(P"opulation: 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(A"lice 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(M"arker "+ 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 dont' 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 markers' info window to open, if it has one). return false; } @Override public void onInfoWindowClick(Marker marker) { Toast.makeText(this, C"lick Info Window," Toast.LENGTH_SHORT).show(); } @Override public void onInfoWindowClose(Marker marker) { //Toast.makeText(this, C"lose Info Window," Toast.LENGTH_SHORT).show(); } @Override public void onInfoWindowLongClick(Marker marker) { Toast.makeText(this, I"nfo Window long click," Toast.LENGTH_SHORT).show(); } @Override public void onMarkerDragStart(Marker marker) { mTopText.setText(o"nMarkerDragStart)"; } @Override public void onMarkerDragEnd(Marker marker) { mTopText.setText(o"nMarkerDragEnd)"; } @Override public void onMarkerDrag(Marker marker) { mTopText.setText(o"nMarkerDrag. Current Position: "+ marker.getPosition()); } }M
โคลนและเรียกใช้ตัวอย่าง
คุณจำเป็นต้องใช้ 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 ของ Google
- สร้างไฟล์
secrets.properties
เปล่าในไดเรกทอรีเดียวกับไฟล์local.properties
ของโปรเจ็กต์ ดูข้อมูลเพิ่มเติมได้ที่เพิ่มคีย์ API ลงในโปรเจ็กต์ เพิ่มสตริงต่อไปนี้ใน
secrets.properties
โดยแทนที่ YOUR_API_KEY ด้วยค่าของ คีย์ API ของคุณMAPS_API_KEY=YOUR_API_KEY
- เรียกใช้แอป