تشير العلامات إلى مواقع جغرافية فردية على الخريطة. يمكنك تخصيص العلامات عن طريق تغيير اللون التلقائي أو استبدال رمز العلامة بأحد الصور المخصّصة. يمكن أن توفّر نوافذ المعلومات سياقًا إضافيًا للعلامة.
عيّنات تعليمات برمجية
يتضمّن مستودع ApiDemos على GitHub ملفًا برمجيًا نموذجيًا يعرض ميزات العلامات المختلفة:
Kotlin
- MapWithMarker: خريطة بسيطة تتضمّن علامة. اطّلِع على الدليل التمهيدي عن إضافة خريطة باستخدام علامة kt.
- MarkerDemoActivity: استخدام العلامات على خريطة، بما في ذلك الخيارات والمستمعين
Java
- MapWithMarker: خريطة بسيطة تتضمّن علامة اطّلِع على الدليل التمهيدي عن إضافة خريطة تتضمّن علامة.
- MarkerDemoActivity: استخدام العلامات على خريطة، بما في ذلك الخيارات والمستمعين
مقدمة
تحدِّد العلامات المواقع الجغرافية على الخريطة. يستخدم العلامة التلقائية رمزًا قياسيًا
، وهو رمز شائع في مظهر "خرائط Google" وأسلوبها. من الممكن تغيير
لون الرمز أو صورته أو نقطة ربطه من خلال واجهة برمجة التطبيقات. العلامات هي عناصر من النوع
Marker
، ويتمّ إضافتها إلى الخريطة باستخدام الأسلوب
GoogleMap.addMarker(markerOptions)
.
تم تصميم العلامات لتكون تفاعلية. تتلقّى هذه العناصر أحداث click
تلقائيًا، ويتم استخدامها غالبًا مع أدوات معالجة الأحداث لعرض معلومات
في النوافذ. يؤدي ضبط سمة draggable
للعلامة على true
إلى السماح للمستخدم بتغيير موضع العلامة. استخدِم الضغط مع الاستمرار ل activation تفعيل إمكانية تحريك العلامة.
بشكلٍ تلقائي، عندما ينقر المستخدم على علامة، يظهر شريط أدوات الخريطة في أسفل يسار الخريطة، ما يتيح للمستخدم الوصول بسرعة إلى تطبيق "خرائط Google" للأجهزة الجوّالة. يمكنك إيقاف شريط الأدوات. لمزيد من المعلومات، يمكنك الاطّلاع على دليل عناصر التحكّم.
بدء استخدام العلامات
تتناول هذه الحلقة من برنامج Maps Live أساسيات إضافة علامات إلى خريطتك باستخدام حزمة تطوير البرامج (SDK) لتطبيق "خرائط Google" لنظام التشغيل Android.
إضافة علامة
يوضّح المثال التالي كيفية إضافة علامة إلى خريطة. تم إنشاء العلامة عند الإحداثيات -33.852,151.211
(سيدني، أستراليا)، وتعرض السلسلة "علامة في سيدني" في نافذة معلومات عند النقر عليها.
Kotlin
override fun onMapReady(googleMap: GoogleMap) { // Add a marker in Sydney, Australia, // and move the map's camera to the same location. val sydney = LatLng(-33.852, 151.211) googleMap.addMarker( MarkerOptions() .position(sydney) .title("Marker in Sydney") ) googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)) }
Java
@Override public void onMapReady(GoogleMap googleMap) { // Add a marker in Sydney, Australia, // and move the map's camera to the same location. LatLng sydney = new LatLng(-33.852, 151.211); googleMap.addMarker(new MarkerOptions() .position(sydney) .title("Marker in Sydney")); googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); }
عرض معلومات إضافية عن علامة
من المتطلبات الشائعة عرض معلومات إضافية عن مكان أو موقع جغرافي عندما ينقر المستخدم على علامة على الخريطة. اطّلِع على دليل استخدام نوافذ المعلومات.
ربط البيانات بعلامة
يمكنك تخزين عنصر بيانات عشوائي باستخدام علامة باستخدام Marker.setTag()
،
واسترداد عنصر البيانات باستخدام Marker.getTag()
. يوضّح المثال أدناه كيفية
احتساب عدد المرات التي تم فيها النقر على علامة باستخدام العلامات:
Kotlin
/** * A demo class that stores and retrieves data objects with each marker. */ class MarkerDemoActivity : AppCompatActivity(), OnMarkerClickListener, OnMapReadyCallback { private val PERTH = LatLng(-31.952854, 115.857342) private val SYDNEY = LatLng(-33.87365, 151.20689) private val BRISBANE = LatLng(-27.47093, 153.0235) private var markerPerth: Marker? = null private var markerSydney: Marker? = null private var markerBrisbane: Marker? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_markers) val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment!!.getMapAsync(this) } /** Called when the map is ready. */ override fun onMapReady(map: GoogleMap) { // Add some markers to the map, and add a data object to each marker. markerPerth = map.addMarker( MarkerOptions() .position(PERTH) .title("Perth") ) markerPerth?.tag = 0 markerSydney = map.addMarker( MarkerOptions() .position(SYDNEY) .title("Sydney") ) markerSydney?.tag = 0 markerBrisbane = map.addMarker( MarkerOptions() .position(BRISBANE) .title("Brisbane") ) markerBrisbane?.tag = 0 // Set a listener for marker click. map.setOnMarkerClickListener(this) } /** Called when the user clicks a marker. */ override fun onMarkerClick(marker: Marker): Boolean { // Retrieve the data from the marker. val clickCount = marker.tag as? Int // Check if a click count was set, then display the click count. clickCount?.let { val newClickCount = it + 1 marker.tag = newClickCount Toast.makeText( this, "${marker.title} has been clicked $newClickCount times.", Toast.LENGTH_SHORT ).show() } // 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 } }
Java
/** * A demo class that stores and retrieves data objects with each marker. */ public class MarkerDemoActivity extends AppCompatActivity implements GoogleMap.OnMarkerClickListener, OnMapReadyCallback { private final LatLng PERTH = new LatLng(-31.952854, 115.857342); private final LatLng SYDNEY = new LatLng(-33.87365, 151.20689); private final LatLng BRISBANE = new LatLng(-27.47093, 153.0235); private Marker markerPerth; private Marker markerSydney; private Marker markerBrisbane; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_markers); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); } /** Called when the map is ready. */ @Override public void onMapReady(GoogleMap map) { // Add some markers to the map, and add a data object to each marker. markerPerth = map.addMarker(new MarkerOptions() .position(PERTH) .title("Perth")); markerPerth.setTag(0); markerSydney = map.addMarker(new MarkerOptions() .position(SYDNEY) .title("Sydney")); markerSydney.setTag(0); markerBrisbane = map.addMarker(new MarkerOptions() .position(BRISBANE) .title("Brisbane")); markerBrisbane.setTag(0); // Set a listener for marker click. map.setOnMarkerClickListener(this); } /** Called when the user clicks a marker. */ @Override public boolean onMarkerClick(final Marker marker) { // Retrieve the data from the marker. Integer clickCount = (Integer) marker.getTag(); // Check if a click count was set, then display the click count. if (clickCount != null) { clickCount = clickCount + 1; marker.setTag(clickCount); Toast.makeText(this, marker.getTitle() + " has been clicked " + clickCount + " times.", Toast.LENGTH_SHORT).show(); } // 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; } }
في ما يلي بعض الأمثلة على السيناريوهات التي يكون فيها من المفيد تخزين البيانات واستردادها باستخدام العلامات:
- قد يقدّم تطبيقك أنواعًا مختلفة من العلامات، ويمكنك التعامل معها
بشكل مختلف عندما ينقر عليها المستخدم. ولإجراء ذلك، يمكنك تخزين ملف
String
مع العلامة التي تشير إلى النوع. - قد تكون تتعامل مع نظام يتضمّن معرّفات سجلّات فريدة، ويمثّل فيه العلامات سجلّات معيّنة في ذلك النظام.
- قد تشير بيانات العلامة إلى الأولوية التي يجب استخدامها عند تحديد الفهرس z لعلامة معيّنة.
جعل العلامة قابلة للسحب
يمكنك تغيير موضع علامة بعد إضافتها إلى الخريطة طالما تم ضبط الخاصية
draggable
على true
. اضغط مع الاستمرار على العلامة لتفعيل
السحب. عند رفع إصبعك عن الشاشة، سيظلّ العلامة في
هذا الموضع.
لا يمكن سحب العلامات تلقائيًا. يجب ضبط العلامة صراحةً لتكون
قابلة للسحب إما باستخدام MarkerOptions.draggable(boolean)
قبل إضافتها إلى
الخريطة، أو Marker.setDraggable(boolean)
بعد إضافتها إلى الخريطة.
يمكنك الاستماع إلى أحداث السحب على العلامة، كما هو موضّح في أحداث سحب العلامة.
يضيف المقتطف أدناه علامة قابلة للسحب في بيرث، أستراليا.
Kotlin
val perthLocation = LatLng(-31.90, 115.86) val perth = map.addMarker( MarkerOptions() .position(perthLocation) .draggable(true) )
Java
final LatLng perthLocation = new LatLng(-31.90, 115.86); Marker perth = map.addMarker( new MarkerOptions() .position(perthLocation) .draggable(true));
تخصيص علامة
يعرض هذا الفيديو طرق استخدام العلامات لتصور المواقع الجغرافية على الخريطة.
يمكن أن تحدِّد العلامات صورة مخصّصة لعرضها بدلاً من الرمز التلقائي. يتضمن تحديد رمز ضبط عدد من السمات التي تؤثّر في السلوك المرئي للعلامة.
تتيح العلامات التخصيص من خلال السمات التالية:
- الموضع (مطلوب)
- قيمة
LatLng
لموضع العلامة على الخريطة هذه هي السمة الوحيدة المطلوبة لعنصرMarker
. - نقطة إرساء
- النقطة على الصورة التي سيتم وضعها في موضع LatLng للعلامة يكون هذا الخيار تلقائيًا في منتصف أسفل الصورة.
- إصدار أولي
- يضبط مستوى التعتيم للعلامة. القيمة التلقائية هي 1.0.
- العنوان
- سلسلة يتم عرضها في نافذة المعلومات عندما ينقر المستخدم على العلامة
- المقتطف
- نص إضافي يظهر أسفل العنوان
- الرمز
- صورة نقطية يتم عرضها بدلاً من صورة العلامة التلقائية
- قابل للسحب
- اضبط القيمة على
true
إذا كنت تريد السماح للمستخدم بتحريك العلامة. الإعداد التلقائي هوfalse
. - مرئي
- اضبط القيمة على
false
لإخفاء العلامة. الإعداد التلقائي هوtrue
. - الاتجاه الأفقي أو الاتجاه العمودي للإعلانات على اللوحات
- بشكلٍ تلقائي، تستخدم العلامات اتجاه لوحة الإعلانات، ما يعني أنّه يتم رسمها على شاشة الجهاز بدلاً من سطح الخريطة. لا يؤدي تدوير الخريطة أو إمالتها أو تكبيرها أو تصغيرها إلى تغيير اتجاه العلامة. يمكنك ضبط اتجاه العلامة ليكون مسطّحًا على سطح الأرض. تدور العلامات المسطّحة عند تدوير الخريطة، وتتغيّر طريقة عرضها عند إمالة الخريطة. كما هو الحال مع علامات لوحات الإعلانات، تحتفظ العلامات المسطّحة بحجمها عند تكبير الخريطة أو تصغيرها.
- تدوير
- اتجاه العلامة، المحدّد بالدرجات في اتجاه عقارب الساعة يتغيّر الموضع التلقائي إذا كانت العلامة مسطّحة. يكون الموضع التلقائي لمحدّد مسطح مُحاذاً للشمال. عندما لا يكون العلامة مسطّحة، يكون الوضع التلقائي للعلامة موجهًا للأعلى ويتم الدوران بحيث تكون العلامة في مواجهة الكاميرا دائمًا.
ينشئ المقتطف أدناه علامة بسيطة باستخدام الرمز التلقائي.
Kotlin
val melbourneLocation = LatLng(-37.813, 144.962) val melbourne = map.addMarker( MarkerOptions() .position(melbourneLocation) )
Java
final LatLng melbourneLocation = new LatLng(-37.813, 144.962); Marker melbourne = map.addMarker( new MarkerOptions() .position(melbourneLocation));
تخصيص لون العلامة
من الممكن تخصيص لون صورة العلامة التلقائية من خلال تمرير عنصر
BitmapDescriptor
إلى الطريقة icon(). يمكنك استخدام مجموعة من
الألوان المحدّدة مسبقًا في عنصر BitmapDescriptorFactory
، أو ضبط لون علامة مخصّص باستخدام الطريقة
BitmapDescriptorFactory.defaultMarker(float hue)
. درجة اللون هي قيمة تتراوح بين 0 و360، وتمثّل النقاط على عجلة الألوان.
Kotlin
val melbourneLocation = LatLng(-37.813, 144.962) val melbourne = map.addMarker( MarkerOptions() .position(melbourneLocation) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)) )
Java
final LatLng melbourneLocation = new LatLng(-37.813, 144.962); Marker melbourne = map.addMarker( new MarkerOptions() .position(melbourneLocation) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
تخصيص مستوى التعتيم للعلامة
يمكنك التحكّم في مستوى شفافية العلامة باستخدام الطريقة MarkerOptions.alpha(). يجب تحديد قيمة "الشفافية" كقيمة عائمة بين 0.0 و1.0، حيث يكون 0 شفافيًا بالكامل و1 غير شفاف بالكامل.
Kotlin
val melbourneLocation = LatLng(-37.813, 144.962) val melbourne = map.addMarker( MarkerOptions() .position(melbourneLocation) .alpha(0.7f) )
Java
final LatLng melbourneLocation = new LatLng(-37.813, 144.962); Marker melbourne = map.addMarker(new MarkerOptions() .position(melbourneLocation) .alpha(0.7f));
تخصيص صورة العلامة
يمكنك استبدال صورة العلامة التلقائية بصورة علامة مخصّصة، والتي يُشار إليها غالبًا باسم رمز. يتم دائمًا ضبط الرموز المخصّصة على أنّها BitmapDescriptor
، ويتم تحديدها باستخدام إحدى الطرق في فئة
BitmapDescriptorFactory
.
fromAsset(String assetName)
- تُنشئ علامة مخصّصة باستخدام اسم صورة Bitmap في دليل مواد العرض.
fromBitmap(Bitmap image)
- تُنشئ علامة مخصّصة من صورة بتنسيق Bitmap.
fromFile(String fileName)
- إنشاء رمز مخصّص باستخدام اسم ملف صورة بتنسيق Bitmap في ملف التخزين الداخلي
fromPath(String absolutePath)
- تُنشئ علامة مخصّصة من مسار ملف مطلق لصورة بتنسيق Bitmap.
fromResource(int resourceId)
- تُنشئ علامة مخصّصة باستخدام رقم تعريف المورد لصورة بتنسيق Bitmap.
تنشئ المقتطفة أدناه علامة باستخدام رمز مخصّص.
Kotlin
val melbourneLocation = LatLng(-37.813, 144.962) val melbourne = map.addMarker( MarkerOptions() .position(melbourneLocation) .title("Melbourne") .snippet("Population: 4,137,400") .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)) )
Java
final LatLng melbourneLocation = new LatLng(-37.813, 144.962); Marker melbourne = map.addMarker( new MarkerOptions() .position(melbourneLocation) .title("Melbourne") .snippet("Population: 4,137,400") .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));
تسطيح علامة
يتم عادةً رسم رموز العلامات بالنسبة إلى الشاشة، ولن يؤدي تدوير الخريطة أو إمالتها أو تكبيرها أو تصغيرها إلى تغيير اتجاه العلامة. يمكنك ضبط اتجاه العلامة ليكون مسطّحًا على سطح الأرض. إنّ العلامات التي يتم توجيهها بهذه الطريقة ستتحوّل عند تدوير الخريطة، وستتغيّر منظور مشاهدتها عند إمالة الخريطة. ستحتفظ العلامات المسطّحة بحجمها عند تكبير الخريطة أو تصغيرها.
لتغيير اتجاه العلامة، اضبط سمة flat
للعلامة على
true
.
Kotlin
val perthLocation = LatLng(-31.90, 115.86) val perth = map.addMarker( MarkerOptions() .position(perthLocation) .flat(true) )
Java
final LatLng perthLocation = new LatLng(-31.90, 115.86); Marker perth = map.addMarker( new MarkerOptions() .position(perthLocation) .flat(true));
تدوير علامة
يمكنك تدوير علامة حول نقطة التثبيت باستخدام الرمز
Marker
.setRotation()
. يتم قياس التدوير بالدرجات في اتجاه عقارب الساعة
من الوضع التلقائي. عندما تكون العلامة مسطّحة على الخريطة، يكون اتجاهها التلقائي هو الشمال. عندما لا يكون العلامة مسطّحة، يكون الوضع التلقائي موجهًا
للأعلى ويتم الدوران بحيث تكون العلامة موجّهة دائمًا نحو الكاميرا.
يدير المثال أدناه العلامة بزاوية 90 درجة. يؤدي ضبط نقطة الربط على
0.5,0.5
إلى تدوير العلامة حول مركزها بدلاً من
قاعدتها.
Kotlin
val perthLocation = LatLng(-31.90, 115.86) val perth = map.addMarker( MarkerOptions() .position(perthLocation) .anchor(0.5f, 0.5f) .rotation(90.0f) )
Java
final LatLng perthLocation = new LatLng(-31.90, 115.86); Marker perth = map.addMarker( new MarkerOptions() .position(perthLocation) .anchor(0.5f,0.5f) .rotation(90.0f));
فهرس z للعلامة
يحدِّد "فهرس z" ترتيب تجميع هذا المُحدِّد مقارنةً بالمُحدِّدات الأخرى
على الخريطة. يتم رسم علامة ذات مؤشر z مرتفع فوق العلامات التي تحتوي على مؤشرات z
أقل. القيمة التلقائية لمعلمة z-index هي 0
.
اضبط مؤشر z على عنصر خيارات العلامة من خلال استدعاء
MarkerOptions.zIndex()
، كما هو موضّح في مقتطف الرمز البرمجي التالي:
Kotlin
map.addMarker( MarkerOptions() .position(LatLng(10.0, 10.0)) .title("Marker z1") .zIndex(1.0f) )
Java
map.addMarker(new MarkerOptions() .position(new LatLng(10, 10)) .title("Marker z1") .zIndex(1.0f));
يمكنك الوصول إلى مؤشر z للعلامة من خلال استدعاء Marker.getZIndex()
، ويمكنك
تغييره من خلال استدعاء Marker.setZIndex()
.
يتم دائمًا رسم العلامات فوق طبقات المربّعات والعناصر المركّبة الأخرى غير العلامات (عناصر المركّبة للأرض والمضلّعات والأشكال الأخرى) بغض النظر عن رقم فهرس z للعناصر المركّبة الأخرى. تُعتبر العلامات في الواقع في مجموعة فهرس z منفصلة مقارنةً بالعناصر الأخرى التي تظهر على سطح الخريطة.
يمكنك الاطّلاع أدناه على تأثير z-index في أحداث النقر.
التعامل مع أحداث العلامات
تتيح لك Maps API الاستماع إلى أحداث العلامات والردّ عليها. لتلقّي إعلامات بشأن
هذه الأحداث، عليك ضبط المستمع المقابل في GoogleMap
العنصر الذي تنتمي إليه العلامات. عند وقوع الحدث في أحد
العلامات على الخريطة، سيتمّ استدعاء دالة الاستدعاء للمستمع مع تمرير كائن Marker
المقابل كمَعلمة. لمقارنة عنصر
Marker
هذا مع مرجعك الخاص لعنصر Marker
، يجب استخدام
equals()
وليس ==
.
يمكنك الاستماع إلى الأحداث التالية:
الأحداث الناتجة عن النقر على العلامات
يمكنك استخدام OnMarkerClickListener
للاستماع
إلى أحداث النقر على العلامة. لضبط هذا المستمع على الخريطة، اتصل بالرقم
GoogleMap.setOnMarkerClickListener(OnMarkerClickListener)
. عندما ينقر مستخدم على علامة، سيتمّ استدعاء onMarkerClick(Marker)
وسيتمّ تمرير العلامة
كوسيطة. تعرض هذه الطريقة قيمة منطقية تشير إلى
ما إذا كنت قد استخدمت الحدث (أي أنّك تريد إيقاف السلوك التلقائي
). إذا تم عرض القيمة false
، سيتم تنفيذ السلوك التلقائي بالإضافة إلى السلوك المخصّص. السلوك التلقائي لحدث النقر على علامة هو عرض نافذة المعلومات (إذا كانت متاحة) وتحريك الكاميرة بحيث تكون العلامة في منتصف الخريطة.
تأثير مقياس z-index في أحداث النقر:
- عندما ينقر مستخدم على مجموعة من العلامات، يتم بدء حدث النقر ل العلامة التي لها أعلى قيمة لسمة z-index.
- يتمّ بدء حدث واحد كحدّ أقصى لكلّ نقرة. بعبارة أخرى، لا يتم تمرير النقرة إلى العلامات أو العناصر الأخرى التي تظهر على سطح الخريطة والتي لها قيم أقل لسمة z-index.
- يؤدي النقر على مجموعة من العلامات إلى أن تنتقل النقرات اللاحقة بين المجموعة، مع اختيار كل علامة بدورها. يمنح ترتيب الدورة الأولوية أولاً لفهرس z، ثم للقُرب من نقطة النقر.
- إذا نقر المستخدم خارج نطاق المجموعة، تعيد واجهة برمجة التطبيقات احتساب المجموعة وتعيد ضبط حالة دورة النقر كي تبدأ من البداية.
- ينتقل حدث النقرة من خلال مجموعات العلامات إلى الأشكال الأخرى والعناصر التي تظهر على سطح الخريطة قبل إعادة بدء الدورة.
- تُعتبر العلامات في الواقع ضِمن مجموعة منفصلة لفهرس z مقارنةً بالأشكال أو العناصر الأخرى التي تظهر على سطح الخريطة (الخطوط المتعددة والأشكال الهندسية و/أو الدوائر و/أو العناصر التي تظهر على سطح الأرض)، بغض النظر عن فهرس z للعناصر الأخرى التي تظهر على سطح الخريطة. إذا تمّت تداخل عدة علامات أو أشكال أو عناصر مركّبة فوق بعضها، يتمّ تدوير حدث النقرة في مجموعة العلامات أولاً، ثمّ يتمّ تشغيله لأشكال أو عناصر مركّبة أخرى قابلة للنقر، استنادًا إلى قيم z-index.
أحداث سحب العلامات
يمكنك استخدام OnMarkerDragListener
للاستماع إلى
أحداث السحب على علامة. لضبط هذا المستمع على الخريطة، اتصل بالرقم
GoogleMap.setOnMarkerDragListener
. لنقل علامة، على المستخدم الضغط مع الاستمرار
على العلامة. عندما يرفع المستخدم إصبعه عن الشاشة،
سيظلّ العلامة في هذا الموضع. عند سحب علامة، يتم استدعاء onMarkerDragStart(Marker)
في البداية. أثناء سحب العلامة، يتم استدعاء onMarkerDrag(Marker)
باستمرار. في نهاية السحب، يتم استدعاء
onMarkerDragEnd(Marker)
. يمكنك الحصول على موضع العلامة في
أي وقت من خلال الاتصال بالرقم Marker.getPosition()
.