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().