android-maps-compose icon indicating copy to clipboard operation
android-maps-compose copied to clipboard

MarkerState.showInfoWindow() not working after states are changed

Open thomaslang1912 opened this issue 3 years ago • 7 comments

I created a map with some markers on it:

GoogleMap(
	modifier = Modifier.matchParentSize(),
	cameraPositionState = cameraPositionState,
	uiSettings = mapUiSettings,
	onMapClick = {
	},
) {
	model.markerStates.forEachIndexed { index, markerState ->
		MarkerInfoWindowContent(
			state = markerState,
			title = "Match Marker",
			draggable = true,
		) {
			Text("Home $index : Away $index", color = Color.Red)
		}
	}
}

The markerStates are stored within the model in variable markerStates:

class MapModel : ViewModel() {
	val markerStates = mutableStateListOf<MarkerState>()
	var uiSelectedMatchIndex = mutableStateOf<Int>(-1)
	val aroundMode = mutableStateOf<Int>(0)

	fun nextMatch() {
		if (markerStates.size <= 1)
			return
		if (uiSelectedMatchIndex.value < markerStates.size - 1)
			uiSelectedMatchIndex.value++
		else
			uiSelectedMatchIndex.value = 0
	}
}

On the map I added a button. On click it iterates the marker states and shows the info window:

IconButton(
	onClick = {
		model.nextMatch()
		if (model.uiSelectedMatchIndex.value > -1) {
			model.markerStates[model.uiSelectedMatchIndex.value].showInfoWindow()
		}
	}
) {
	Icon(
		Icons.Outlined.KeyboardArrowRight,
		contentDescription = ""
	)
}

This works fine. Now I added a button which replaces the states in the model with new ones:

IconButton(
	onClick = {
		model.markerStates.clear()
		markerStates.addAll(nearbyMarkers())
		model.markerStates[model.uiSelectedMatchIndex.value].showInfoWindow()
	},
) {
	Icon(
		Icons.Outlined.AccountCircle,
		contentDescription = ""
	)
}

When I press this button, the new markers are displayed on the map and the first infoWindow is displayed. All following clicks on next have no effect. Always the same InfoWindow is displayed. In debug mode I saw that iteration of markerStates works correct.

Environment details

project gradle

buildscript {
    ext {
        ext.kotlin_version = '1.7.10'
        ext.compose_compiler_version = '1.2.0'
        ext.compose_version = '1.2.0-rc03'
    }
}
plugins {
    id 'com.android.application' version '7.2.2' apply false
    id 'com.android.library' version '7.2.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}

module gradle

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.example.markerstatebug"
        minSdk 30
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion "1.3.0"//compose_version
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {

    implementation 'androidx.activity:activity-compose:1.5.1'
    implementation "androidx.compose.foundation:foundation:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation 'androidx.core:core-ktx:1.8.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
    implementation "androidx.compose.ui:ui-tooling-preview:1.2.1"
    implementation "androidx.compose.runtime:runtime-livedata:1.2.1"
    implementation "androidx.compose.ui:ui-tooling:1.2.1"

    implementation "com.google.maps.android:maps-compose:2.2.1"
    implementation 'com.google.android.gms:play-services-maps:18.1.0'
    implementation 'com.google.android.material:material:1.6.1'
    implementation 'com.google.maps.android:maps-ktx:3.4.0'
    implementation 'com.google.maps.android:android-maps-utils:2.3.0'

    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
    debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
}

thomaslang1912 avatar Aug 23 '22 10:08 thomaslang1912

@thomaslang1912 can you share the implementation of nearbyMarkers()?

arriolac avatar Aug 30 '22 18:08 arriolac

Hi Chris, to keep it simple I used the following implementation for showing the bug:

val list1 = listOf( MarkerState( LatLng(48.218967, 11.623746) ), MarkerState( LatLng(48.218967, 11.663746) ) )

val list2 = listOf( MarkerState( LatLng(48.238967, 11.623746) ), MarkerState( LatLng(48.258967, 11.623746) ) )

fun initialMarkers(): List<MarkerState> { return list1 }

fun nearbyMarkers(): List<MarkerState> { return list2 }

Best regards,

Thomas

thomaslang1912 avatar Aug 31 '22 08:08 thomaslang1912

hello @thomaslang1912 ,

I've had a similar issue here, that I was able to solve by using rememberMarkerState.

cmota avatar Nov 04 '22 00:11 cmota

Hi Carlos, using rememberMarkerState has no effect. As soon as the list of markers is changed showInfoWindow is not working anymore... @arriolac will there be a fix in future?

thomaslang1912 avatar Dec 30 '22 12:12 thomaslang1912

Hello @thomaslang1912,

I've used that approach and it worked. I don't have the project here right now, but I can attach a snippet next week.

cmota avatar Dec 30 '22 13:12 cmota

Try Marker window info instead with MarkerState

MarkerInfoWindow(
                        state = MarkerState(position = position),
                        onClick = {

                            if (currentMarkerInfoWindow.position == it.position) {
                                it.hideInfoWindow()
                                currentMarkerInfoWindow.position = LatLng(0.00, 0.00)
                            } else {
                                it.showInfoWindow()
                                currentMarkerInfoWindow.position = it.position
                            }

                            true
                        },
                        content = {...}

PranayHousing avatar Apr 03 '23 11:04 PranayHousing