Markers

اختَر النظام الأساسي: Android iOS JavaScript

تشير العلامات إلى مواقع فردية على الخريطة. يمكنك تخصيص علاماتك عن طريق تغيير اللون الافتراضي أو استبدال رمز العلامة بصورة مخصصة. يمكن أن توفر نوافذ المعلومات سياقًا إضافيًا للعلامة.

عيّنات تعليمات برمجية

يتضمن مستودع ApiDemos على GitHub نموذجًا يوضح ميزات العلامات المختلفة:

Kotlin

Java

مقدمة

تحدد العلامات المواقع على الخريطة. تستخدم العلامة الافتراضية رمزًا قياسيًا، شائعًا في شكل ومظهر خرائط Google. من الممكن تغيير لون الرمز أو صورته أو نقطة الارتساء عبر واجهة برمجة التطبيقات. العلامات هي كائنات من النوع Marker، وتتمّ إضافتها إلى الخريطة باستخدام طريقة GoogleMap.addMarker(markerOptions).

تم تصميم العلامات لتكون تفاعلية. تتلقّى أحداث click تلقائيًا، ويتم استخدامها غالبًا مع أدوات معالجة الأحداث لعرض نوافذ المعلومات. يؤدي ضبط خاصية draggable للعلامة على true إلى السماح للمستخدم بتغيير موضع العلامة. استخدم ضغطة طويلة لتنشيط القدرة على تحريك العلامة.

بشكل تلقائي، عندما ينقر مستخدم على محدّد موقع، يظهر شريط أدوات الخريطة في أسفل يسار الخريطة، ما يتيح للمستخدم الوصول بسرعة إلى تطبيق "خرائط Google" للأجهزة الجوّالة. ويمكنك إيقاف شريط الأدوات. لمزيد من المعلومات، اطّلِع على دليل عناصر التحكُّم.

بدء استخدام العلامات

تتناول هذه الحلقة من Maps Live أساسيات إضافة علامات إلى خريطتك باستخدام حزمة SDK للخرائط لنظام التشغيل 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.
مرساة
النقطة التي سيتم وضعها في الصورة والتي سيتم وضعها في موضع خط الطول والعرض للعلامة. يكون هذا الإعداد التلقائي هو منتصف الجزء السفلي من الصورة.
إصدار أولي
لتعيين تعتيم العلامة. يكون الإعداد التلقائي بالقيمة 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)
لإنشاء علامة مخصصة باستخدام اسم صورة نقطية في دليل مواد العرض.
fromBitmap(Bitmap image)
لإنشاء علامة مخصّصة من صورة نقطية
fromFile(String fileName)
لإنشاء رمز مخصّص باستخدام اسم ملف صورة نقطية موجود في وحدة التخزين الداخلية.
fromPath(String absolutePath)
لإنشاء علامة مخصصة من مسار ملف مطلق لصورة نقطية.
fromResource(int resourceId)
لإنشاء علامة مخصّصة باستخدام رقم تعريف المورد لصورة نقطية.

ينشئ المقتطف أدناه علامة برمز مخصّص.

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 هي 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 على أحداث النقر أدناه.

التعامل مع أحداث محدّد الموقع

تسمح لك واجهة برمجة تطبيقات الخرائط بالاستماع إلى أحداث محدّد الموقع والاستجابة لها. للاستماع إلى هذه الأحداث، يجب ضبط أداة معالجة الصوت المناسبة على عنصر GoogleMap الذي تنتمي إليه العلامات. عند وقوع الحدث على إحدى العلامات على الخريطة، سيتم استدعاء استدعاء المستمع مع تمرير كائن Marker المقابل كمَعلمة. لمقارنة عنصر Marker هذا بمرجعك الخاص بكائن Marker، يجب استخدام equals() وليس ==.

ويمكنك الاستماع إلى الأحداث التالية:

الأحداث الناتجة عن النقر على العلامات

يمكنك استخدام OnMarkerClickListener للاستماع إلى أحداث النقر على العلامة. لضبط هذه المستمع على الخريطة، اتصل بـ GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). عندما ينقر مستخدم على علامة، سيتم استدعاء onMarkerClick(Marker) وسيتم تمرير العلامة كوسيطة. تعرض هذه الطريقة قيمة منطقية تشير إلى ما إذا كنت قد استهلكت الحدث (أي أنك تريد إيقاف السلوك الافتراضي). وإذا عرضت false، سيتم تطبيق السلوك التلقائي بالإضافة إلى السلوك المخصّص. السلوك التلقائي لحدث النقر على محدّد الموقع هو عرض نافذة المعلومات الخاصة به (إذا كان ذلك متاحًا) وتحريك الكاميرا بحيث تتمركز العلامة على الخريطة.

تأثير مؤشر z على أحداث النقر:

  • عندما ينقر المستخدم على مجموعة من العلامات، يتم بدء حدث النقر للعلامة ذات أعلى مؤشر z.
  • يتم بدء حدث واحد على الأكثر لكل نقرة. وبعبارة أخرى، لا يتم تمرير النقرة إلى العلامات أو التراكبات الأخرى ذات قيم مؤشر z الأدنى.
  • يؤدي النقر على مجموعة من العلامات إلى تبديل النقرات اللاحقة بين هذه المجموعة واختيار كل منها على التوالي. يعطي ترتيب الدورة أولاً الأولوية لمؤشر z، ثم القرب من نقطة النقر.
  • إذا نقر المستخدم خارج إطار المجموعة، ستعيد واجهة برمجة التطبيقات حساب المجموعة وتعيد ضبط حالة دورة النقر بحيث تبدأ من البداية.
  • يقع حدث النقر خلال مجموعات العلامات على الأشكال والتراكبات الأخرى قبل إعادة تشغيل الدورة.
  • تعتبر العلامات فعليًا في مجموعة فهرس z منفصلة مقارنةً بالتراكبات أو الأشكال الأخرى (الخطوط المتعددة و/أو المضلّعات و/أو الدوائر و/أو تراكبات الأرض)، بغض النظر عن المؤشر z للتراكبات الأخرى. في حالة وجود عدة علامات أو تراكبات أو أشكال مركّبة فوق بعضها البعض، يتم تدوير حدث النقر عبر مجموعة العلامات أولاً، ثم يتم تشغيله للتراكبات أو الأشكال الأخرى القابلة للنقر، على أساس قيم فهرسة z.

أحداث سحب العلامات

يمكنك استخدام OnMarkerDragListener للاستماع إلى أحداث السحب على علامة. لضبط هذه المستمع على الخريطة، اتصل بـ GoogleMap.setOnMarkerDragListener. لسحب علامة، يجب على المستخدم الضغط مع الاستمرار على العلامة. عندما يزيل المستخدم إصبعه من الشاشة، فستبقى العلامة في هذا الموضع. عند سحب العلامة، يتم استدعاء onMarkerDragStart(Marker) في البداية. أثناء سحب العلامة، يتم استدعاء onMarkerDrag(Marker) باستمرار. في نهاية عملية السحب، يتم استدعاء onMarkerDragEnd(Marker). يمكنك الحصول على موضع محدّد الموقع في أي وقت عن طريق استدعاء Marker.getPosition().