আপনার অ্যান্ড্রয়েড অ্যাপে একটি মানচিত্র যোগ করুন (কোটলিন)

1. আপনি শুরু করার আগে

এই কোডল্যাব আপনাকে শেখায় কিভাবে আপনার অ্যাপের সাথে Android এর জন্য Maps SDK সংহত করতে হয় এবং সান ফ্রান্সিসকো, CA, USA-তে সাইকেলের দোকানগুলির একটি মানচিত্র প্রদর্শন করে এমন একটি অ্যাপ তৈরি করে এর মূল বৈশিষ্ট্যগুলি ব্যবহার করতে হয়৷

f05e1ca27ff42bf6.png

পূর্বশর্ত

  • কোটলিন এবং অ্যান্ড্রয়েড বিকাশের প্রাথমিক জ্ঞান

আপনি কি করবেন

  • একটি Android অ্যাপে Google মানচিত্র যুক্ত করতে Android এর জন্য Maps SDK সক্ষম করুন এবং ব্যবহার করুন৷
  • যোগ করুন, কাস্টমাইজ করুন, এবং ক্লাস্টার মার্কার।
  • মানচিত্রে পলিলাইন এবং বহুভুজ আঁকুন।
  • ক্যামেরার দৃষ্টিকোণ প্রোগ্রামিকভাবে নিয়ন্ত্রণ করুন।

আপনি কি প্রয়োজন হবে

2. সেট আপ করুন

নিম্নলিখিত সক্রিয়করণ পদক্ষেপের জন্য, আপনাকে Android এর জন্য মানচিত্র SDK সক্ষম করতে হবে৷

Google Maps প্ল্যাটফর্ম সেট আপ করুন

আপনার যদি ইতিমধ্যেই একটি Google ক্লাউড প্ল্যাটফর্ম অ্যাকাউন্ট না থাকে এবং বিলিং সক্ষম করা একটি প্রকল্প থাকে, তাহলে অনুগ্রহ করে একটি বিলিং অ্যাকাউন্ট এবং একটি প্রকল্প তৈরি করতে Google মানচিত্র প্ল্যাটফর্মের সাথে শুরু করা নির্দেশিকাটি দেখুন৷

  1. ক্লাউড কনসোলে , প্রকল্পের ড্রপ-ডাউন মেনুতে ক্লিক করুন এবং এই কোডল্যাবের জন্য আপনি যে প্রকল্পটি ব্যবহার করতে চান সেটি নির্বাচন করুন।

  1. Google ক্লাউড মার্কেটপ্লেসে এই কোডল্যাবের জন্য প্রয়োজনীয় Google মানচিত্র প্ল্যাটফর্ম API এবং SDK সক্ষম করুন৷ এটি করতে, এই ভিডিও বা এই ডকুমেন্টেশনের ধাপগুলি অনুসরণ করুন৷
  2. ক্লাউড কনসোলের শংসাপত্র পৃষ্ঠায় একটি API কী তৈরি করুন। আপনি এই ভিডিও বা এই ডকুমেন্টেশনের ধাপগুলি অনুসরণ করতে পারেন। Google মানচিত্র প্ল্যাটফর্মের সমস্ত অনুরোধের জন্য একটি API কী প্রয়োজন৷

3. দ্রুত শুরু

যত তাড়াতাড়ি সম্ভব আপনাকে শুরু করতে, এই কোডল্যাবের সাথে আপনাকে অনুসরণ করতে সহায়তা করার জন্য এখানে কিছু স্টার্টার কোড রয়েছে৷ সমাধানে ঝাঁপ দিতে আপনাকে স্বাগত জানাই, তবে আপনি যদি এটি নিজে তৈরি করার সমস্ত পদক্ষেপগুলি অনুসরণ করতে চান তবে পড়তে থাকুন।

  1. আপনি যদি git ইনস্টল করে থাকেন তবে সংগ্রহস্থল ক্লোন করুন।
git clone https://github.com/googlecodelabs/maps-platform-101-android.git

বিকল্পভাবে, আপনি সোর্স কোড ডাউনলোড করতে নিম্নলিখিত বোতামে ক্লিক করতে পারেন।

  1. কোড পাওয়ার পরে, এগিয়ে যান এবং অ্যান্ড্রয়েড স্টুডিওতে starter ডিরেক্টরির মধ্যে পাওয়া প্রকল্পটি খুলুন।

4. Google Maps যোগ করুন

এই বিভাগে, আপনি Google মানচিত্র যোগ করবেন যাতে আপনি অ্যাপটি চালু করার সময় এটি লোড হয়।

d1d068b5d4ae38b9.png

আপনার API কী যোগ করুন

আপনি একটি পূর্ববর্তী ধাপে যে API কী তৈরি করেছেন সেটি অ্যাপটিতে প্রদান করা প্রয়োজন যাতে Android এর জন্য Maps SDK আপনার অ্যাপের সাথে আপনার কী সংযুক্ত করতে পারে।

  1. এটি প্রদান করার জন্য, আপনার প্রকল্পের রুট ডিরেক্টরিতে local.properties নামক ফাইলটি খুলুন (একই স্তর যেখানে gradle.properties এবং settings.gradle আছে)।
  2. সেই ফাইলে, একটি নতুন কী GOOGLE_MAPS_API_KEY সংজ্ঞায়িত করুন যার মান আপনার তৈরি করা API কী।

local.properties

GOOGLE_MAPS_API_KEY=YOUR_KEY_HERE

লক্ষ্য করুন যে Git সংগ্রহস্থলের .gitignore ফাইলে local.properties তালিকাভুক্ত করা হয়েছে। কারণ আপনার API কী সংবেদনশীল তথ্য হিসেবে বিবেচিত হয় এবং সম্ভব হলে উৎস নিয়ন্ত্রণে চেক ইন করা উচিত নয়।

  1. এর পরে, আপনার API প্রকাশ করতে যাতে এটি আপনার অ্যাপ জুড়ে ব্যবহার করা যায়, app/ ডিরেক্টরিতে অবস্থিত আপনার অ্যাপের build.gradle ফাইলে Android প্লাগইনের জন্য সিক্রেটস গ্রেডল প্লাগইন অন্তর্ভুক্ত করুন এবং plugins ব্লকের মধ্যে নিম্নলিখিত লাইনটি যুক্ত করুন:

অ্যাপ-লেভেল build.gradle

plugins {
    // ...
    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}

নিম্নলিখিত ক্লাসপথ অন্তর্ভুক্ত করার জন্য আপনাকে আপনার প্রকল্প-স্তরের build.gradle ফাইলটিও সংশোধন করতে হবে:

প্রকল্প-স্তরের build.gradle

buildscript {
    dependencies {
        // ...
        classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:1.3.0"
    }
}

এই প্লাগইনটি আপনার local.properties ফাইলের মধ্যে সংজ্ঞায়িত কীগুলিকে অ্যান্ড্রয়েড ম্যানিফেস্ট ফাইলে বিল্ড ভেরিয়েবল এবং বিল্ড টাইমে গ্রেডল-জেনারেট করা BuildConfig ক্লাসে ভেরিয়েবল হিসাবে উপলব্ধ করবে৷ এই প্লাগইনটি ব্যবহার করা বয়লারপ্লেট কোডটি সরিয়ে দেয় যা অন্যথায় local.properties থেকে বৈশিষ্ট্যগুলি পড়ার জন্য প্রয়োজন হবে যাতে এটি আপনার অ্যাপ জুড়ে অ্যাক্সেস করা যায়।

Google Maps নির্ভরতা যোগ করুন

  1. এখন যেহেতু আপনার API কী অ্যাপের ভিতরে অ্যাক্সেস করা যেতে পারে, পরবর্তী ধাপ হল আপনার অ্যাপের build.gradle ফাইলে Android নির্ভরতার জন্য Maps SDK যোগ করা।

এই কোডল্যাবের সাথে আসা স্টার্টার প্রকল্পে, এই নির্ভরতা ইতিমধ্যেই আপনার জন্য যোগ করা হয়েছে।

build.gradle

dependencies {
   // Dependency to include Maps SDK for Android
   implementation 'com.google.android.gms:play-services-maps:17.0.0'
}
  1. এরপরে, আপনার আগের ধাপে তৈরি করা API কীটি পাস করতে AndroidManifest.xml এ একটি নতুন meta-data ট্যাগ যোগ করুন। এটি করার জন্য, এগিয়ে যান এবং এই ফাইলটি অ্যান্ড্রয়েড স্টুডিওতে খুলুন এবং আপনার AndroidManifest.xml ফাইলে application অবজেক্টের ভিতরে নিম্নলিখিত meta-data ট্যাগ যোগ করুন, যা app/src/main main-এ অবস্থিত।

AndroidManifest.xml

<meta-data
   android:name="com.google.android.geo.API_KEY"
   android:value="${GOOGLE_MAPS_API_KEY}" />
  1. এরপর, app/src/main/res/layout/ ডিরেক্টরিতে activity_main.xml নামে একটি নতুন লেআউট ফাইল তৈরি করুন এবং এটিকে নিম্নরূপ সংজ্ঞায়িত করুন:

activity_main.xml

<FrameLayout 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"
   tools:context=".MainActivity">

   <fragment
       class="com.google.android.gms.maps.SupportMapFragment"
       android:id="@+id/map_fragment"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</FrameLayout>

এই লেআউটে একটি FrameLayout ধারণকারী একটি একক SupportMapFragment আছে। এই খণ্ডটিতে অন্তর্নিহিত GoogleMaps অবজেক্ট রয়েছে যা আপনি পরবর্তী ধাপে ব্যবহার করেন।

  1. সবশেষে, onCreate পদ্ধতিকে ওভাররাইড করতে নিম্নলিখিত কোড যোগ করে app/src/main/java/com/google/codelabs/buildyourfirstmap এ অবস্থিত MainActivity ক্লাস আপডেট করুন যাতে আপনি এইমাত্র তৈরি করা নতুন লেআউটের সাথে এর বিষয়বস্তু সেট করতে পারেন।

প্রধান কাজ

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(R.layout.activity_main)
}
  1. এখন এগিয়ে যান এবং অ্যাপ্লিকেশন চালান. আপনি এখন আপনার ডিভাইসের স্ক্রিনে মানচিত্র লোড দেখতে পাবেন।

5. ক্লাউড-ভিত্তিক মানচিত্র স্টাইলিং (ঐচ্ছিক)

আপনি ক্লাউড-ভিত্তিক মানচিত্র স্টাইলিং ব্যবহার করে আপনার মানচিত্রের শৈলী কাস্টমাইজ করতে পারেন৷

একটি মানচিত্র আইডি তৈরি করুন

আপনি যদি এটির সাথে সম্পর্কিত একটি মানচিত্র শৈলী সহ একটি মানচিত্র আইডি তৈরি না করে থাকেন তবে নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করতে মানচিত্র আইডি নির্দেশিকাটি দেখুন:

  1. একটি মানচিত্র আইডি তৈরি করুন।
  2. একটি মানচিত্র শৈলীতে একটি মানচিত্র ID সংযুক্ত করুন৷

আপনার অ্যাপে ম্যাপ আইডি যোগ করা হচ্ছে

আপনার তৈরি করা মানচিত্র আইডি ব্যবহার করতে, activity_main.xml ফাইলটি সংশোধন করুন এবং SupportMapFragment এর map:mapId অ্যাট্রিবিউটে আপনার মানচিত্র আইডি পাস করুন।

activity_main.xml

<fragment xmlns:map="http://schemas.android.com/apk/res-auto"
    class="com.google.android.gms.maps.SupportMapFragment"
    <!-- ... -->
    map:mapId="YOUR_MAP_ID" />

একবার আপনি এটি সম্পূর্ণ করলে, এগিয়ে যান এবং আপনার নির্বাচিত স্টাইলে আপনার মানচিত্র দেখতে অ্যাপটি চালান!

6. মার্কার যোগ করুন

এই টাস্কে, আপনি মানচিত্রে চিহ্নিতকারী যোগ করেন যা আপনার আগ্রহের পয়েন্টগুলিকে প্রতিনিধিত্ব করে যা আপনি মানচিত্রে হাইলাইট করতে চান। প্রথমে, আপনি আপনার জন্য স্টার্টার প্রকল্পে দেওয়া জায়গাগুলির একটি তালিকা পুনরুদ্ধার করুন, তারপর সেই স্থানগুলিকে মানচিত্রে যোগ করুন। এই উদাহরণে, এগুলি সাইকেলের দোকান।

bc5576877369b554.png

গুগলম্যাপের একটি রেফারেন্স পান

প্রথমে, আপনাকে GoogleMap অবজেক্টের একটি রেফারেন্স পেতে হবে যাতে আপনি এর পদ্ধতিগুলি ব্যবহার করতে পারেন। এটি করার জন্য, setContentView() এ কল করার ঠিক পরে আপনার MainActivity.onCreate() পদ্ধতিতে নিম্নলিখিত কোড যোগ করুন:

MainActivity.onCreate()

val mapFragment = supportFragmentManager.findFragmentById(   
    R.id.map_fragment
) as? SupportMapFragment
mapFragment?.getMapAsync { googleMap ->
    addMarkers(googleMap)
}

বাস্তবায়নটি প্রথমে SupportMapFragment খুঁজে পায় যা আপনি SupportFragmentManager অবজেক্টে findFragmentById() পদ্ধতি ব্যবহার করে আগের ধাপে যোগ করেছেন। একবার একটি রেফারেন্স প্রাপ্ত হয়ে গেলে, একটি ল্যাম্বডায় পাস করার পরে getMapAsync() কলটি আহ্বান করা হয়। এই ল্যাম্বডা যেখানে GoogleMap অবজেক্ট পাস করা হয়। এই ল্যাম্বডার ভিতরে, addMarkers() পদ্ধতি কল আহ্বান করা হয়েছে, যা শীঘ্রই সংজ্ঞায়িত করা হয়েছে।

প্রদান করা ক্লাস: PlacesReader

স্টার্টার প্রকল্পে, আপনার জন্য ক্লাস PlacesReader প্রদান করা হয়েছে। এই ক্লাসটি 49টি স্থানের একটি তালিকা পড়ে যা একটি JSON ফাইলের মধ্যে সংরক্ষিত হয়, যাকে places.json বলা হয় এবং সেগুলিকে একটি List<Place> হিসেবে ফেরত দেয়। স্থানগুলি সান ফ্রান্সিসকো, CA, USA এর আশেপাশে সাইকেলের দোকানগুলির একটি তালিকা উপস্থাপন করে৷

আপনি যদি এই ক্লাসের বাস্তবায়ন সম্পর্কে আগ্রহী হন তবে আপনি এটিকে GitHub-এ অ্যাক্সেস করতে পারেন বা Android স্টুডিওতে PlacesReader ক্লাস খুলতে পারেন।

স্থানপাঠক

package com.google.codelabs.buildyourfirstmap.place

import android.content.Context
import com.google.codelabs.buildyourfirstmap.R
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.InputStream
import java.io.InputStreamReader

/**
* Reads a list of place JSON objects from the file places.json
*/
class PlacesReader(private val context: Context) {

   // GSON object responsible for converting from JSON to a Place object
   private val gson = Gson()

   // InputStream representing places.json
   private val inputStream: InputStream
       get() = context.resources.openRawResource(R.raw.places)

   /**
    * Reads the list of place JSON objects in the file places.json
    * and returns a list of Place objects
    */
   fun read(): List<Place> {
       val itemType = object : TypeToken<List<PlaceResponse>>() {}.type
       val reader = InputStreamReader(inputStream)
       return gson.fromJson<List<PlaceResponse>>(reader, itemType).map {
           it.toPlace()
       }
   }

স্থান লোড

সাইকেলের দোকানের তালিকা লোড করতে, MainActivity places নামক একটি সম্পত্তি যোগ করুন এবং এটিকে নিম্নরূপ সংজ্ঞায়িত করুন:

MainActivity.places

private val places: List<Place> by lazy {
   PlacesReader(this).read()
}

এই কোডটি একটি PlacesReaderread() পদ্ধতি চালু করে, যা একটি List<Place> প্রদান করে। একটি Place name , স্থানের নাম এবং একটি latLng নামক একটি সম্পত্তি রয়েছে - স্থানটি যেখানে অবস্থিত সেখানে স্থানাঙ্ক।

স্থান

data class Place(
   val name: String,
   val latLng: LatLng,
   val address: LatLng,
   val rating: Float
)

মানচিত্রে চিহ্নিতকারী যোগ করুন

এখন যেহেতু স্থানগুলির তালিকা মেমরিতে লোড করা হয়েছে, পরবর্তী পদক্ষেপটি মানচিত্রে এই স্থানগুলিকে উপস্থাপন করা।

  1. addMarkers() নামে MainActivity এ একটি পদ্ধতি তৈরি করুন এবং এটিকে নিম্নরূপ সংজ্ঞায়িত করুন:

MainActivity.addMarkers()

/**
* Adds marker representations of the places list on the provided GoogleMap object
*/
private fun addMarkers(googleMap: GoogleMap) {
   places.forEach { place ->
       val marker = googleMap.addMarker(
           MarkerOptions()
               .title(place.name)
               .position(place.latLng)
       )
   }
}

প্রদত্ত GoogleMap অবজেক্টে addMarker() পদ্ধতি ব্যবহার করে এই পদ্ধতিটি places তালিকার মাধ্যমে পুনরাবৃত্তি করে। মার্কারটি একটি MarkerOptions অবজেক্টকে ইনস্ট্যান্টিয়েট করে তৈরি করা হয়, যা আপনাকে মার্কারটিকেই কাস্টমাইজ করতে দেয়। এই ক্ষেত্রে, চিহ্নিতকারীর শিরোনাম এবং অবস্থান প্রদান করা হয়, যা যথাক্রমে সাইকেলের দোকানের নাম এবং এর স্থানাঙ্কগুলিকে প্রতিনিধিত্ব করে।

  1. এগিয়ে যান এবং অ্যাপটি চালান, এবং আপনি এইমাত্র যোগ করা মার্কারগুলি দেখতে সান ফ্রান্সিসকোতে যান!

7. মার্কার কাস্টমাইজ করুন

মার্কারগুলির জন্য বেশ কয়েকটি কাস্টমাইজেশন বিকল্প রয়েছে যা আপনি এইমাত্র যোগ করেছেন যাতে তাদের আলাদা হতে এবং ব্যবহারকারীদের কাছে দরকারী তথ্য পৌঁছে দিতে সহায়তা করে৷ এই টাস্কে, আপনি প্রতিটি মার্কারের ইমেজ কাস্টমাইজ করার সাথে সাথে একটি মার্কার ট্যাপ করার সময় প্রদর্শিত তথ্য উইন্ডোটি কাস্টমাইজ করে সেগুলির কিছু অন্বেষণ করবেন।

a26f82802fe838e9.png

একটি তথ্য উইন্ডো যোগ করা হচ্ছে

ডিফল্টরূপে, আপনি যখন একটি মার্কারে ট্যাপ করেন তখন তথ্য উইন্ডোটি তার শিরোনাম এবং স্নিপেট (যদি সেট থাকে) প্রদর্শন করে। আপনি এটি কাস্টমাইজ করুন যাতে এটি অতিরিক্ত তথ্য প্রদর্শন করতে পারে, যেমন স্থানের ঠিকানা এবং রেটিং।

marker_info_contents.xml তৈরি করুন

প্রথমে, marker_info_contents.xml নামে একটি নতুন লেআউট ফাইল তৈরি করুন।

  1. এটি করতে, Android স্টুডিওতে প্রজেক্ট ভিউতে app/src/main/res/layout ফোল্ডারে ডান ক্লিক করুন এবং New > Layout Resource File নির্বাচন করুন।

8cac51fcbef9171b.png

  1. ডায়ালগে, ফাইলের নামের ক্ষেত্রে LinearLayout এবং Root element ক্ষেত্রে marker_info_contents টাইপ করুন, তারপর ওকে ক্লিক করুন।

8783af12baf07a80.png

এই লেআউট ফাইলটি পরে ইনফো উইন্ডোর মধ্যে বিষয়বস্তু উপস্থাপন করার জন্য স্ফীত হয়।

  1. নিম্নলিখিত কোড স্নিপেটে বিষয়বস্তু অনুলিপি করুন, যা একটি উল্লম্ব LinearLayout ভিউ গ্রুপের মধ্যে তিনটি TextViews যোগ করে এবং ফাইলে ডিফল্ট কোডটি ওভাররাইট করে।

marker_info_contents.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:orientation="vertical"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:gravity="center_horizontal"
   android:padding="8dp">

   <TextView
       android:id="@+id/text_view_title"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textColor="@android:color/black"
       android:textSize="18sp"
       android:textStyle="bold"
       tools:text="Title"/>

   <TextView
       android:id="@+id/text_view_address"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textColor="@android:color/black"
       android:textSize="16sp"
       tools:text="123 Main Street"/>

   <TextView
       android:id="@+id/text_view_rating"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textColor="@android:color/black"
       android:textSize="16sp"
       tools:text="Rating: 3"/>

</LinearLayout>

একটি InfoWindowAdapter এর বাস্তবায়ন তৈরি করুন

কাস্টম তথ্য উইন্ডোর জন্য লেআউট ফাইল তৈরি করার পর, পরবর্তী ধাপ হল GoogleMap.InfoWindowAdapter ইন্টারফেস বাস্তবায়ন করা। এই ইন্টারফেসে দুটি পদ্ধতি রয়েছে, getInfoWindow() এবং getInfoContents() । উভয় পদ্ধতি একটি ঐচ্ছিক View অবজেক্ট ফেরত দেয় যেখানে পূর্বেরটি উইন্ডোটি নিজেই কাস্টমাইজ করতে ব্যবহৃত হয়, যখন পরবর্তীটি এর বিষয়বস্তু কাস্টমাইজ করতে ব্যবহৃত হয়। আপনার ক্ষেত্রে, আপনি উভয়ই বাস্তবায়ন করেন এবং getInfoWindow() এ নাল রিটার্ন করার সময় getInfoWindow() getInfoContents() এর রিটার্ন কাস্টমাইজ করেন, যা নির্দেশ করে যে ডিফল্ট উইন্ডো ব্যবহার করা উচিত।

  1. Android স্টুডিওতে প্রজেক্ট ভিউতে app/src/main/java/com/google/codelabs/buildyourfirstmap ফোল্ডারে ডান-ক্লিক করে MainActivity এর মতো একই প্যাকেজে MarkerInfoWindowAdapter নামে একটি নতুন Kotlin ফাইল তৈরি করুন, তারপর New > Kotlin File/Class নির্বাচন করুন .

3975ba36eba9f8e1.png

  1. ডায়ালগে, MarkerInfoWindowAdapter টাইপ করুন এবং ফাইল হাইলাইট রাখুন।

992235af53d3897f.png

  1. একবার আপনার ফাইলটি তৈরি হয়ে গেলে, নিম্নলিখিত কোড স্নিপেটের বিষয়বস্তুগুলি আপনার নতুন ফাইলে অনুলিপি করুন।

MarkerInfoWindowAdapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.Marker
import com.google.codelabs.buildyourfirstmap.place.Place

class MarkerInfoWindowAdapter(
    private val context: Context
) : GoogleMap.InfoWindowAdapter {
   override fun getInfoContents(marker: Marker?): View? {
       // 1. Get tag
       val place = marker?.tag as? Place ?: return null

       // 2. Inflate view and set title, address, and rating
       val view = LayoutInflater.from(context).inflate(
           R.layout.marker_info_contents, null
       )
       view.findViewById<TextView>(
           R.id.text_view_title
       ).text = place.name
       view.findViewById<TextView>(
           R.id.text_view_address
       ).text = place.address
       view.findViewById<TextView>(
           R.id.text_view_rating
       ).text = "Rating: %.2f".format(place.rating)

       return view
   }

   override fun getInfoWindow(marker: Marker?): View? {
       // Return null to indicate that the 
       // default window (white bubble) should be used
       return null
   }
}

getInfoContents() পদ্ধতির বিষয়বস্তুতে, পদ্ধতিতে প্রদত্ত মার্কারটিকে একটি Place টাইপে কাস্ট করা হয় এবং যদি কাস্ট করা সম্ভব না হয়, তাহলে পদ্ধতিটি শূন্য হয়ে যায় (আপনি এখনও Marker ট্যাগ বৈশিষ্ট্য সেট করেননি, কিন্তু আপনি পরবর্তী ধাপে এটি করুন)।

এর পরে, লেআউট marker_info_contents.xml স্ফীত হয় এবং তারপরে TextViews ধারণ করে Place ট্যাগে টেক্সট সেট করে।

MainActivity আপডেট করুন

আপনি এখন পর্যন্ত তৈরি করা সমস্ত উপাদান আঠালো করতে, আপনাকে আপনার MainActivity ক্লাসে দুটি লাইন যোগ করতে হবে।

প্রথমে, getMapAsync মেথড কলের ভিতরে কাস্টম InfoWindowAdapter , MarkerInfoWindowAdapter পাস করতে, GoogleMap অবজেক্টে setInfoWindowAdapter() পদ্ধতি চালু করুন এবং MarkerInfoWindowAdapter এর একটি নতুন উদাহরণ তৈরি করুন।

  1. getMapAsync() getMapAsync() এর ভিতরে addMarkers() মেথড কল করার পরে নিম্নলিখিত কোড যোগ করে এটি করুন।

MainActivity.onCreate()

// Set custom info window adapter
googleMap.setInfoWindowAdapter(MarkerInfoWindowAdapter(this))

সবশেষে, ম্যাপে যোগ করা প্রতিটি মার্কারের ট্যাগ সম্পত্তি হিসাবে আপনাকে প্রতিটি স্থান সেট করতে হবে।

  1. এটি করার জন্য, নিম্নলিখিতগুলির সাথে addMarkers() ফাংশনে places.forEach{} কল পরিবর্তন করুন:

MainActivity.addMarkers()

places.forEach { place ->
   val marker = googleMap.addMarker(
       MarkerOptions()
           .title(place.name)
           .position(place.latLng)
           .icon(bicycleIcon)
   )

   // Set place as the tag on the marker object so it can be referenced within
   // MarkerInfoWindowAdapter
   marker.tag = place
}

একটি কাস্টম মার্কার ইমেজ যোগ করুন

মার্কার ইমেজ কাস্টমাইজ করা হল আপনার মানচিত্রে মার্কার যে ধরনের জায়গার প্রতিনিধিত্ব করে তা যোগাযোগ করার একটি মজার উপায়। এই ধাপের জন্য, আপনি মানচিত্রে প্রতিটি দোকানের প্রতিনিধিত্ব করার জন্য ডিফল্ট লাল মার্কারগুলির পরিবর্তে সাইকেলগুলি প্রদর্শন করুন৷ স্টার্টার প্রজেক্টে app/src/res/drawable এ সাইকেল আইকন ic_directions_bike_black_24dp.xml অন্তর্ভুক্ত রয়েছে, যা আপনি ব্যবহার করেন।

6eb7358bb61b0a88.png

মার্কারে কাস্টম বিটম্যাপ সেট করুন

আপনার নিষ্পত্তিতে ভেক্টর অঙ্কনযোগ্য সাইকেল আইকন সহ, পরবর্তী পদক্ষেপটি মানচিত্রে প্রতিটি চিহ্নিতকারীর আইকন হিসাবে সেই অঙ্কনযোগ্যটিকে সেট করা। MarkerOptions এর একটি পদ্ধতি icon রয়েছে, যা একটি BitmapDescriptor নেয় যা আপনি এটি সম্পাদন করতে ব্যবহার করেন।

প্রথমে, আপনাকে একটি BitmapDescriptor যোগ করা ভেক্টর অঙ্কনযোগ্য রূপান্তর করতে হবে। স্টার্টার প্রজেক্টে অন্তর্ভুক্ত BitMapHelper নামক একটি ফাইলে vectorToBitmap() নামে একটি সহায়ক ফাংশন রয়েছে, যা ঠিক তাই করে।

বিটম্যাপ হেল্পার

package com.google.codelabs.buildyourfirstmap

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.util.Log
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.DrawableCompat
import com.google.android.gms.maps.model.BitmapDescriptor
import com.google.android.gms.maps.model.BitmapDescriptorFactory

object BitmapHelper {
   /**
    * Demonstrates converting a [Drawable] to a [BitmapDescriptor], 
    * for use as a marker icon. Taken from ApiDemos on GitHub:
    * https://github.com/googlemaps/android-samples/blob/main/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/MarkerDemoActivity.kt
    */
   fun vectorToBitmap(
      context: Context,
      @DrawableRes id: Int, 
      @ColorInt color: Int
   ): BitmapDescriptor {
       val vectorDrawable = ResourcesCompat.getDrawable(context.resources, id, null)
       if (vectorDrawable == null) {
           Log.e("BitmapHelper", "Resource not found")
           return BitmapDescriptorFactory.defaultMarker()
       }
       val bitmap = Bitmap.createBitmap(
           vectorDrawable.intrinsicWidth,
           vectorDrawable.intrinsicHeight,
           Bitmap.Config.ARGB_8888
       )
       val canvas = Canvas(bitmap)
       vectorDrawable.setBounds(0, 0, canvas.width, canvas.height)
       DrawableCompat.setTint(vectorDrawable, color)
       vectorDrawable.draw(canvas)
       return BitmapDescriptorFactory.fromBitmap(bitmap)
   }
}

এই পদ্ধতিটি একটি Context , একটি অঙ্কনযোগ্য রিসোর্স আইডি, সেইসাথে একটি রঙের পূর্ণসংখ্যা নেয় এবং এটির একটি BitmapDescriptor উপস্থাপনা তৈরি করে।

সাহায্যকারী পদ্ধতি ব্যবহার করে, bicycleIcon নামে একটি নতুন সম্পত্তি ঘোষণা করুন এবং এটিকে নিম্নলিখিত সংজ্ঞা দিন: MainActivity.bicycleIcon

private val bicycleIcon: BitmapDescriptor by lazy {
   val color = ContextCompat.getColor(this, R.color.colorPrimary)
   BitmapHelper.vectorToBitmap(this, R.drawable.ic_directions_bike_black_24dp, color)
}

এই বৈশিষ্ট্যটি আপনার অ্যাপে পূর্বনির্ধারিত রঙের কালার colorPrimary ব্যবহার করে এবং সাইকেল আইকনটি টিন্ট করতে এবং এটিকে BitmapDescriptor হিসাবে ফিরিয়ে দিতে ব্যবহার করে।

  1. এই সম্পত্তি ব্যবহার করে, এগিয়ে যান এবং আপনার আইকন কাস্টমাইজেশন সম্পূর্ণ করতে addMarkers() পদ্ধতিতে MarkerOptions এর icon পদ্ধতি ব্যবহার করুন। এটি করছেন, মার্কার সম্পত্তি এই মত হওয়া উচিত:

MainActivity.addMarkers()

val marker = googleMap.addMarker(
    MarkerOptions()
        .title(place.name)
        .position(place.latLng)
        .icon(bicycleIcon)
)
  1. আপডেট মার্কার দেখতে অ্যাপটি চালান!

8. ক্লাস্টার মার্কার

আপনি মানচিত্রে কতদূর জুম করেছেন তার উপর নির্ভর করে, আপনি লক্ষ্য করেছেন যে আপনি যে মার্কারগুলি যোগ করেছেন ওভারল্যাপ করেছেন। ওভারল্যাপিং মার্কারগুলির সাথে ইন্টারঅ্যাক্ট করা এবং প্রচুর শব্দ তৈরি করা খুব কঠিন, যা আপনার অ্যাপের ব্যবহারযোগ্যতাকে প্রভাবিত করে৷

68591edc86d73724.png

এটির জন্য ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে, যখনই আপনার কাছে একটি বড় ডেটাসেট থাকে যা ঘনিষ্ঠভাবে ক্লাস্টার করা হয়, তখন মার্কার ক্লাস্টারিং প্রয়োগ করা সর্বোত্তম অনুশীলন। ক্লাস্টারিংয়ের সাথে, আপনি ম্যাপ জুম ইন এবং আউট করার সাথে সাথে কাছাকাছি থাকা মার্কারগুলিকে এইভাবে একসাথে ক্লাস্টার করা হয়:

f05e1ca27ff42bf6.png

এটি বাস্তবায়ন করতে, আপনার Android ইউটিলিটি লাইব্রেরির জন্য Maps SDK- এর সাহায্য প্রয়োজন।

Android ইউটিলিটি লাইব্রেরির জন্য মানচিত্র SDK

Android এর জন্য Maps SDK-এর কার্যকারিতা বাড়ানোর উপায় হিসেবে Android ইউটিলিটি লাইব্রেরির জন্য Maps SDK তৈরি করা হয়েছে৷ এটি উন্নত বৈশিষ্ট্যগুলি অফার করে, যেমন মার্কার ক্লাস্টারিং, হিটম্যাপ, কেএমএল এবং জিওজসন সমর্থন, পলিলাইন এনকোডিং এবং ডিকোডিং এবং গোলাকার জ্যামিতির আশেপাশে কয়েকটি সহায়ক ফাংশন।

আপনার build.gradle আপডেট করুন

কারণ ইউটিলিটি লাইব্রেরিটি Android এর জন্য Maps SDK থেকে আলাদাভাবে প্যাকেজ করা হয়েছে, তাই আপনাকে আপনার build.gradle ফাইলে একটি অতিরিক্ত নির্ভরতা যোগ করতে হবে।

  1. এগিয়ে যান এবং আপনার app/build.gradle ফাইলের dependencies বিভাগ আপডেট করুন।

build.gradle

implementation 'com.google.maps.android:android-maps-utils:1.1.0'
  1. এই লাইনটি যোগ করার পরে, আপনাকে নতুন নির্ভরতা আনতে একটি প্রকল্প সিঙ্ক করতে হবে।

b7b030ec82c007fd.png

ক্লাস্টারিং বাস্তবায়ন করুন

আপনার অ্যাপে ক্লাস্টারিং বাস্তবায়ন করতে, এই তিনটি ধাপ অনুসরণ করুন:

  1. ClusterItem ইন্টারফেস প্রয়োগ করুন।
  2. DefaultClusterRenderer ক্লাস সাবক্লাস করুন।
  3. একটি ClusterManager তৈরি করুন এবং আইটেম যোগ করুন।

ClusterItem ইন্টারফেস প্রয়োগ করুন

মানচিত্রে একটি ক্লাস্টারেবল মার্কার প্রতিনিধিত্ব করে এমন সমস্ত বস্তুকে ClusterItem ইন্টারফেস বাস্তবায়ন করতে হবে। আপনার ক্ষেত্রে, এর মানে হল যে Place মডেলটিকে ClusterItem এর সাথে সামঞ্জস্য করতে হবে। এগিয়ে যান এবং Place.kt ফাইলটি খুলুন এবং এতে নিম্নলিখিত পরিবর্তনগুলি করুন:

স্থান

data class Place(
   val name: String,
   val latLng: LatLng,
   val address: String,
   val rating: Float
) : ClusterItem {
   override fun getPosition(): LatLng =
       latLng

   override fun getTitle(): String =
       name

   override fun getSnippet(): String =
       address
}

ClusterItem এই তিনটি পদ্ধতি সংজ্ঞায়িত করে:

  • getPosition() , যা স্থানটির LatLng প্রতিনিধিত্ব করে।
  • getTitle() , যা স্থানটির নাম উপস্থাপন করে
  • getSnippet() , যা স্থানটির ঠিকানা উপস্থাপন করে।

DefaultClusterRenderer ক্লাস সাবক্লাস করুন

ক্লাস্টারিং বাস্তবায়নের দায়িত্বে থাকা শ্রেণী, ClusterManager , অভ্যন্তরীণভাবে একটি ClusterRenderer ক্লাস ব্যবহার করে ক্লাস্টার তৈরি করার জন্য যখন আপনি মানচিত্রের চারপাশে প্যান এবং জুম করেন। ডিফল্টরূপে, এটি ডিফল্ট রেন্ডারার, DefaultClusterRenderer এর সাথে আসে, যা ClusterRenderer প্রয়োগ করে। সাধারণ ক্ষেত্রে, এটি যথেষ্ট হওয়া উচিত। আপনার ক্ষেত্রে, যাইহোক, কারণ মার্কারগুলি কাস্টমাইজ করা দরকার, আপনাকে এই ক্লাসটি প্রসারিত করতে হবে এবং সেখানে কাস্টমাইজেশন যোগ করতে হবে।

এগিয়ে যান এবং com.google.codelabs.buildyourfirstmap.place প্যাকেজে com.google.codelabs.buildyourfirstmap.place ফাইল PlaceRenderer.kt তৈরি করুন এবং এটিকে নিম্নরূপ সংজ্ঞায়িত করুন:

প্লেস রেন্ডারার

package com.google.codelabs.buildyourfirstmap.place

import android.content.Context
import androidx.core.content.ContextCompat
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.BitmapDescriptor
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
import com.google.codelabs.buildyourfirstmap.BitmapHelper
import com.google.codelabs.buildyourfirstmap.R
import com.google.maps.android.clustering.ClusterManager
import com.google.maps.android.clustering.view.DefaultClusterRenderer

/**
* A custom cluster renderer for Place objects.
*/
class PlaceRenderer(
   private val context: Context,
   map: GoogleMap,
   clusterManager: ClusterManager<Place>
) : DefaultClusterRenderer<Place>(context, map, clusterManager) {

   /**
    * The icon to use for each cluster item
    */
   private val bicycleIcon: BitmapDescriptor by lazy {
       val color = ContextCompat.getColor(context,
           R.color.colorPrimary
       )
       BitmapHelper.vectorToBitmap(
           context,
           R.drawable.ic_directions_bike_black_24dp,
           color
       )
   }

   /**
    * Method called before the cluster item (the marker) is rendered.
    * This is where marker options should be set.
    */
   override fun onBeforeClusterItemRendered(
      item: Place,
      markerOptions: MarkerOptions
   ) {
       markerOptions.title(item.name)
           .position(item.latLng)
           .icon(bicycleIcon)
   }

   /**
    * Method called right after the cluster item (the marker) is rendered.
    * This is where properties for the Marker object should be set.
    */
   override fun onClusterItemRendered(clusterItem: Place, marker: Marker) {
       marker.tag = clusterItem
   }
}

এই ক্লাস এই দুটি ফাংশন ওভাররাইড করে:

  • onBeforeClusterItemRendered() , যা ম্যাপে ক্লাস্টার রেন্ডার হওয়ার আগে বলা হয়। এখানে, আপনি মার্কার MarkerOptions মাধ্যমে কাস্টমাইজেশন প্রদান করতে পারেন — এই ক্ষেত্রে, এটি চিহ্নিতকারীর শিরোনাম, অবস্থান এবং আইকন সেট করে।
  • onClusterItemRenderer() , যাকে ম্যাপে মার্কার রেন্ডার করার পরে বলা হয়। এখানেই আপনি তৈরি Marker অবজেক্ট অ্যাক্সেস করতে পারেন—এই ক্ষেত্রে, এটি মার্কার ট্যাগ বৈশিষ্ট্য সেট করে।

একটি ClusterManager তৈরি করুন এবং আইটেম যোগ করুন

সবশেষে, ক্লাস্টারিং কাজ করার জন্য, আপনাকে একটি ClusterManager ইনস্ট্যান্টিয়েট করার জন্য MainActivity সংশোধন করতে হবে এবং এটিতে প্রয়োজনীয় নির্ভরতা প্রদান করতে হবে। ClusterManager অভ্যন্তরীণভাবে মার্কার ( ClusterItem অবজেক্ট) যোগ করার কাজ পরিচালনা করে, তাই মানচিত্রে সরাসরি মার্কার যোগ করার পরিবর্তে, এই দায়িত্বটি ClusterManager কে অর্পণ করা হয়। উপরন্তু, ClusterManager এছাড়াও setInfoWindowAdapter() অভ্যন্তরীণভাবে কল করে তাই ClusterManger এর MarkerManager.Collection অবজেক্টে একটি কাস্টম তথ্য উইন্ডো সেট করতে হবে।

  1. শুরু করতে, MainActivity.onCreate()getMapAsync() কলে ল্যাম্বডার বিষয়বস্তু পরিবর্তন করুন। এগিয়ে যান এবং addMarkers() এবং setInfoWindowAdapter() ) এ কলটি মন্তব্য করুন, এবং পরিবর্তে addClusteredMarkers() নামে একটি পদ্ধতি চালু করুন, যা আপনি পরবর্তী সংজ্ঞায়িত করেছেন।

MainActivity.onCreate()

mapFragment?.getMapAsync { googleMap ->
    //addMarkers(googleMap)
    addClusteredMarkers(googleMap)

    // Set custom info window adapter.
    // googleMap.setInfoWindowAdapter(MarkerInfoWindowAdapter(this))
}
  1. এরপরে, MainActivityaddClusteredMarkers() সংজ্ঞায়িত করুন।

MainActivity.addClusteredMarkers()

/**
* Adds markers to the map with clustering support.
*/
private fun addClusteredMarkers(googleMap: GoogleMap) {
   // Create the ClusterManager class and set the custom renderer.
   val clusterManager = ClusterManager<Place>(this, googleMap)
   clusterManager.renderer =
       PlaceRenderer(
           this,
           googleMap,
           clusterManager
       )

   // Set custom info window adapter
   clusterManager.markerCollection.setInfoWindowAdapter(MarkerInfoWindowAdapter(this))

   // Add the places to the ClusterManager.
   clusterManager.addItems(places)
   clusterManager.cluster()

   // Set ClusterManager as the OnCameraIdleListener so that it
   // can re-cluster when zooming in and out.
   googleMap.setOnCameraIdleListener {
       clusterManager.onCameraIdle()
   }
}

এই পদ্ধতিটি একটি ClusterManager ইনস্ট্যান্টিয়েট করে, এটিতে কাস্টম রেন্ডারার PlacesRenderer পাস করে, সমস্ত স্থান যোগ করে এবং cluster() পদ্ধতি চালু করে। এছাড়াও, যেহেতু ClusterManager মানচিত্র অবজেক্টে setInfoWindowAdapter() পদ্ধতি ব্যবহার করে, তাই ClusterManager.markerCollection অবজেক্টে কাস্টম তথ্য উইন্ডো সেট করতে হবে। সবশেষে, যেহেতু আপনি চাচ্ছেন ক্লাস্টারিং পরিবর্তন করার সাথে সাথে ব্যবহারকারী ম্যাপের চারপাশে প্যান এবং জুম করে, তাই googleMap-এ একটি OnCameraIdleListener প্রদান করা googleMap , যেমন ক্যামেরাটি নিষ্ক্রিয় হয়ে গেলে, clusterManager.onCameraIdle() চালু করা হয়।

  1. এগিয়ে যান এবং নতুন ক্লাস্টার দোকান দেখতে অ্যাপ চালান!

9. মানচিত্রে আঁকুন

আপনি ইতিমধ্যে মানচিত্রে আঁকার একটি উপায় অন্বেষণ করেছেন (মার্কার যোগ করে), Android এর জন্য Maps SDK ম্যাপে দরকারী তথ্য প্রদর্শন করার জন্য আপনি আঁকতে পারেন এমন আরও অনেক উপায় সমর্থন করে৷

উদাহরণস্বরূপ, আপনি যদি মানচিত্রে রুট এবং অঞ্চলগুলিকে উপস্থাপন করতে চান তবে আপনি মানচিত্রে এইগুলি প্রদর্শন করতে পলিলাইন এবং বহুভুজ ব্যবহার করতে পারেন। অথবা, আপনি যদি মাটির পৃষ্ঠে একটি চিত্র ঠিক করতে চান, আপনি গ্রাউন্ড ওভারলে ব্যবহার করতে পারেন।

এই টাস্কে, আপনি শিখবেন কিভাবে আকৃতি আঁকতে হয়, বিশেষ করে একটি বৃত্ত, যখনই একটি মার্কারের চারপাশে ট্যাপ করা হয়।

f98ce13055430352.png

ক্লিক শ্রোতা যোগ করুন

সাধারণত, আপনি যেভাবে একটি মার্কারে একটি ক্লিক শ্রোতা যোগ করবেন তা হল setOnMarkerClickListener() এর মাধ্যমে সরাসরি GoogleMap অবজেক্টে একটি ক্লিক লিসেনার পাস করা। যাইহোক, যেহেতু আপনি ক্লাস্টারিং ব্যবহার করছেন, তার পরিবর্তে ক্লিক শ্রোতাকে ClusterManager প্রদান করতে হবে।

  1. MainActivityaddClusteredMarkers() পদ্ধতিতে, এগিয়ে যান এবং cluster() এ আহ্বানের ঠিক পরে নিম্নলিখিত লাইনটি যোগ করুন।

MainActivity.addClusteredMarkers()

// Show polygon
clusterManager.setOnClusterItemClickListener { item ->
   addCircle(googleMap, item)
   return@setOnClusterItemClickListener false
}

এই পদ্ধতিটি একজন শ্রোতাকে যুক্ত করে এবং addCircle() পদ্ধতিটি আহ্বান করে, যা আপনি পরবর্তী সংজ্ঞায়িত করেন। সবশেষে, এই পদ্ধতিটি থেকে false ফেরত দেওয়া হয় যাতে বোঝা যায় যে এই পদ্ধতিটি এই ইভেন্টটি গ্রাস করেনি।

  1. এর পরে, আপনাকে MainActivity এ প্রপার্টি circle এবং মেথড addCircle() সংজ্ঞায়িত করতে হবে।

MainActivity.addCircle()

private var circle: Circle? = null

/**
* Adds a [Circle] around the provided [item]
*/
private fun addCircle(googleMap: GoogleMap, item: Place) {
   circle?.remove()
   circle = googleMap.addCircle(
       CircleOptions()
           .center(item.latLng)
           .radius(1000.0)
           .fillColor(ContextCompat.getColor(this, R.color.colorPrimaryTranslucent))
           .strokeColor(ContextCompat.getColor(this, R.color.colorPrimary))
   )
}

circle সম্পত্তি সেট করা হয় যাতে যখনই একটি নতুন মার্কার ট্যাপ করা হয়, পূর্ববর্তী বৃত্তটি সরানো হয় এবং একটি নতুন যোগ করা হয়। লক্ষ্য করুন যে একটি বৃত্ত যোগ করার জন্য এপিআই একটি মার্কার যোগ করার মতোই।

  1. এখনই এগিয়ে যান এবং পরিবর্তনগুলি দেখতে অ্যাপটি চালান।

10. ক্যামেরা নিয়ন্ত্রণ

আপনার শেষ কাজ হিসাবে, আপনি কিছু ক্যামেরা নিয়ন্ত্রণের দিকে তাকান যাতে আপনি একটি নির্দিষ্ট অঞ্চলের চারপাশে দৃশ্য ফোকাস করতে পারেন।

ক্যামেরা এবং ভিউ

আপনি অ্যাপটি চালানোর সময় যদি লক্ষ্য করেন, ক্যামেরাটি আফ্রিকা মহাদেশ প্রদর্শন করে এবং আপনার যোগ করা মার্কারগুলি খুঁজে পেতে আপনাকে পরিশ্রমের সাথে প্যান এবং জুম করতে হবে সান ফ্রান্সিসকোতে। যদিও এটি বিশ্বকে অন্বেষণ করার একটি মজার উপায় হতে পারে, আপনি যদি এখনই মার্কারগুলি প্রদর্শন করতে চান তবে এটি কার্যকর নয়৷

এটিতে সহায়তা করার জন্য, আপনি ক্যামেরার অবস্থান প্রোগ্রাম্যাটিকভাবে সেট করতে পারেন যাতে ভিউটি যেখানে আপনি চান সেখানে কেন্দ্রীভূত হয়।

  1. এগিয়ে যান এবং ক্যামেরা ভিউ সামঞ্জস্য করতে getMapAsync() কলে নিম্নলিখিত কোডটি যোগ করুন যাতে অ্যাপটি চালু হলে এটি সান ফ্রান্সিসকোতে শুরু হয়।

MainActivity.onCreate()

mapFragment?.getMapAsync { googleMap ->
   // Ensure all places are visible in the map.
   googleMap.setOnMapLoadedCallback {
       val bounds = LatLngBounds.builder()
       places.forEach { bounds.include(it.latLng) }
       googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), 20))
   }
}

প্রথমে, setOnMapLoadedCallback() বলা হয় যাতে ম্যাপ লোড হওয়ার পরেই ক্যামেরা আপডেট করা হয়। এই পদক্ষেপটি প্রয়োজনীয় কারণ একটি ক্যামেরা আপডেট কল করার আগে মানচিত্র বৈশিষ্ট্য যেমন মাত্রাগুলি গণনা করা প্রয়োজন৷

ল্যাম্বডায়, একটি নতুন LatLngBounds অবজেক্ট তৈরি করা হয়েছে, যা মানচিত্রে একটি আয়তক্ষেত্রাকার অঞ্চলকে সংজ্ঞায়িত করে। এটি ক্রমবর্ধমানভাবে সমস্ত স্থান LatLng মানগুলিকে অন্তর্ভুক্ত করে তৈরি করা হয়েছে যাতে সমস্ত স্থান সীমার মধ্যে থাকে। একবার এই অবজেক্টটি তৈরি হয়ে গেলে, GoogleMapmoveCamera() পদ্ধতিটি চালু করা হয় এবং CameraUpdateFactory.newLatLngBounds(bounds.build(), 20) মাধ্যমে এটিতে একটি CameraUpdate প্রদান করা হয়।

  1. অ্যাপটি চালান এবং লক্ষ্য করুন যে ক্যামেরাটি এখন সান ফ্রান্সিসকোতে শুরু হয়েছে।

ক্যামেরা পরিবর্তনের কথা শোনা

ক্যামেরার অবস্থান পরিবর্তন করার পাশাপাশি, ব্যবহারকারী মানচিত্রের চারপাশে চলাফেরা করার সাথে সাথে আপনি ক্যামেরা আপডেটগুলিও শুনতে পারেন। ক্যামেরা ঘুরার সাথে সাথে আপনি UI পরিবর্তন করতে চাইলে এটি কার্যকর হতে পারে।

শুধুমাত্র মজার জন্য, যখনই ক্যামেরা সরানো হয় তখন মার্কারগুলিকে স্বচ্ছ করতে আপনি কোডটি পরিবর্তন করেন৷

  1. addClusteredMarkers() পদ্ধতিতে, এগিয়ে যান এবং পদ্ধতির নীচের দিকে নিম্নলিখিত লাইনগুলি যোগ করুন:

MainActivity.addClusteredMarkers()

// When the camera starts moving, change the alpha value of the marker to translucent.
googleMap.setOnCameraMoveStartedListener {
   clusterManager.markerCollection.markers.forEach { it.alpha = 0.3f }
   clusterManager.clusterMarkerCollection.markers.forEach { it.alpha = 0.3f }
}

এটি একটি OnCameraMoveStartedListener যোগ করে যাতে, যখনই ক্যামেরা নড়াচড়া শুরু করে, সমস্ত মার্কারগুলির (ক্লাস্টার এবং মার্কার উভয়) আলফা মানগুলিকে 0.3f এ পরিবর্তন করা হয় যাতে মার্কারগুলি স্বচ্ছ দেখায়৷

  1. সবশেষে, ক্যামেরা বন্ধ হয়ে গেলে স্বচ্ছ মার্কারগুলিকে অস্বচ্ছ অবস্থায় ফিরিয়ে আনতে, addClusteredMarkers() পদ্ধতিতে setOnCameraIdleListener এর বিষয়বস্তু নিম্নোক্তভাবে পরিবর্তন করুন:

MainActivity.addClusteredMarkers()

googleMap.setOnCameraIdleListener {
   // When the camera stops moving, change the alpha value back to opaque.
   clusterManager.markerCollection.markers.forEach { it.alpha = 1.0f }
   clusterManager.clusterMarkerCollection.markers.forEach { it.alpha = 1.0f }

   // Call clusterManager.onCameraIdle() when the camera stops moving so that reclustering
   // can be performed when the camera stops moving.
   clusterManager.onCameraIdle()
}
  1. এগিয়ে যান এবং ফলাফল দেখতে অ্যাপ্লিকেশন চালান!

11. KTX মানচিত্র

এক বা একাধিক Google মানচিত্র প্ল্যাটফর্ম অ্যান্ড্রয়েড SDK ব্যবহার করে Kotlin অ্যাপগুলির জন্য, Kotlin এক্সটেনশন বা KTX লাইব্রেরিগুলি আপনাকে কোরটিন, এক্সটেনশন বৈশিষ্ট্য/ফাংশন এবং আরও অনেক কিছুর মতো Kotlin ভাষার বৈশিষ্ট্যগুলির সুবিধা নিতে সক্ষম করার জন্য উপলব্ধ। প্রতিটি Google Maps SDK-এর একটি সংশ্লিষ্ট KTX লাইব্রেরি রয়েছে যা নীচে দেখানো হয়েছে:

Google Maps প্ল্যাটফর্ম KTX ডায়াগ্রাম

এই টাস্কে, আপনি আপনার অ্যাপে Maps KTX এবং Maps Utils KTX লাইব্রেরিগুলি ব্যবহার করবেন এবং আগের টাস্কের বাস্তবায়নকে রিফ্যাক্ট করবেন যাতে আপনি আপনার অ্যাপে Kotlin-নির্দিষ্ট ভাষার বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন।

  1. আপনার অ্যাপ-লেভেল build.gradle ফাইলে KTX নির্ভরতা অন্তর্ভুক্ত করুন

যেহেতু অ্যাপটি Android এর জন্য Maps SDK এবং Android ইউটিলিটি লাইব্রেরির জন্য Maps SDK উভয়ই ব্যবহার করে, তাই আপনাকে এই লাইব্রেরির জন্য সংশ্লিষ্ট KTX লাইব্রেরিগুলি অন্তর্ভুক্ত করতে হবে। আপনি এই কাজটিতে AndroidX Lifecycle KTX লাইব্রেরিতে পাওয়া একটি বৈশিষ্ট্যও ব্যবহার করবেন যাতে সেই নির্ভরতাটি আপনার অ্যাপ-লেভেলের build.gradle করুন।

build.gradle

dependencies {
    // ...

    // Maps SDK for Android KTX Library
    implementation 'com.google.maps.android:maps-ktx:3.0.0'

    // Maps SDK for Android Utility Library KTX Library
    implementation 'com.google.maps.android:maps-utils-ktx:3.0.0'

    // Lifecycle Runtime KTX Library
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
}
  1. GoogleMap.addMarker() এবং GoogleMap.addCircle() এক্সটেনশন ফাংশন ব্যবহার করুন

Maps KTX লাইব্রেরি পূর্ববর্তী ধাপে ব্যবহৃত GoogleMap.addMarker GoogleMap.addMarker(MarkerOptions) এবং GoogleMap.addCircle(CircleOptions) এর জন্য একটি DSL-শৈলী API বিকল্প প্রদান করে। উপরে উল্লিখিত APIগুলি ব্যবহার করার জন্য, একটি মার্কার বা বৃত্তের বিকল্পগুলি সম্বলিত একটি ক্লাস নির্মাণ করা প্রয়োজন যেখানে KTX বিকল্পগুলির সাথে আপনি আপনার প্রদান করা ল্যাম্বডাতে মার্কার বা বৃত্তের বিকল্পগুলি সেট করতে সক্ষম হবেন।

এই APIগুলি ব্যবহার করতে, MainActivity.addMarkers(GoogleMap) এবং MainActivity.addCircle(GoogleMap) পদ্ধতিগুলি আপডেট করুন:

MainActivity.addMarkers(GoogleMap)

/**
 * Adds markers to the map. These markers won't be clustered.
 */
private fun addMarkers(googleMap: GoogleMap) {
    places.forEach { place ->
        val marker = googleMap.addMarker {
            title(place.name)
            position(place.latLng)
            icon(bicycleIcon)
        }
        // Set place as the tag on the marker object so it can be referenced within
        // MarkerInfoWindowAdapter
        marker.tag = place
    }
}

MainActivity.addCircle(GoogleMap)

/**
 * Adds a [Circle] around the provided [item]
 */
private fun addCircle(googleMap: GoogleMap, item: Place) {
    circle?.remove()
    circle = googleMap.addCircle {
        center(item.latLng)
        radius(1000.0)
        fillColor(ContextCompat.getColor(this@MainActivity, R.color.colorPrimaryTranslucent))
        strokeColor(ContextCompat.getColor(this@MainActivity, R.color.colorPrimary))
    }
}

এইভাবে উপরের পদ্ধতিগুলি পুনরায় লেখা পড়া অনেক বেশি সংক্ষিপ্ত যা রিসিভার সহ Kotlin এর ফাংশন আক্ষরিক ব্যবহার করে সম্ভব হয়েছে।

  1. SupportMapFragment.awaitMap() এবং GoogleMap.awaitMapLoad() এক্সটেনশন সাসপেন্ডিং ফাংশন ব্যবহার করুন

মানচিত্র কেটিএক্স লাইব্রেরি কোরোটিনের মধ্যে ব্যবহার করার জন্য সাসপেন্ডিং ফাংশন এক্সটেনশন সরবরাহ করে। বিশেষত, SupportMapFragment.getMapAsync(OnMapReadyCallback) এবং GoogleMap.setOnMapLoadedCallback(OnMapLoadedCallback) এর জন্য সাসপেন্ডিং ফাংশন বিকল্প রয়েছে। এই বিকল্প APIগুলি ব্যবহার করে কলব্যাক পাস করার প্রয়োজনীয়তা দূর করে এবং পরিবর্তে আপনাকে এই পদ্ধতিগুলির প্রতিক্রিয়া সিরিয়াল এবং সিঙ্ক্রোনাস উপায়ে পেতে দেয়।

যেহেতু এই পদ্ধতিগুলি ফাংশনগুলিকে স্থগিত করছে, তাই তাদের ব্যবহার একটি কোরোটিনের মধ্যে ঘটতে হবে৷ লাইফসাইকেল রানটাইম কেটিএক্স লাইব্রেরি লাইফসাইকেল-সচেতন করোটিন স্কোপগুলি প্রদান করার জন্য একটি এক্সটেনশন অফার করে যাতে সঠিক জীবনচক্র ইভেন্টে করোটিনগুলি চালানো এবং বন্ধ করা হয়।

এই ধারণাগুলিকে একত্রিত করে, MainActivity.onCreate(Bundle) পদ্ধতি আপডেট করুন:

MainActivity.onCreate(বান্ডেল)

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val mapFragment =
        supportFragmentManager.findFragmentById(R.id.map_fragment) as SupportMapFragment
    lifecycleScope.launchWhenCreated {
        // Get map
        val googleMap = mapFragment.awaitMap()

        // Wait for map to finish loading
        googleMap.awaitMapLoad()

        // Ensure all places are visible in the map
        val bounds = LatLngBounds.builder()
        places.forEach { bounds.include(it.latLng) }
        googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), 20))

        addClusteredMarkers(googleMap)
    }
}

lifecycleScope.launchWhenCreated coroutine স্কোপ ব্লকটি কার্যকর করবে যখন কার্যকলাপটি অন্তত তৈরি অবস্থায় থাকে। এছাড়াও লক্ষ্য করুন যে GoogleMap অবজেক্ট পুনরুদ্ধার করার জন্য এবং মানচিত্রটি লোড হওয়া শেষ হওয়ার জন্য অপেক্ষা করার জন্য, যথাক্রমে SupportMapFragment.awaitMap() এবং GoogleMap.awaitMapLoad() দিয়ে প্রতিস্থাপিত হয়েছে৷ এই সাসপেন্ডিং ফাংশনগুলি ব্যবহার করে রিফ্যাক্টরিং কোড আপনাকে অনুক্রমিক পদ্ধতিতে সমতুল্য কলব্যাক-ভিত্তিক কোড লিখতে সক্ষম করে।

  1. এগিয়ে যান এবং আপনার রিফ্যাক্টর করা পরিবর্তনগুলির সাথে অ্যাপটি পুনরায় তৈরি করুন!

12. অভিনন্দন

অভিনন্দন! আপনি অনেক কন্টেন্ট কভার করেছেন এবং আশা করি আপনি Android এর জন্য Maps SDK-এ দেওয়া মূল বৈশিষ্ট্যগুলি সম্পর্কে আরও ভালভাবে বুঝতে পেরেছেন।

আরও জানুন

  • Android এর জন্য SDK স্থানগুলি — আপনার চারপাশের ব্যবসাগুলি আবিষ্কার করতে স্থানের ডেটার সমৃদ্ধ সেট অন্বেষণ করুন৷
  • android-maps-ktx —একটি ওপেন সোর্স লাইব্রেরি যা আপনাকে অ্যান্ড্রয়েডের জন্য মানচিত্র SDK এবং Android ইউটিলিটি লাইব্রেরির জন্য Maps SDK একটি Kotlin-বান্ধব উপায়ে একীভূত করার অনুমতি দেয়৷
  • android-place-ktx —একটি ওপেন সোর্স লাইব্রেরি যা আপনাকে কোটলিন-বান্ধব উপায়ে Android-এর জন্য Places SDK-এর সাথে একীভূত করতে দেয়৷
  • android-samples — GitHub-এ নমুনা কোড এই কোডল্যাবে আচ্ছাদিত সমস্ত বৈশিষ্ট্য প্রদর্শন করে এবং আরও অনেক কিছু।
  • Google মানচিত্র প্ল্যাটফর্মের সাথে অ্যান্ড্রয়েড অ্যাপ তৈরির জন্য আরও কোটলিন কোডল্যাব