Welcome to Google Map In Fragment Kotlin Example MapView Android.
In this kotlin google map example, you will learn how to integrate google mapview inside the fragment.
Generally, to integrate google map in fragment is little bit complex than to integrate it in the activity.
But this tutorial will help you to load google map in fragment with easy and simple kotlin source code.
First of all, watch the following output video to have some idea of the feature of this example.
Getting Google API Key
To load the google map in fragment using kotlin, we need to create one app in the developer console of google.
And after making an app, we need to generate Google API key.
Here is the specific tutorial how to generate API for google map in kotlin android.
So go through the above tutorial first and then come back with the Google API.
Android Studio Work
Now make a new brand new project in the android studio.
While making new project, make sure you have selected “Empty activity” as the default one.
If you select “Map Activity” then compiler write some lines of code which is difficult to understand.
Also, you should select “Kotlin” as the source language for the project.
Gradle Changes
Go to your build.gradle(Module:app) file, and add the following line
implementation 'com.google.android.gms:play-services:12.0.1'
This line will integrate google play services in our project.
It will allow us to use various services like map, push notification, google earth etc. in our android app.
Manifest Toppings
Open your AndroidManifest.xml file. Add the following lines inside <application> tags.
<meta-data android:name="com.google.android.geo.API_KEY" android:value="AIza............FQ"/>
Look at the attribute “android:value” . You can see that I have written my Google API key in it.
Simply replace my Google API key with yours.
Now, outside of <application> tags, add the following coding lines
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
So the final source code for AndroidManifest.xml file is as the below
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.mapfragmentkotlin"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <meta-data android:name="com.google.android.geo.API_KEY" android:value="AIz........FQ"/> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> <uses-feature android:glEsVersion="0x00020000" android:required="true"/> </manifest>
Spider man Image
This example need one image to show as the marker on the google map.
So, click the following link to download the image of the spider man.
https://demonuts.com/wp-content/uploads/2018/09/spidy.zip
After downloading the image, save it inside app->res->drawable directory.
Two Fragments
Make a new fragment with the name as OneFragment.
Inside your fragment_one.xml file, add the following lines of code
<?xml version="1.0" encoding="utf-8"?> <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=".OneFragment"> <!-- TODO: Update blank fragment layout --> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent" android:textColor="#fff" android:gravity="center" android:textSize="35dp" android:text="One Fragment" /> </FrameLayout>
There is one text view in the above file.
Background of the text view is of pink color and it has text value as “One Fragment”
Now in your OneFragment.kt file, write down the below code lines
import android.os.Bundle import android.support.v4.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup class OneFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_one, container, false) } }// Required empty public constructor
Now create another fragment and set it’s name as the MapFragment.
In your fragment_map.xml file, add the below source snippet
<?xml version="1.0" encoding="utf-8"?> <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=".MapFragment"> <fragment android:name="com.google.android.gms.maps.SupportMapFragment" android:id="@+id/frg" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout>
Below is the source code snippet for the MapFragment.kt file.
import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.drawable.Drawable import android.os.Bundle import android.support.v4.app.Fragment import android.support.v4.content.ContextCompat import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.BitmapDescriptor import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.MarkerOptions class MapFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment val rootView = inflater.inflate(R.layout.fragment_map, container, false) val mapFragment = childFragmentManager.findFragmentById(R.id.frg) as SupportMapFragment? //use SuppoprtMapFragment for using in fragment instead of activity MapFragment = activity SupportMapFragment = fragment mapFragment!!.getMapAsync { mMap -> mMap.mapType = GoogleMap.MAP_TYPE_NORMAL mMap.clear() //clear old markers val googlePlex = CameraPosition.builder() .target(LatLng(37.4219999, -122.0862462)) .zoom(10f) .bearing(0f) .tilt(45f) .build() mMap.animateCamera(CameraUpdateFactory.newCameraPosition(googlePlex), 10000, null) mMap.addMarker( MarkerOptions() .position(LatLng(37.4219999, -122.0862462)) .title("Spider Man") .icon(bitmapDescriptorFromVector(activity, R.drawable.spider)) ) mMap.addMarker( MarkerOptions() .position(LatLng(37.4629101, -122.2449094)) .title("Iron Man") .snippet("His Talent : Plenty of money") ) mMap.addMarker( MarkerOptions() .position(LatLng(37.3092293, -122.1136845)) .title("Captain America") ) } return rootView } private fun bitmapDescriptorFromVector(context: Context?, vectorResId: Int): BitmapDescriptor { val vectorDrawable = ContextCompat.getDrawable(context!!, vectorResId) vectorDrawable!!.setBounds(0, 0, vectorDrawable.intrinsicWidth, vectorDrawable.intrinsicHeight) val bitmap = Bitmap.createBitmap(vectorDrawable.intrinsicWidth, vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) vectorDrawable.draw(canvas) return BitmapDescriptorFactory.fromBitmap(bitmap) } }// Required empty public constructor
Look at the following snippet
val googlePlex = CameraPosition.builder() .target(LatLng(37.4219999, -122.0862462)) .zoom(10f) .bearing(0f) .tilt(45f) .build() mMap.animateCamera(CameraUpdateFactory.newCameraPosition(googlePlex), 10000, null)
Above lines are making some settings for the google map.
Settings are like latitude, longitude, zoom, tilt etc. You can modify these settings also.
Now focus on the following coding zone
mMap.addMarker( MarkerOptions() .position(LatLng(37.4219999, -122.0862462)) .title("Spider Man") .icon(bitmapDescriptorFromVector(activity, R.drawable.spider)) )
Above coding lines will add one marker on the google map.
.position() will set the position of the marker using latitude and longitude.
.title() will reflect as the name of the marker.
.icon() will allow us to set any image as the icon or view of the marker.
Last Words
You should have two main files like activity_main.xml and MainActivity.kt
Following is the code court for the file activity_main.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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="0dp" android:layout_weight="1" android:id="@+id/btn1" android:layout_height="wrap_content" android:text="Fragment 1 " /> <Button android:layout_width="0dp" android:layout_weight="1" android:id="@+id/btn2" android:layout_height="wrap_content" android:text="Map Fragment" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/container_frame_back" android:layout_marginTop="5dp" android:orientation="horizontal"> </LinearLayout> </LinearLayout>
There are two buttons and one Linearlayout is there in the above file.
Linear layout will work as the container of the fragment.
We will load OneFragment and google map inside this linear layout.
Now write down the below coding reference inside the MainActivity.kt file.
import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentTransaction import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.view.View import android.widget.Button class MainActivity : AppCompatActivity() { private var btn1: Button? = null private var btn2: Button? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) btn1 = findViewById(R.id.btn1) as Button btn2 = findViewById(R.id.btn2) as Button btn1!!.setOnClickListener { addFragment(OneFragment(), false, "one") } btn2!!.setOnClickListener { addFragment(MapFragment(), false, "one") } } fun addFragment(fragment: Fragment, addToBackStack: Boolean, tag: String) { val manager = supportFragmentManager val ft = manager.beginTransaction() if (addToBackStack) { ft.addToBackStack(tag) } ft.replace(R.id.container_frame_back, fragment, tag) ft.commitAllowingStateLoss() } }
When the user clicks the btn1, compiler will load the OneFragment inside the container.
On the click event of the btn2, compiler will load the MapFragment.
Compiler is using the addFragment() method to load the fragment in the container.
Below is the codding snippet for the addFragment() method.
fun addFragment(fragment: Fragment, addToBackStack: Boolean, tag: String) { val manager = supportFragmentManager val ft = manager.beginTransaction() if (addToBackStack) { ft.addToBackStack(tag) } ft.replace(R.id.container_frame_back, fragment, tag) ft.commitAllowingStateLoss() }
This method has three parameters. First parameter is the name of the fragment.
Second is the boolean variable one which says whether to put the fragment in the back stack or not.
ft.replace() will put the fragment into the container (container_frame_back)