Skip to content

Multiple Surfaces in Fragment Recycler

In this guide you will learn how to add/remove multiple fragment surfaces, each of which can contain an interactive map centered on a different desired location. The maps are fully 3D, supporting pan, pinch-zoom, rotate and tilt.

Setup

First, get an API key token, see the Getting Started guide.

Download the Maps & Navigation SDK for Android archive file

Download the MultipleSurfacesInFragmentRecycler project archive file or clone the project with Git

See the Configure Android Example guide.

Run the example

In Android Studio, from the File menu, select Sync Project with Gradle Files

Multiple surfaces example Android screenshot

Multiple surfaces example Android screenshot

An android device should be connected via USB cable.
Press SHIFT+F10 to compile, install and run the example on the android device.
Click NEXT to go to the second screen
Click the green + in the lower right corner to add a fragment with a map.
Each map can show a different location. Try to pan or zoom each map.
Click the red - in the lower left corner to remove the last added fragment.
Click PREVIOUS to go back to the first screen.

How it works

Android example screenshot

You can open the MainActivity.kt file to see how to render multiple maps, and add or remove maps.

 1class FirstFragment : Fragment()
 2{
 3 override fun onCreateView(
 4     inflater: LayoutInflater, container: ViewGroup?,
 5     savedInstanceState: Bundle?
 6 ): View? {
 7     return inflater.inflate(R.layout.fragment_first, container, false)
 8 }
 9 override fun onViewCreated(view: View, savedInstanceState: Bundle?)
10 {
11     super.onViewCreated(view, savedInstanceState)
12     view.findViewById<Button>(R.id.button_first).setOnClickListener
13     {
14         findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
15     }
16 }
17}

The first fragment. When the first fragment instantiation is complete, a click listener is added to the button to go to the second fragment.

 1override fun onCreateView(
 2     inflater: LayoutInflater, container: ViewGroup?,
 3     savedInstanceState: Bundle?
 4 ): View? {
 5     return inflater.inflate(R.layout.fragment_second, container, false)
 6 }
 7 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
 8     super.onViewCreated(view, savedInstanceState)
 9     view.findViewById<Button>(R.id.button_second).setOnClickListener {
10         findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
11     }
12     recycler = view.findViewById<RecyclerView>(R.id.list).apply {
13         itemAnimator = null
14         layoutManager = LinearLayoutManager(requireContext())
15         adapter = CustomAdapter(list)
16     }
17     val leftBtn = view.findViewById<FloatingActionButton>(R.id.bottomLeftButton)
18     leftBtn.visibility = View.VISIBLE
19     buttonAsDelete(requireContext(), leftBtn) {
20         deleteLastSurface()
21     }
22     val rightBtn = view.findViewById<FloatingActionButton>(R.id.bottomRightButton)
23     rightBtn.visibility = View.VISIBLE
24     buttonAsAdd(requireContext(), rightBtn) {
25         addSurface()
26     }
27}
The second fragment.
Each of the 2 fragments has a button to navigate to the other fragment, see res/navigation/nav_graph.xml in the project.
 1private fun addSurface() {
 2     if (list.size >= maxSurfacesCount) {
 3         return
 4     }
 5     list.add(list.lastIndex + 1)
 6     recycler.adapter?.notifyItemInserted(list.lastIndex)
 7 }
 8 private fun deleteLastSurface() {
 9     if (list.size == 0) return
10     list.removeLast()
11     recycler.adapter?.notifyItemRemoved(list.lastIndex + 1)
12 }
13 private fun buttonAsAdd(context: Context, button: FloatingActionButton?, action: () -> Unit) {
14     button ?: return
15     val tag = "add"
16     val backgroundTintList =
17         AppCompatResources.getColorStateList(context, R.color.green)
18     val drawable = ContextCompat.getDrawable(context, android.R.drawable.ic_input_add)
19     button.tag = tag
20     button.setOnClickListener { action() }
21     button.setImageDrawable(drawable)
22     button.backgroundTintList = backgroundTintList
23 }
24 private fun buttonAsDelete(
25     context: Context,
26     button: FloatingActionButton?,
27     action: () -> Unit
28 ) {
29     button ?: return
30     val tag = "delete"
31     val backgroundTintList =
32         AppCompatResources.getColorStateList(context, R.color.red)
33     val drawable = ContextCompat.getDrawable(context, android.R.drawable.ic_delete)
34     button.tag = tag
35     button.setOnClickListener { action() }
36     button.setImageDrawable(drawable)
37     button.backgroundTintList = backgroundTintList
38 }
The SecondFragment also has a green + and a red x button to add or remove maps, respectively, using the addSurface() and deleteLastSurface() functions.
 1class CustomAdapter(private val dataSet: ArrayList<Int>) :
 2     RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
 3     class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
 4     override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
 5         val view = LayoutInflater.from(viewGroup.context)
 6             .inflate(R.layout.map_layout, viewGroup, false)
 7         val result = ViewHolder(view)
 8         result.setIsRecyclable(false)
 9         return result
10     }
11     override fun getItemCount() = dataSet.size
12     override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) = Unit
13}
The SecondFragment has a custom adapter container where the maps are stored.
 1class MainActivity : AppCompatActivity() {
 2 override fun onCreate(savedInstanceState: Bundle?) {
 3     super.onCreate(savedInstanceState)
 4     setContentView(R.layout.activity_main)
 5 }
 6 override fun onDestroy() {
 7     super.onDestroy()
 8     // Deinitialize the SDK.
 9     GemSdk.release()
10 }
11 override fun onBackPressed() {
12     finish()
13 }
14}
MainActivity overrides the onCreate() function and sets the initial screen to setContentView(R.layout.activity_main) where activity_main`` is defined in res/layout in the project. This is the first fragment above, which has the NEXT button to go to the second fragment where the maps and red and green buttons are shown.

Android Examples

Maps SDK for Android Examples can be downloaded or cloned with Git