Skip to content

Commit 820adfe

Browse files
kikosodkhawk
andauthored
chore: added Fragment sample (#727)
* chore: added Fragment sample * chore: added ViewPager example * chore: fixed GitHub flow * feat: Updates to the FragmentDemoActivity.kt Key changes include: - Renamed `activity_main.xml` to `activity_fragment_demo.xml` and added a `TextView` to indicate swipe functionality. - Renamed `MyFragmentPagerAdaptar.kt` to `MapFragmentPagerAdapter.kt` and modified it to dynamically determine the number of fragments based on `mapConfigs`. --------- Co-authored-by: dkhawk <107309+dkhawk@users.noreply.github.com>
1 parent b825285 commit 820adfe

File tree

10 files changed

+266
-5
lines changed

10 files changed

+266
-5
lines changed

.github/workflows/lint-report.yml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,26 @@ jobs:
3535
- name: Run Android Lint
3636
run: ./gradlew lint
3737

38-
- name: Merge SARIF files
39-
run: |
40-
jq -s '{ "$schema": "https://json.schemastore.org/sarif-2.1.0", "version": "2.1.0", "runs": map(.runs) | add }' maps-compose/build/reports/lint-results.sarif maps-compose-utils/build/reports/lint-results.sarif maps-compose-widgets/build/reports/lint-results.sarif maps-app/build/reports/lint-results.sarif > merged.sarif
38+
- name: Upload SARIF from maps-compose
39+
uses: github/codeql-action/upload-sarif@v3
40+
with:
41+
sarif_file: maps-compose/build/reports/lint-results.sarif
42+
category: maps-compose
43+
44+
- name: Upload SARIF from maps-compose-utils
45+
uses: github/codeql-action/upload-sarif@v3
46+
with:
47+
sarif_file: maps-compose-utils/build/reports/lint-results.sarif
48+
category: maps-compose-utils
49+
50+
- name: Upload SARIF from maps-compose-widgets
51+
uses: github/codeql-action/upload-sarif@v3
52+
with:
53+
sarif_file: maps-compose-widgets/build/reports/lint-results.sarif
54+
category: maps-compose-widgets
4155

42-
- name: Upload SARIF file
56+
- name: Upload SARIF from maps-app
4357
uses: github/codeql-action/upload-sarif@v3
4458
with:
45-
sarif_file: merged.sarif
59+
sarif_file: maps-app/build/reports/lint-results.sarif
60+
category: maps-app

gradle/libs.versions.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ mapsecrets = "2.0.1"
1818
mapsktx = "5.2.0"
1919
org-jacoco-core = "0.8.12"
2020
screenshot = "0.0.1-alpha10"
21+
constraintlayout = "2.2.1"
22+
material = "1.12.0"
2123

2224
[libraries]
2325
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }
@@ -48,6 +50,8 @@ maps-ktx-utils = { module = "com.google.maps.android:maps-utils-ktx", version.re
4850
maps-secrets-plugin = { module = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin", version.ref = "mapsecrets" }
4951
org-jacoco-core = { module = "org.jacoco:org.jacoco.core", version.ref = "org-jacoco-core" }
5052
test-junit = { module = "junit:junit", version.ref = "junit" }
53+
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
54+
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
5155

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

maps-app/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ dependencies {
6565
implementation(libs.kotlin)
6666
implementation(libs.kotlinx.coroutines.android)
6767
implementation(libs.androidx.compose.ui.preview.tooling)
68+
implementation(libs.androidx.constraintlayout)
69+
implementation(libs.material)
6870
debugImplementation(libs.androidx.compose.ui.tooling)
6971
debugImplementation(libs.leakcanary.android)
7072

maps-app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@
7272
<activity
7373
android:name=".RecompositionActivity"
7474
android:exported="false"/>
75+
<activity
76+
android:name=".FragmentDemoActivity"
77+
android:exported="false"/>
7578
<activity
7679
android:name=".markerexamples.markerdragevents.MarkerDragEventsActivity"
7780
android:exported="false"/>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.google.maps.android.compose
2+
3+
4+
import android.os.Bundle
5+
import androidx.fragment.app.FragmentActivity
6+
import androidx.viewpager2.widget.ViewPager2
7+
8+
class FragmentDemoActivity : FragmentActivity() {
9+
10+
private lateinit var viewPager: ViewPager2
11+
private lateinit var pagerAdapter: MapFragmentPagerAdapter
12+
13+
override fun onCreate(savedInstanceState: Bundle?) {
14+
super.onCreate(savedInstanceState)
15+
setContentView(R.layout.activity_fragment_demo)
16+
17+
viewPager = findViewById(R.id.view_pager)
18+
19+
pagerAdapter = MapFragmentPagerAdapter(this)
20+
viewPager.adapter = pagerAdapter
21+
22+
}
23+
}
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/MainActivity.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ class MainActivity : ComponentActivity() {
199199
}) {
200200
Text(getString(R.string.draggable_markers_collection_with_polygon))
201201
}
202+
Spacer(modifier = Modifier.padding(5.dp))
203+
Button(
204+
onClick = {
205+
context.startActivity(Intent(context, FragmentDemoActivity::class.java))
206+
}) {
207+
Text(getString(R.string.fragment_demo_activity))
208+
}
202209
}
203210
}
204211
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
class MapFragmentPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
9+
10+
private val mapConfigs = listOf(
11+
MapConfig( // First map - Los Angeles
12+
initialLatLng = LatLng(34.0522, -118.2437),
13+
initialZoom = 10f,
14+
title = "Los Angeles",
15+
// LA gets the custom content marker
16+
markerType = MarkerType.CUSTOM_CONTENT_MARKER
17+
),
18+
MapConfig( // Second map - New York City
19+
initialLatLng = LatLng(40.7128, -74.0060),
20+
initialZoom = 10f,
21+
title = "New York City",
22+
// NYC gets the standard marker
23+
markerType = MarkerType.STANDARD_MARKER_WITH_SNIPPET,
24+
standardMarkerSnippet = "The Big Apple!"
25+
)
26+
)
27+
28+
override fun getItemCount(): Int = mapConfigs.size
29+
30+
override fun createFragment(position: Int): Fragment {
31+
return GoogleMapComposeFragment.newInstance(mapConfigs[position])
32+
}
33+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:id="@+id/container"
6+
android:layout_width="match_parent"
7+
android:layout_height="match_parent"
8+
tools:context=".FragmentDemoActivity">
9+
10+
<androidx.viewpager2.widget.ViewPager2
11+
android:id="@+id/view_pager"
12+
android:layout_width="0dp"
13+
android:layout_height="0dp"
14+
app:layout_constraintBottom_toBottomOf="parent"
15+
app:layout_constraintEnd_toEndOf="parent"
16+
app:layout_constraintStart_toStartOf="parent"
17+
app:layout_constraintTop_toTopOf="parent" />
18+
19+
<TextView
20+
android:layout_width="wrap_content"
21+
android:layout_height="wrap_content"
22+
android:layout_margin="16dp"
23+
android:background="#80000000"
24+
android:padding="16dp"
25+
android:text="Swipe to switch between views"
26+
android:textColor="@android:color/white"
27+
app:layout_constraintBottom_toBottomOf="parent"
28+
app:layout_constraintEnd_toEndOf="parent"
29+
app:layout_constraintStart_toStartOf="parent" />
30+
31+
</androidx.constraintlayout.widget.ConstraintLayout>

maps-app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<string name="syncing_draggable_marker_with_data_model">Syncing Draggable Marker With Model</string>
2929
<string name="updating_non_draggable_marker_with_data_model">Updating Non-Draggable Marker With Model</string>
3030
<string name="draggable_markers_collection_with_polygon">Polygon around draggable markers</string>
31+
<string name="fragment_demo_activity">Fragment Demo Activity</string>
3132
<string name="recomposition_activity">Recomposition Map</string>
3233
<string name="street_view">Street View</string>
3334
<string name="custom_location_button">Custom Location Button</string>

0 commit comments

Comments
 (0)