Skip to content

MarkerComposable throw Fatal Exception: java.lang.IllegalArgumentException: width and height must be > 0 #694

Open
@CarloskHard

Description

@CarloskHard

When I try to make a cluter of custom markers with MarkerComposable it gives me an error of size 0 even if I forze a size (I have tried every modifier of size= size, height/width, requiredSize,..) . If I don't user Clusters, it works.
There's a few reports of this exact same problem that you have closed even tough people are still telling it is still happening so please don't close this until everyone says it's fixed

Environment details

  1. I am using the API mapsCompose = "6.5.0"
  2. Windows with Android Studio: Build #AI-243.22562.218.2431.13114758, built on February 25, 2025

Runtime version: 21.0.5+-12932927-b750.29 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.

Kotlin plugin: K2 mode

Steps to reproduce

  1. Try to make a cluter of markers

Code example

`package es.platorama.ui.explorador.mapa

import android.graphics.Bitmap
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DarkMode
import androidx.compose.material.icons.filled.WbSunny
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.graphics.Path
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.graphics.createBitmap
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MapStyleOptions
import com.google.maps.android.clustering.ClusterItem
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.GoogleMapComposable
import com.google.maps.android.compose.MapProperties
import com.google.maps.android.compose.MapUiSettings
import com.google.maps.android.compose.MapsComposeExperimentalApi
import com.google.maps.android.compose.MarkerComposable
import com.google.maps.android.compose.MarkerState
import com.google.maps.android.compose.clustering.Clustering
import com.google.maps.android.compose.rememberCameraPositionState
import es.platorama.R
import es.platorama.ui.explorador.BotonCentrarMapaCustom
import es.platorama.ui.explorador.MarcadorLocal

@OptIn(MapsComposeExperimentalApi::class)
@composable
fun MapScreen(ubiUser: LatLng?, marcadores: State<List>, bottomPadding: Dp) {
var initialCameraSet by remember { mutableStateOf(false) }
val defaultPosition = LatLng(0.0, 0.0)
var isDarkMode by remember { mutableStateOf(true) } // Estado para cambiar el tema del mapa
val context = LocalContext.current

val cameraPositionState = rememberCameraPositionState {
    position = CameraPosition.fromLatLngZoom(ubiUser ?: defaultPosition, 15f)
}

LaunchedEffect(ubiUser) {
    if (!initialCameraSet && ubiUser != null) {
        cameraPositionState.animate(CameraUpdateFactory.newLatLng(ubiUser))
        initialCameraSet = true
    }
}

val mapProperties = remember(isDarkMode) {
    MapProperties(
        isMyLocationEnabled = true,
        mapStyleOptions = if (isDarkMode) {
            MapStyleOptions.loadRawResourceStyle(context, R.raw.map_style_dark)
        } else {
            null // Usa el tema predeterminado de Google Maps
        }
    )
}

val mapUiSettings = MapUiSettings(
    myLocationButtonEnabled = false,
    zoomControlsEnabled = false,
    compassEnabled = false,
)

Box(modifier = Modifier.fillMaxSize()) {
    GoogleMap(
        modifier = Modifier.fillMaxSize(),
        cameraPositionState = cameraPositionState,
        properties = mapProperties,
        uiSettings = mapUiSettings,
        contentPadding = PaddingValues(bottom = bottomPadding)
    ) {
        val marcadoresItems =
            marcadores.value.map { marcador ->
                MarcadorCustomClusterItem(
                    position = marcador.latLng,
                    title = "fdasfadsfa",
                    snippet = marcador.rating.toString()
                )
            }
        Log.d("Carlos MapScreen", "Llamando a clustering-> ${marcadoresItems.size}")
        Clustering(
            items = marcadoresItems,
            clusterItemContent = {
                Log.d("Carlos MapScreen", "ClusterItemContent called")
                CustomMapMarker(
                    latLng = it.position,
                    rating = it.snippet.toFloat()
                )
            }
        )
        /*
        // Marcadores personalizados
        marcadores.value.forEach() { marcador ->
            CustomMapMarker(marcador.latLng, marcador.rating,)
        }*/
    }

    // Botón para cambiar el modo claro/oscuro
    FloatingActionButton(
        onClick = { isDarkMode = !isDarkMode },
        modifier = Modifier
            .align(Alignment.TopStart)
            .padding(15.dp)
            .size(30.dp)
    ) {
        Icon(
            imageVector = if (isDarkMode) Icons.Default.DarkMode else Icons.Default.WbSunny,
            contentDescription = "Cambiar tema del mapa"
        )
    }
    // Botón para centrar en user (Sustituyo al que viene por defecto)
    BotonCentrarMapaCustom(cameraPositionState, ubiUser, defaultPosition,
        modifier = Modifier
            .align(Alignment.TopEnd)
            .padding(15.dp)
            .size(30.dp)
    )
}

}

// Define una clase para tus items de cluster
class MarcadorCustomClusterItem(
private val position: LatLng,
private val title: String,
private val snippet: String
) : ClusterItem {
override fun getPosition(): LatLng = position
override fun getTitle(): String = title
override fun getSnippet(): String = snippet
override fun getZIndex(): Float = 1f
}

@composable
@GoogleMapComposable
fun CustomMapMarker(latLng: LatLng ,rating: Float) {
val markerState = remember { MarkerState(position = latLng) }
Log.d("Carlos MapScreen", "CustomMapMarker called inside")
MarkerComposable (
keys = arrayOf("array test"),
state = markerState,
){
Box(
modifier = Modifier
.requiredSize(50.dp)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Box(
modifier = Modifier
.background(Color(0xFF6200EE), shape = RoundedCornerShape(4.dp))
.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Text(
//text = String.format("%.1f", rating),
text = "prueba",
color = Color.White,
fontSize = 14.sp,
fontWeight = FontWeight.Bold
)
}

            Spacer(modifier = Modifier.height(2.dp)) // Añade un espacio para asegurar altura

            Canvas(
                modifier = Modifier
                    .size(width = 20.dp, height = 10.dp)
                    .align(Alignment.CenterHorizontally)
            ) {
                val path = Path().apply {
                    moveTo(0f, 0f)
                    lineTo(size.width, 0f)
                    lineTo(size.width / 2f, size.height)
                    close()
                }
                drawPath(
                    path = path,
                    color = Color(0xFF6200EE)
                )
            }
        }
    }
}

}

/*
@Preview
@composable
fun preview(){
CustomMapMarker(rating = 4.5f)
}*/`

Stack trace

java.lang.IllegalStateException: The ComposeView was measured to have a width or height of zero. Make sure that the content has a non-zero size. at com.google.maps.android.compose.RememberComposeBitmapDescriptorKt.renderComposableToBitmapDescriptor(RememberComposeBitmapDescriptor.kt:58) at com.google.maps.android.compose.RememberComposeBitmapDescriptorKt.access$renderComposableToBitmapDescriptor(RememberComposeBitmapDescriptor.kt:1) at com.google.maps.android.compose.RememberComposeBitmapDescriptorKt.rememberComposeBitmapDescriptor(RememberComposeBitmapDescriptor.kt:29) at com.google.maps.android.compose.MarkerKt.MarkerComposable-Khg_OnI(Marker.kt:342) at es.platorama.ui.explorador.mapa.MapaScreensKt.CustomMapMarker(MapaScreens.kt:169) at es.platorama.ui.explorador.mapa.ComposableSingletons$MapaScreensKt$lambda-1$1.invoke(MapaScreens.kt:116) at es.platorama.ui.explorador.mapa.ComposableSingletons$MapaScreensKt$lambda-1$1.invoke(MapaScreens.kt:114) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer$createAndAddView$view$2.invoke(ClusterRenderer.kt:95) at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer$createAndAddView$view$2.invoke(ClusterRenderer.kt:95) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer$InvalidatingComposeView.Content(ClusterRenderer.kt:222) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:259) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:258) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:380) at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:216) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:132) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:131) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:380) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:121) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:155) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:154) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:401) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:154) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:133) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) 2025-03-17 19:23:04.541 23672-23672 AndroidRuntime es.platorama.debug E at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:97) (Ask Gemini) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3595) at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3522) at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:743) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1122) at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:3876) at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:649) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:635) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:124) at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1626) at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:124) at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:180) at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:320) at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:198) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:124) at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1707) at android.view.View.dispatchAttachedToWindow(View.java:22895) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3506) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3513) at android.view.ViewGroup.addViewInner(ViewGroup.java:5318) at android.view.ViewGroup.addView(ViewGroup.java:5104) at android.view.ViewGroup.addView(ViewGroup.java:5044) at android.view.ViewGroup.addView(ViewGroup.java:5016) at com.google.maps.android.compose.MapComposeViewRenderKt.startRenderingComposeView(MapComposeViewRender.kt:46) at com.google.maps.android.compose.MapViewDelegate.startRenderingComposeView(GoogleMap.kt:378) at com.google.maps.android.compose.MapComposeViewRenderKt$rememberComposeUiViewRenderer$1$1.startRenderingView(MapComposeViewRender.kt:92) at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer.createAndAddView(ClusterRenderer.kt:99) at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer.onClustersChanged(ClusterRenderer.kt:67) at com.google.maps.android.clustering.ClusterManager$ClusterTask.onPostExecute(ClusterManager.java:322) at com.google.maps.android.clustering.ClusterManager$ClusterTask.onPostExecute(ClusterManager.java:308) at android.os.AsyncTask.finish(AsyncTask.java:771) at android.os.AsyncTask.-$$Nest$mfinish(Unknown Source:0) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788) at android.os.Handler.dispatchMessage(Handler.java:109) at android.os.Looper.loopOnce(Looper.java:232) at android.os.Looper.loop(Looper.java:317) at android.app.ActivityThread.main(ActivityThread.java:8787) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:591) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:871)

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage meI really want to be triaged.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions