Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.google.maps.android.compose

import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeUp
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

class MapsInLazyColumnTests {
@get:Rule
val composeTestRule = createComposeRule()

private val mapItems = listOf(
MapListItem(id = "1", location = LatLng(1.23, 4.56), zoom = 10f, title = "Item 1"),
MapListItem(id = "2", location = LatLng(7.89, 0.12), zoom = 12f, title = "Item 2"),
MapListItem(id = "3", location = LatLng(3.45, 6.78), zoom = 11f, title = "Item 3"),
MapListItem(id = "4", location = LatLng(9.01, 2.34), zoom = 13f, title = "Item 4"),
MapListItem(id = "5", location = LatLng(5.67, 8.90), zoom = 9f, title = "Item 5"),
MapListItem(id = "6", location = LatLng(4.32, 7.65), zoom = 14f, title = "Item 6"),
MapListItem(id = "7", location = LatLng(8.76, 1.23), zoom = 10f, title = "Item 7"),
MapListItem(id = "8", location = LatLng(2.98, 6.54), zoom = 12f, title = "Item 8"),
MapListItem(id = "9", location = LatLng(7.65, 3.21), zoom = 11f, title = "Item 9"),
MapListItem(id = "10", location = LatLng(0.12, 9.87), zoom = 13f, title = "Item 10"),
)


private lateinit var cameraPositionStates: Map<MapItemId, CameraPositionState>

private fun initMaps() {
check(hasValidApiKey) { "Maps API key not specified" }

composeTestRule.setContent {
val lazyListState = rememberLazyListState()
val visibleMapCount = remember { mutableStateOf(0) }

val visibleItems by remember {
derivedStateOf {
lazyListState.layoutInfo.visibleItemsInfo.size
}
}

LaunchedEffect(visibleItems) {
visibleMapCount.value = visibleItems
}

val countDownLatch = CountDownLatch(visibleMapCount.value)

MapsInLazyColumn(
mapItems,
lazyListState = lazyListState,
onMapLoaded = {
countDownLatch.countDown()
}
)

LaunchedEffect(Unit) {
val mapsLoaded = countDownLatch.await(30, TimeUnit.SECONDS)
assertTrue("Visible maps loaded", mapsLoaded)
}
}
}

@Before
fun setUp() {
cameraPositionStates = mapItems.associate { item ->
item.id to CameraPositionState(
position = CameraPosition.fromLatLngZoom(item.location, item.zoom)
)
}
}

@Test
fun testStartingCameraPositions() {
initMaps()
mapItems.forEach { item ->
item.location.assertEquals(cameraPositionStates[item.id]?.position?.target!!)
}
}

@Test
fun testLazyColumnScrolls_MapPositionsRemain() {
initMaps()
composeTestRule.onRoot().performTouchInput { swipeUp() }
composeTestRule.waitForIdle()

mapItems.forEach { item ->
item.location.assertEquals(cameraPositionStates[item.id]?.position?.target!!)
}
}

@Test
fun testScrollToBottom() {
initMaps()
composeTestRule.onRoot().performTouchInput { swipeUp(durationMillis = 1000) }
composeTestRule.waitForIdle()
//We do not need to check anything on the test, just to make sure the scroll down doesnt crash
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
Expand All @@ -40,7 +41,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
Expand All @@ -51,12 +52,16 @@ import com.google.android.gms.maps.model.LatLng

private data class CountryLocation(val name: String, val latLng: LatLng, val zoom: Float)

private typealias MapItemId = String
typealias MapItemId = String

// From https://developers.google.com/public-data/docs/canonical/countries_csv
private val countries = listOf(
CountryLocation("Hong Kong", LatLng(22.396428, 114.109497), 5f),
CountryLocation("Madison Square Garden (has indoor mode)", LatLng(40.7504656, -73.9937246), 19.33f),
CountryLocation(
"Madison Square Garden (has indoor mode)",
LatLng(40.7504656, -73.9937246),
19.33f
),
CountryLocation("Bolivia", LatLng(-16.290154, -63.588653), 5f),
CountryLocation("Ecuador", LatLng(-1.831239, -78.183406), 5f),
CountryLocation("Sweden", LatLng(60.128161, 18.643501), 5f),
Expand All @@ -74,7 +79,7 @@ private val countries = listOf(
CountryLocation("Burundi", LatLng(-3.373056, 29.918886), 5f)
)

private data class MapListItem(
data class MapListItem(
val title: String,
val location: LatLng,
val zoom: Float,
Expand All @@ -98,7 +103,8 @@ class MapsInLazyColumnActivity : ComponentActivity() {
}

Column(
Modifier.fillMaxSize()
Modifier
.fillMaxSize()
.systemBarsPadding(),
) {
Row(
Expand All @@ -125,7 +131,7 @@ class MapsInLazyColumnActivity : ComponentActivity() {
}
if (showLazyColumn) {
Box(Modifier.border(1.dp, Color.LightGray.copy(0.5f))) {
MapsInLazyColumn(visibleItems)
MapsInLazyColumn(visibleItems, onMapLoaded = { })
}
}
}
Expand All @@ -134,8 +140,15 @@ class MapsInLazyColumnActivity : ComponentActivity() {
}

@Composable
private fun MapsInLazyColumn(mapItems: List<MapListItem>) {
val lazyListState = rememberLazyListState()
fun MapsInLazyColumn(
mapItems: List<MapListItem>,
lazyListState: LazyListState = rememberLazyListState(),
onMapLoaded: () -> Unit
) {

var isMapLoaded by remember { mutableStateOf(false) }

val lazyListState = lazyListState

val cameraPositionStates = mapItems.associate { item ->
item.id to rememberCameraPositionState(
Expand Down Expand Up @@ -168,7 +181,10 @@ private fun MapsInLazyColumn(mapItems: List<MapListItem>) {
.height(300.dp),
contentAlignment = Alignment.Center
) {
MapCard(item, cameraPositionState)
MapCard(item, cameraPositionState, onMapLoaded = {
isMapLoaded = true
onMapLoaded()
})
}
}
}
Expand All @@ -177,7 +193,11 @@ private fun MapsInLazyColumn(mapItems: List<MapListItem>) {

@OptIn(MapsComposeExperimentalApi::class)
@Composable
private fun MapCard(item: MapListItem, cameraPositionState: CameraPositionState) {
private fun MapCard(
item: MapListItem,
cameraPositionState: CameraPositionState,
onMapLoaded: () -> Unit,
) {
Card(
Modifier.padding(16.dp),
elevation = 4.dp
Expand All @@ -192,11 +212,13 @@ private fun MapCard(item: MapListItem, cameraPositionState: CameraPositionState)
var map: GoogleMap? by remember { mutableStateOf(null) }

fun updateIndoorLevel() {
activatedIndoorLevel = map!!.focusedBuilding?.run { levels.getOrNull(activeLevelIndex)?.name }
activatedIndoorLevel =
map!!.focusedBuilding?.run { levels.getOrNull(activeLevelIndex)?.name }
}

Box {
GoogleMap(
modifier = Modifier.testTag("Map"),
onMapClick = {
onMapClickCount++
},
Expand All @@ -207,7 +229,10 @@ private fun MapCard(item: MapListItem, cameraPositionState: CameraPositionState)
)
},
cameraPositionState = cameraPositionState,
onMapLoaded = { mapLoaded = true },
onMapLoaded = {
onMapLoaded.invoke()
mapLoaded = true
},
indoorStateChangeListener = object : IndoorStateChangeListener {
override fun onIndoorBuildingFocused() {
super.onIndoorBuildingFocused()
Expand Down Expand Up @@ -242,7 +267,7 @@ private fun MapCard(item: MapListItem, cameraPositionState: CameraPositionState)
@Composable
fun TextWithBackground(text: String, fontWeight: FontWeight = FontWeight.Medium) {
Text(
modifier = Modifier.background(Color.White.copy(0.7f)),
modifier = Modifier.background(Color.White.copy(0.7f)).testTag(text),
text = text,
fontWeight = fontWeight,
fontSize = 10.sp
Expand Down
Loading