aoao
aoao

Reputation: 11

Jetpack Compose:@Composable invocations can only happen from the context of a @Composable function

(https://i.sstatic.net/EFnPS.png)
Source Code:

@Composable
fun Greeting(modifier: Modifier = Modifier) {
    LazyHorizontalGrid(
        rows = GridCells.Fixed(2)
    ) {

        for (item in listOf("a", "b", "c", "d", "e")) {
            Text(text = item)
        }
    }
}

}

Build Output:

@Composable invocations can only happen from the context of a @Composable function

Why cannot use Text() in LazyHorizontalGrid()?

how can i fix this ?

Upvotes: 0

Views: 221

Answers (1)

Dmitri
Dmitri

Reputation: 2982

You need to use the "items" dsl on LazyGridScope:

import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.foundation.lazy.grid.items

@Composable
    fun Greeting(modifier: Modifier = Modifier) {
        LazyHorizontalGrid(
            rows = GridCells.Fixed(2)
        ) {
    
            val elements = listOf("a", "b", "c", "d", "e")
            items(elements){ item ->
                Text(text = item)
            }
        }
    }

If curious to see more, the implementation is here: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridDsl.kt?q=file:androidx%2Fcompose%2Ffoundation%2Flazy%2Fgrid%2FLazyGridDsl.kt%20class:androidx.compose.foundation.lazy.grid.LazyGridScope

and the code is:

/**
 * Adds an array of items.
 *
 * @param items the data array
 * @param key a factory of stable and unique keys representing the item. Using the same key
 * for multiple items in the grid is not allowed. Type of the key should be saveable
 * via Bundle on Android. If null is passed the position in the grid will represent the key.
 * When you specify the key the scroll position will be maintained based on the key, which
 * means if you add/remove items before the current visible item the item with the given key
 * will be kept as the first visible one.
 * @param span define custom spans for the items. Default is 1x1. It is good practice to leave
 * it `null` when this matches the intended behavior, as providing a custom implementation
 * impacts performance
 * @param contentType a factory of the content types for the item. The item compositions of
 * the same type could be reused more efficiently. Note that null is a valid type and items of such
 * type will be considered compatible.
 * @param itemContent the content displayed by a single item
 */
inline fun <T> LazyGridScope.items(
    items: Array<T>,
    noinline key: ((item: T) -> Any)? = null,
    noinline span: (LazyGridItemSpanScope.(item: T) -> GridItemSpan)? = null,
    noinline contentType: (item: T) -> Any? = { null },
    crossinline itemContent: @Composable LazyGridItemScope.(item: T) -> Unit
) = items(
    count = items.size,
    key = if (key != null) { index: Int -> key(items[index]) } else null,
    span = if (span != null) { { span(items[it]) } } else null,
    contentType = { index: Int -> contentType(items[index]) }
) {
    itemContent(items[it])
}

Upvotes: 1

Related Questions