خوشه بندی نشانه ها (Clustering) – کاتلین

مستندات جامع اندروید

نسخه 1.0.3

هدف از این بخش از پروژه بررسی نحوه فعال‌سازی و غیرفعال‌سازی خوشه بندی ( Clustering ) نشانه هاست. خوشه بندی زمانی کاربرد دارد که تعداد نشانه های موجود بر روی نقشه زیاد باشد و برای جلوگیری از شلوغی نقشه با تکنیک خوشه بندی، نشانه های نزدیک به هم را با هم ادغام می کنیم و در صورتی که زوم نقشه بر روی نشانه ها باشد آن ها را از حالت ادغام خارج میکنیم. این کار براحتی در sdk نقشه نشان بطور خودکار انجام می شود که نحوه فعال یا غیرفعالسازی آن را در ادامه توضیح می دهیم.

activity_marker_clustering.xml:

در این صفحه، علاوه بر المان نقشه نشان، یک ToggleButton برای فعال‌ یا غیرفعال کردن خوشه بندی وجود دارد.

            <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".activity.MarkerClustering">

    <org.neshan.mapsdk.MapView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:id="@+id/map"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <ToggleButton
        android:checked="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/toggle_button_text_color"
        android:textOff="خوشه بندی"
        android:textOn="خوشه بندی"
        android:elevation="8dp"
        android:paddingStart="8dp"
        android:paddingEnd="8dp"
        android:background="@drawable/toggle_button_bg"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        tools:targetApi="m"
        android:onClick="toggleClustering"/>

</androidx.constraintlayout.widget.ConstraintLayout>
        

MarkerClusteringActivity.kt:

متد initLayoutRefrences جهت مقداردهی اولیه تمامی المان‌های مربوط به رابط کاربری نوشته شده‌است. به دلیل این که لازم است تا المان اندرویدی نقشه نشان ابتدا به طور کامل ایجاد شود و سپس با آن تعامل برقرار شود (متدهای مختلف بر روی المان نقشه اجرا شود)، تمامی متدهای مربوط به رابط کاربری باید در متد onStart انجام شوند.

            override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_marker_clustering)
    }

    override fun onStart() {
        super.onStart()
        // everything related to ui is initialized here
        initLayoutReferences()
    }
        

پس از مقداردهی اولیه viewها یک رویداد کلیک ( OnMapClickListener ) بر روی نقشه تعریف می شود تا با هر کلیک بر روی نقشه یک نشانه جدید اضافه شود. نشانه جدید با کمک متد createMarker ساخته شده و با map.addMarker به نقشه اضافه می شود.

توضیحات نحوه ایجاد نشانه را می توانید در بخش افزودن نشانگر ببینید.

از طریق پارامتر boolean ی که متد createMarker دریافت میکند می توان با ارسال true به آن یک نشانگر قرمز و با ارسال false، یک نشانگر آبی توسط آن ایجاد کرد. پس با هر بار کلیک بر روی نقشه یک نشانگر قرمز و بار هر بار کلیک طولانی روی نقشه، یک نشانگر آبی به نقشه اضافه می شود. همچنین متد map.addMarker در اینجا با یک پارامتر false برای ورودی clusterable صدا زده می شود. این کار باعث میشود نشانگرهای اضافه شده به این شکل شامل خوشه بندی ( clustering ) نشوند. و در آخر یک رویداد setOnMarkerClickListener برای نقشه تعریف شده که با کلیک بر روی هر نشانگر صدا زده می شود و با استفاده از متد map.removeMarker نشانگر مربوطه را از روی نقشه حذف می کند.

                // Initializing layout references (views, map and map events)
    private fun initLayoutReferences() {
        // Initializing views
        initViews()
        // Initializing mapView element
        initMap()

        // when clicked on map, a red marker will added in clicked location on map and it's clusterable
        map.setOnMapClickListener { latLng: LatLng ->
            map.addMarker(createMarker(latLng, true))
        }

        // when long click on map, a blue marker will added to clicked location on map and it's not clusterable
        map.setOnMapLongClickListener {
            map.addMarker(createMarker(it, false), false)
        }

        // Remove marker when click on it
        map.setOnMarkerClickListener {
            map.removeMarker(it)
        }
    }

// This method gets a LatLng as input and adds a marker on that position
    private fun createMarker(loc: LatLng, clusterable: Boolean): Marker {
        // Creating animation for marker. We should use an object of type AnimationStyleBuilder, set
        // all animation features on it and then call buildStyle() method that returns an object of type
        // AnimationStyle
        val animStBl = AnimationStyleBuilder()
        animStBl.fadeAnimationType = AnimationType.ANIMATION_TYPE_SMOOTHSTEP
        animStBl.sizeAnimationType = AnimationType.ANIMATION_TYPE_SPRING
        animStBl.phaseInDuration = 0.5f
        animStBl.phaseOutDuration = 0.5f
        animSt = animStBl.buildStyle()

        // Creating marker style. We should use an object of type MarkerStyleCreator, set all features on it
        // and then call buildStyle method on it. This method returns an object of type MarkerStyle
        val markStCr = MarkerStyleBuilder()
        markStCr.size = 30f
        if (clusterable) {
            markStCr.bitmap = BitmapUtils.createBitmapFromAndroidBitmap(
                BitmapFactory.decodeResource(
                    resources,
                    R.drawable.ic_marker
                )
            )
        } else {
            markStCr.bitmap = BitmapUtils.createBitmapFromAndroidBitmap(
                BitmapFactory.decodeResource(
                    resources,
                    R.drawable.ic_marker_blue
                )
            )
        }
        // AnimationStyle object - that was created before - is used here
        markStCr.animationStyle = animSt
        val markSt = markStCr.buildStyle()

        // Creating marker
        return Marker(loc, markSt)
    }
        

متد toggleClustering که با هر بار کلیک بر روی toggleButton صدا زده می شود، بررسی می‌ کند که اگر toggleButton موجود در رابط کاربری در حالت انتخاب شده باشد، خوشه بندی نشانه ها با استفاده از متد map.settings.isMarkerClusteringEnabled = true فعال می شود و در غیر اینصورت این متد با مقدار false فراخوانی شده و در نتیجه خوشه بندی غیرفعال می شود.

            fun toggleClustering(view: View) {
        val toggleButton = view as ToggleButton
        map.settings.isMarkerClusteringEnabled = toggleButton.isChecked
    }
        

فهرست مطالب این صفحه

فهرست مطالب این صفحه