Skip to content

Commit 8b765e4

Browse files
committed
chore: added ViewPager example
1 parent 3198483 commit 8b765e4

File tree

7 files changed

+201
-40
lines changed

7 files changed

+201
-40
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mapsktx = "5.2.0"
1919
org-jacoco-core = "0.8.12"
2020
screenshot = "0.0.1-alpha10"
2121
constraintlayout = "2.2.1"
22+
material = "1.12.0"
2223

2324
[libraries]
2425
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }
@@ -50,6 +51,7 @@ maps-secrets-plugin = { module = "com.google.android.libraries.mapsplatform.secr
5051
org-jacoco-core = { module = "org.jacoco:org.jacoco.core", version.ref = "org-jacoco-core" }
5152
test-junit = { module = "junit:junit", version.ref = "junit" }
5253
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
54+
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
5355

5456
[plugins]
5557
android-application = { id = "com.android.application", version.ref = "agp" }

maps-app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ dependencies {
6666
implementation(libs.kotlinx.coroutines.android)
6767
implementation(libs.androidx.compose.ui.preview.tooling)
6868
implementation(libs.androidx.constraintlayout)
69+
implementation(libs.material)
6970
debugImplementation(libs.androidx.compose.ui.tooling)
7071
debugImplementation(libs.leakcanary.android)
7172

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
package com.google.maps.android.compose
22

3+
34
import android.os.Bundle
45
import androidx.fragment.app.FragmentActivity
6+
import androidx.viewpager2.widget.ViewPager2
7+
8+
class FragmentDemoActivity : FragmentActivity() {
59

6-
class FragmentDemoActivity : FragmentActivity() {
10+
private lateinit var viewPager: ViewPager2
11+
private lateinit var pagerAdapter: MapFragmentPagerAdapter
712

813
override fun onCreate(savedInstanceState: Bundle?) {
914
super.onCreate(savedInstanceState)
1015
setContentView(R.layout.activity_main)
16+
17+
viewPager = findViewById(R.id.view_pager)
18+
19+
pagerAdapter = MapFragmentPagerAdapter(this)
20+
viewPager.adapter = pagerAdapter
21+
1122
}
1223
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package com.google.maps.android.compose
2+
3+
import android.os.Bundle
4+
import android.view.LayoutInflater
5+
import android.view.View
6+
import android.view.ViewGroup
7+
import androidx.compose.material.MaterialTheme
8+
import androidx.compose.material.Text
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.ui.geometry.Offset // For MarkerComposable anchor
11+
import androidx.compose.ui.platform.ComposeView
12+
import androidx.compose.ui.platform.ViewCompositionStrategy
13+
import androidx.fragment.app.Fragment
14+
import com.google.android.gms.maps.model.CameraPosition
15+
import com.google.android.gms.maps.model.LatLng
16+
17+
18+
enum class MarkerType {
19+
CUSTOM_CONTENT_MARKER, // To use com.google.maps.android.compose.MarkerComposable with your Text
20+
STANDARD_MARKER_WITH_SNIPPET // To use the standard com.google.maps.android.compose.Marker
21+
}
22+
23+
data class MapConfig(
24+
val initialLatLng: LatLng,
25+
val initialZoom: Float,
26+
val title: String,
27+
val markerType: MarkerType = MarkerType.CUSTOM_CONTENT_MARKER, // Default
28+
val standardMarkerSnippet: String? = null
29+
)
30+
31+
class GoogleMapComposeFragment : Fragment() {
32+
33+
private var mapConfig: MapConfig? = null
34+
35+
override fun onCreate(savedInstanceState: Bundle?) {
36+
super.onCreate(savedInstanceState)
37+
arguments?.let {
38+
val lat = it.getDouble(ARG_LAT, Double.NaN)
39+
val lng = it.getDouble(ARG_LNG, Double.NaN)
40+
val zoom = it.getFloat(ARG_ZOOM, 10f)
41+
val title = it.getString(ARG_TITLE, "Map")
42+
43+
val markerTypeName = it.getString(ARG_MARKER_TYPE)
44+
val markerType = markerTypeName?.let { name ->
45+
try {
46+
MarkerType.valueOf(name)
47+
} catch (e: IllegalArgumentException) {
48+
MarkerType.CUSTOM_CONTENT_MARKER
49+
}
50+
} ?: MarkerType.CUSTOM_CONTENT_MARKER
51+
52+
val snippet = it.getString(ARG_STANDARD_MARKER_SNIPPET)
53+
54+
if (!lat.isNaN() && !lng.isNaN()) {
55+
mapConfig = MapConfig(
56+
initialLatLng = LatLng(lat, lng),
57+
initialZoom = zoom,
58+
title = title,
59+
markerType = markerType,
60+
standardMarkerSnippet = snippet
61+
)
62+
}
63+
}
64+
}
65+
66+
override fun onCreateView(
67+
inflater: LayoutInflater,
68+
container: ViewGroup?,
69+
savedInstanceState: Bundle?
70+
): View = ComposeView(requireContext()).apply {
71+
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
72+
setContent {
73+
MaterialTheme {
74+
val currentConfig = mapConfig ?: MapConfig(
75+
initialLatLng = LatLng(0.0, 0.0),
76+
initialZoom = 2f,
77+
title = "Default Map",
78+
markerType = MarkerType.CUSTOM_CONTENT_MARKER
79+
)
80+
MapContent(config = currentConfig)
81+
}
82+
}
83+
}
84+
85+
@Composable
86+
fun MapContent(config: MapConfig) {
87+
val cameraPositionState = rememberCameraPositionState {
88+
position = CameraPosition.fromLatLngZoom(config.initialLatLng, config.initialZoom)
89+
}
90+
91+
GoogleMap(
92+
cameraPositionState = cameraPositionState
93+
) {
94+
when (config.markerType) {
95+
MarkerType.CUSTOM_CONTENT_MARKER -> {
96+
val markerState = rememberUpdatedMarkerState(position = config.initialLatLng)
97+
markerState.position = config.initialLatLng
98+
99+
MarkerComposable(
100+
state = markerState,
101+
anchor = Offset(0.5f, 1.0f)
102+
){
103+
Text(text = "Hello, World! (from ${config.title})")
104+
}
105+
}
106+
MarkerType.STANDARD_MARKER_WITH_SNIPPET -> {
107+
val markerState = rememberUpdatedMarkerState(position = config.initialLatLng)
108+
markerState.position = config.initialLatLng
109+
110+
Marker(
111+
state = markerState,
112+
title = config.title,
113+
snippet = config.standardMarkerSnippet ?: "Standard Marker Snippet" // Snippet for the info window
114+
)
115+
}
116+
}
117+
}
118+
}
119+
120+
companion object {
121+
private const val ARG_LAT = "arg_lat"
122+
private const val ARG_LNG = "arg_lng"
123+
private const val ARG_ZOOM = "arg_zoom"
124+
private const val ARG_TITLE = "arg_title"
125+
private const val ARG_MARKER_TYPE = "arg_marker_type"
126+
private const val ARG_STANDARD_MARKER_SNIPPET = "arg_standard_marker_snippet"
127+
128+
@JvmStatic
129+
fun newInstance(config: MapConfig): GoogleMapComposeFragment {
130+
return GoogleMapComposeFragment().apply {
131+
arguments = Bundle().apply {
132+
putDouble(ARG_LAT, config.initialLatLng.latitude)
133+
putDouble(ARG_LNG, config.initialLatLng.longitude)
134+
putFloat(ARG_ZOOM, config.initialZoom)
135+
putString(ARG_TITLE, config.title)
136+
putString(ARG_MARKER_TYPE, config.markerType.name)
137+
config.standardMarkerSnippet?.let { putString(ARG_STANDARD_MARKER_SNIPPET, it) }
138+
}
139+
}
140+
}
141+
}
142+
}

maps-app/src/main/java/com/google/maps/android/compose/MainFragment.kt

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.google.maps.android.compose
2+
3+
import androidx.fragment.app.Fragment
4+
import androidx.fragment.app.FragmentActivity
5+
import androidx.viewpager2.adapter.FragmentStateAdapter
6+
import com.google.android.gms.maps.model.LatLng
7+
8+
private const val NUM_MAP_FRAGMENTS = 2
9+
10+
class MapFragmentPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
11+
12+
private val mapConfigs = listOf(
13+
MapConfig( // First map - Los Angeles
14+
initialLatLng = LatLng(34.0522, -118.2437),
15+
initialZoom = 10f,
16+
title = "Los Angeles",
17+
// LA gets the custom content marker
18+
markerType = MarkerType.CUSTOM_CONTENT_MARKER
19+
),
20+
MapConfig( // Second map - New York City
21+
initialLatLng = LatLng(40.7128, -74.0060),
22+
initialZoom = 10f,
23+
title = "New York City",
24+
// NYC gets the standard marker
25+
markerType = MarkerType.STANDARD_MARKER_WITH_SNIPPET,
26+
standardMarkerSnippet = "The Big Apple!"
27+
)
28+
)
29+
30+
override fun getItemCount(): Int = NUM_MAP_FRAGMENTS
31+
32+
override fun createFragment(position: Int): Fragment {
33+
return GoogleMapComposeFragment.newInstance(mapConfigs[position])
34+
}
35+
}
Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3-
xmlns:tools="http://schemas.android.com/tools"
43
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
55
android:id="@+id/container"
66
android:layout_width="match_parent"
77
android:layout_height="match_parent"
8-
tools:context=".MainActivity">
8+
tools:context=".FragmentDemoActivity">
99

10-
<androidx.fragment.app.FragmentContainerView
11-
android:layout_width="match_parent"
12-
android:layout_height="match_parent"
13-
android:id="@+id/viewFragment"
14-
android:name="com.google.maps.android.compose.MainFragment"
15-
app:layout_constraintTop_toTopOf="parent"
10+
<androidx.viewpager2.widget.ViewPager2
11+
android:id="@+id/view_pager"
12+
android:layout_width="0dp"
13+
android:layout_height="0dp"
1614
app:layout_constraintBottom_toBottomOf="parent"
15+
app:layout_constraintEnd_toEndOf="parent"
1716
app:layout_constraintStart_toStartOf="parent"
18-
app:layout_constraintEnd_toEndOf="parent" />
17+
app:layout_constraintTop_toTopOf="parent" />
1918

20-
</androidx.constraintlayout.widget.ConstraintLayout>
19+
</androidx.constraintlayout.widget.ConstraintLayout>

0 commit comments

Comments
 (0)