Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asking for intrinsic measurements of SubcomposeLayout layouts is not supported. #482

Closed
KwonDae opened this issue May 3, 2024 · 6 comments

Comments

@KwonDae
Copy link
Contributor

KwonDae commented May 3, 2024

Please complete the following information:

  • Library Version : 2.3.3
  • Affected Device(s) : Samsung Galaxy Fold3 with Android 14.0

Describe the Bug:

Scaffold {
   Column {
      TabRow {
         Tab {
            LazyColumn {
                GlideImage
            ...

I'm using as above structure.
When I use GlideImage inside TabRow, the following error occurs,

java.lang.IllegalStateException: Asking for intrinsic measurements of SubcomposeLayout layouts is not supported. 
This includes components that are built on top of SubcomposeLayout, such as lazy lists, BoxWithConstraints, TabRow, etc. To mitigate this:
 
- if intrinsic measurements are used to achieve 'match parent' sizing, 
consider replacing the parent of the component with a custom layout which controls the order in which children are measured, 
making intrinsic measurement not needed

- adding a size modifier to the component, in order to fast return the queried intrinsic measurement.

It is said that it does not support intrinsic measurements behavior inside components such as TabRow using SubcomposeLayout.

@Composable
fun TabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    containerColor: Color = TabRowDefaults.primaryContainerColor,
    contentColor: Color = TabRowDefaults.primaryContentColor,
    indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->
        if (selectedTabIndex < tabPositions.size) {
            TabRowDefaults.SecondaryIndicator(
                Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
            )
        }
    },
    divider: @Composable () -> Unit = @Composable {
        HorizontalDivider()
    },
    tabs: @Composable () -> Unit
) {
    TabRowWithSubcomposeImpl(modifier, containerColor, contentColor, indicator, divider, tabs)
}

Is it possible that the contents of the ImageLoad are using BoxWithConstraintsScope internally in the process of calling the ImageLoad function in private fun GlideImage?

@Composable
public fun <T : Any> ImageLoad(
  recomposeKey: T?,
  executeImageRequest: suspend () -> Flow<ImageLoadState>,
  modifier: Modifier = Modifier,
  imageOptions: ImageOptions,
  constrainable: Constrainable? = null,
  content: @Composable BoxWithConstraintsScope.(imageState: ImageLoadState) -> Unit,
) {
image
@skydoves
Copy link
Owner

skydoves commented May 6, 2024

Hey @KwonDae, I believe you'll be able to resolve this issue by wrapping your GlideImage with a Box Composable, as demonstrated in the code below:

Box(modifier = Modifier.size(56.dp)) {
          GlideImage(..)
}

@KwonDae
Copy link
Contributor Author

KwonDae commented May 6, 2024

Thanks @skydoves
Should I use fixed size in parent composable of GlideImage?

    FlowRow(
        modifier = modifier.fillMaxWidth(),
        maxItemsInEachRow = 2,
    ) {
        items.forEach {
            ImageItem(
                item = it,
                modifier = Modifier.weight(0.5f)
            )
        }
    }

I use GlideImage within Modifier.weight

@skydoves
Copy link
Owner

skydoves commented May 7, 2024

Hi @KwonDae, you actually don't need to use FlowRow if you want to maintain the same width for each item as half the size. Instead, you can utilize LazyVerticalGrid.

LazyVerticalGrid(
      modifier = Modifier.fillMaxWidth(),
      columns = GridCells.Fixed(2)
) {

@KwonDae
Copy link
Contributor Author

KwonDae commented May 8, 2024

Hi @skydoves, Thanks to you, I was able to solve the Issue.
I'm more curious to see how coil render image without that issue in FlowRow. I find AsyncImage using SizeResolver with ConstraintSizeResolver.
Has it something to do with above issue?

GlideImage render content within BoxWithConstraintsScope,
AsyncImage use Layout with ConstraintsSizeResolver?

@skydoves
Copy link
Owner

Hey @KwonDae, Landscapist uses SizeResolver to request pre-computed image sizes before rendering. The reason for adopting BoxWithConstraints is to limit content sizes and support match-parent functionality. This is achieved by leveraging the properties of SubComposeLayout, which delegates incoming parent constraints, making it easier to implement match-parent features.

On the other hand, Landscapist offers other image libraries, such as Glide and Fresco, but they don't yet provide features similar to SizeResolver. Therefore, I need to find a better way to support all of them. This is important because BoxWithConstraints incurs slightly higher overhead compared to a regular Box.

@KwonDae
Copy link
Contributor Author

KwonDae commented May 21, 2024

Thank you for the answers.
It was very helpful, I got a lot out of it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants