Markers

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

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

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

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

Kotlin

Java

مقدمة

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

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

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

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

تتناول هذه الحلقة من Maps Live أساسيات إضافة محددات المواقع إلى خريطتك باستخدام حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط 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.
نقطة إرساء
النقطة التي سيتم وضعها في موضع خط الطول والعرض للعلامة يتم تطبيق القيمة التلقائية في منتصف أسفل الصورة.
إصدار أولي
يضبط مستوى التعتيم للعلامة. القيمة التلقائية هي 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 التلقائية هي 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-index.
  • يتمّ بدء حدث واحد كحدّ أقصى لكلّ نقرة. بمعنى آخر، لا يتم تمرير النقرة إلى العلامات أو التراكبات الأخرى ذات قيم فهرس z المنخفضة.
  • يؤدي النقر على مجموعة من العلامات إلى أن تنتقل النقرات اللاحقة في دورة من المجموعة، مع اختيار كل علامة بدورها. يمنح ترتيب الدورة الأولوية أولاً لفهرس z، ثم للقُرب من نقطة النقر.
  • إذا نقر المستخدم خارج المجموعة القريبة من المجموعة، ستعيد واجهة برمجة التطبيقات حساب المجموعة وتعيد ضبط حالة دورة النقرات بحيث تبدأ من البداية.
  • يقع حدث النقر من خلال مجموعات العلامات على الأشكال والتراكبات الأخرى قبل إعادة بدء الدورة.
  • تُعتبر العلامات في الواقع ضِمن مجموعة منفصلة لترتيب طبقات البيانات حسب العمق مقارنةً بالأشكال أو العناصر الأخرى التي تظهر على سطح الخريطة (الخطوط المتعددة والأشكال الهندسية و/أو الدوائر و/أو العناصر التي تظهر على سطح الأرض)، بغض النظر عن ترتيب طبقات البيانات حسب العمق للعناصر الأخرى. في حال تركيب عدّة علامات أو تراكبات أو أشكال فوق بعضها البعض، تتم إدارة حدث النقر عبر مجموعة العلامات أولاً، ثم يتم تشغيله مع التراكبات أو الأشكال الأخرى القابلة للنقر، استنادًا إلى قيم مؤشر z.

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

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