Markers

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

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

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

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

Kotlin

Java

مقدمة

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

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

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

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

تتناول هذه الحلقة من Maps Live أساسيات إضافة محددات المواقع إلى خريطتك باستخدام حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" لنظام التشغيل Android.

إضافة علامة

يوضح المثال التالي كيفية إضافة علامة إلى خريطة. يتم إنشاء العلامة في إحداثيات -33.852,151.211 (سيدني، أستراليا)، وتعرض السلسلة "Marker in Sydney" في نافذة معلومات عند النقر عليها.

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

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

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

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

أحداث النقر على محدّد الموقع

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

تأثير z-index على أحداث النقر:

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

أحداث سحب محدّد الموقع

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