JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.24k stars 1.11k forks source link

CAMetalLayer ignoring invalid setDrawableSize error #4859

Open emirhanemmez opened 1 month ago

emirhanemmez commented 1 month ago

Describe the bug I'm using ExposedDropdownMenuBox in Compose multi platform. It works fine in Android but somehow its not working on ios. I cannot see DropdownMenuItems but I can select something when I pretend its visible. Here is my code:

fun LanguageSpinner(
    modifier: Modifier = Modifier,
    placeholder: String,
    selectedLanguage: Language,
    languages: List<Language>,
    isExpanded: Boolean,
    onExpandChange: (Boolean) -> Unit,
    onLanguageSelected: (Language) -> Unit,
) {
    ExposedDropdownMenuBox(
        modifier = modifier.background(Color.White),
        expanded = isExpanded,
        onExpandedChange = onExpandChange
    ) {
        BasicTextField(
            modifier = Modifier
                .fillMaxWidth()
                .menuAnchor(),
            value = selectedLanguage.name,
            onValueChange = {},
            readOnly = true,
            textStyle = appTypography.bodyMedium,
            decorationBox = { innerTextField ->
                TextFieldDefaults.DecorationBox(
                    value = selectedLanguage.name,
                    shape = CircleShape,
                    innerTextField = innerTextField,
                    enabled = true,
                    singleLine = true,
                    interactionSource = remember {
                        MutableInteractionSource()
                    },
                    visualTransformation = VisualTransformation.None,
                    placeholder = {
                        Text(
                            text = placeholder,
                            style = appTypography.bodyMedium,
                            color = textColor.copy(alpha = 0.5f)
                        )
                    },
                    trailingIcon = {
                        ExposedDropdownMenuDefaults.TrailingIcon(expanded = isExpanded)
                    },
                    colors = TextFieldDefaults.colors(
                        disabledTextColor = Color.Transparent,
                        focusedContainerColor = Color.White,
                        unfocusedContainerColor = Color.White,
                        disabledContainerColor = Color.White,
                        errorContainerColor = Color.White,
                        focusedIndicatorColor = Color.Transparent,
                        unfocusedIndicatorColor = Color.Transparent,
                        disabledIndicatorColor = Color.Transparent,
                        unfocusedPlaceholderColor = textColor.copy(alpha = 0.5f),
                        focusedPlaceholderColor = textColor.copy(alpha = 0.5f),
                        focusedTrailingIconColor = textColor.copy(alpha = 0.5f),
                        unfocusedTrailingIconColor = textColor.copy(alpha = 0.5f),
                        unfocusedLeadingIconColor = textColor.copy(alpha = 0.5f),
                        focusedLeadingIconColor = textColor.copy(alpha = 0.5f)
                    ),
                    contentPadding = PaddingValues(
                        horizontal = LocalSpacing.current.spaceMedium,
                        vertical = LocalSpacing.current.spaceSmall
                    )
                )
            }
        )

        ExposedDropdownMenu(
            modifier = Modifier.width(100.dp)
                .background(Color.White)
                .height(300.dp),
            expanded = isExpanded,
            onDismissRequest = {
                onExpandChange.invoke(false)
            }
        ) {
            languages.forEach { language ->
                DropdownMenuItem(
                    modifier = Modifier.background(Color.White),
                    text = {
                        Text(
                            text = language.name,
                            style = appTypography.bodyMedium,
                            color = textColor
                        )
                    },
                    onClick = {
                        onExpandChange.invoke(false)
                        onLanguageSelected.invoke(language)
                    }
                )
            }
        }
    }
}

Affected platforms

Versions

This is the expected behavior (Android screenshot) image

And this is on iPhone https://github.com/JetBrains/compose-multiplatform/assets/33161529/b4ae2c6d-cc3d-4bc4-a050-553c71a82a2d

When I click dropdown component image

mazunin-v-jb commented 1 month ago

Hello, @emirhanemmez! Could you please reproduce that behavior on a clean project from the template and attach it here?

emirhanemmez commented 1 month ago

Hello, @mazunin-v-jb I captured the bug. It actually happens when you give large list to dropdownmenu. I was trying to give large country list so I got this error. You can check from this repo. There are 2 spinner here. The one has large list, other one has short list. Only the spinner with large list is not working. It works on Android fyi.

emirhanemmez commented 5 days ago

Hello @elijah-semyonov , maybe it will help. When you describe DropdownMenuItem with LazyColumn not with forEach and give specific height and width to LazyColumn, it works on ios as well.

Old code:

ExposedDropdownMenu(
            modifier = Modifier.width(100.dp)
                .background(Color.White)
                .height(300.dp),
            expanded = isExpanded,
            onDismissRequest = {
                onExpandChange.invoke(false)
            }
        ) {
            languages.forEach { language ->
                DropdownMenuItem(
                    modifier = Modifier.background(Color.White),
                    text = {
                        Text(
                            text = language,
                        )
                    },
                    onClick = {
                        onExpandChange.invoke(false)
                        onLanguageSelected.invoke(language)
                    }
                )
            }
        }

New code:

ExposedDropdownMenu(
            expanded = isExpanded,
            onDismissRequest = {
                onExpandChange.invoke(false)
            }
        ) {
            LazyColumn(
                modifier = Modifier
                    .width(200.dp)
                    .height(300.dp)
            ) {
                items(languages) { language ->
                    DropdownMenuItem(
                        modifier = Modifier.background(Color.White),
                        text = {
                            Text(
                                text = language.name,
                                style = appTypography.bodyMedium,
                                color = textColor
                            )
                        },
                        onClick = {
                            onExpandChange.invoke(false)
                            onLanguageSelected.invoke(language)
                        }
                    )
                }
            }
        }