How to reference map created in Android Fragment

I am following this guide:
https://developers.google.com/codelabs/maps-platform/maps-platform-101-android#9

and I am trying to get a map in a fragment. I have the map successfully working but right now when the map opens, it defaults to showing Africa at a really high-level view. I want the map to default to opening to my City at a much more local level.

My xml file for the fragment looks like:

<?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=".ViewNearbyFragment">

    <androidx.fragment.app.FragmentContainerView
        xmlns:map="http://schemas.android.com/apk/res-auto"
        class="com.google.android.gms.maps.SupportMapFragment"
        map:mapId="{my_map_id}"
        android:id="@+id/map_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

And the Kotlin file corresponding to the same fragment looks like:

class ViewNearbyFragment : Fragment() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        (fragmentManager?.findFragmentById(
            R.id.map_fragment
        ) as? SupportMapFragment)?.getMapAsync { googleMap ->
            
            // Ensure all places are visible in the map.
            googleMap.setOnMapLoadedCallback {
                val bounds = LatLngBounds.builder()
                bounds.include(LatLng(0.0, 0.0))
                googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), 20))
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_view_nearby, container, false)
    }
}

I am never entering the block that follows the getMapAsync call and I am not sure why. How can I access the map that was created in the xml file? or better yet, how can I change default values associated with this map?

>Solution :

There’s two problems with your code:

  1. onCreate() runs before onCreateView as per the Fragment lifecycle guide. This means that your FragmentContainerView hasn’t been inflated (and your SupportFragmentFragment hasn’t been created) when your onCreate code runs. Code you want to run after onCreateView should be moved to onViewCreated().

  2. You’re using the wrong FragmentManager – the deprecated fragmentManager is the FragmentManager that the fragment is attached to (that’s why it was deprecated for the much more descriptive parentFragmentManager name). The fragment you’ve created is a ‘child fragment’ (as per the FragmentManager guide) so you need to use the childFragmentManager.

Your fixed code would look like:

class ViewNearbyFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_view_nearby, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        (childFragmentManager.findFragmentById(
            R.id.map_fragment
        ) as? SupportMapFragment)?.getMapAsync { googleMap ->
            
            // Ensure all places are visible in the map.
            googleMap.setOnMapLoadedCallback {
                val bounds = LatLngBounds.builder()
                bounds.include(LatLng(0.0, 0.0))
                googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), 20))
            }
        }
    }
}

Leave a Reply