https://kotlinlang.org logo
Join Slack
Powered by
# compose
  • s

    Soumen pal

    09/11/2025, 12:22 PM
    Hi, I am trying to create some UI in compose like this the closest I have reached is the second image does anyone know how can I create the shape properly (I am unable to create it) and here is the releavent code ``````
    🧵 3
    j
    d
    • 3
    • 7
  • t

    Taha

    09/11/2025, 2:16 PM
    is there a way to pass a list of Serializables as an argument in compose multiplatform navigation?
    • 1
    • 1
  • j

    Janne Mareike Koschinski

    09/11/2025, 3:03 PM
    How do I build a custom list that implements the WCAG composite component keyboard navigation patterns? Specifically, one tab enters the list, one tab exists the list, arrow keys move focus within of the list. As an example for that'd look like, consider the room list of Slack or Teams, or listboxes in Win32/Qt/HTML5. Requirements: • All list items are focusable (e.g., via 2D focus movement or screenreaders) • The list acts as one item for the tab navigation, when tab enters the list the selected item is considered focused for screenreaders • I need to be able to use a custom key event handler to move focus within of the list (up/down one item, up/down a page of items, to the start of the list, to the end of the list). We're building a chat app, and the room list needs to follow these guidelines https://www.w3.org/WAI/ARIA/apg/patterns/listbox/ in our compose desktop and compose web clients: > A primary keyboard navigation convention common across all platforms is that the tab and shift + tab keys move focus from one UI component to another while other keys, primarily the arrow keys, move focus inside of components that include multiple focusable elements. The path that the focus follows when pressing the tab key is known as the tab sequence or tab ring. For that I was planning on using the roving tab index pattern https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex Things I've tried: 1. Setting focusProperties { next = ..., previous = ... }. But that requires me to know the UI layout of my app ahead of time, and it's modular so that enterprise clients can customize it, some of which add their own UI widgets before/after the room list. 2. Intercepting key presses. Doesn't really work, as it's the tab key press on the last UI element before my list that I'd need to intercept, with the same issues as #1 3. Adding focusRequesters to all items, storing those in a list, setting all except for one item as not focusable and updating the focusable state and using requestFocus to move the focus position. But then the focus flickers for a moment, the other items are not visible as focusable to screen readers, and focus movement via screen readers doesn't work as expected anymore 4. I've also tried intercepting the onFocusEvent event, to immediately move the focus to the selected list item when my list is selected, but that doesn't work reliably and still doesn't allow me to move the focus back out of the list again. I've got a simple demo app for how this behaviour should work here: https://public.s3.kuschku.de/demo.html and a simple demo struggling to implement this behaviour in compose here: https://github.com/justjanne/compose-list-navigation/ (I've previously asked this question in #C01D6HTPATV here, but was told I might get more answers here)
    šŸ‘€ 1
  • a

    Adam Hill

    09/11/2025, 9:46 PM
    Compose MP Resources Question • Drawables āœ… • Strings āœ… • Fonts āœ… • Files (for use in coil)āŒ I have set:
    Copy code
    compose.resources {
        publicResClass = true
        generateResClass = always
    }
    IntelliJ Project Explorer shows styled icons for all of them except files. Custom fonts went smoothly, I expected Files to be no different. What am I missing?? Thanks.
    w
    • 2
    • 4
  • t

    Thomas

    09/12/2025, 3:32 AM
    What is the best solution for Figma design to Compose code generation? Looks like ever since Relay plugin died, everything else just went down hill.
    s
    a
    • 3
    • 4
  • m

    Mark

    09/12/2025, 8:24 AM
    I have a
    FlowRow
    that shows a bunch of tags (Chips). I was expecting this to be typically less than a hundred items, but I notice some users have over 500, and this causes major performance issues. How do you deal with `FlowRow`s with too many items?
    s
    s
    +2
    • 5
    • 13
  • j

    Jonathan

    09/12/2025, 12:56 PM
    Has anyone handled navigating to a login route when the user isn’t authenticated using
    NavHost
    in a Compose Multiplatform app? My concern is the Home screen (startDestination) may be visible until the preferences are read (using DataStore) and it’s determined the app should navigate to the Login route. In Android, this we straightforward to achieve by holding the splash screen until we’ve loaded initial state. I’m struggling to find an effective way of achieving this that works for both Android and iOS. Not sure if this is the best channel for this question. If not, please point out the best one for this question.
    s
    • 2
    • 7
  • m

    Michael Paus

    09/12/2025, 2:24 PM
    I am wondering how to deal with
    pointerInput
    correctly in common code. I want to detect a right mouse click if the device is operated with a mouse. However, when I use the button property of the event, then I get a build time error for Android. Why? IntelliJ does not complain when I use this in common code.
    Copy code
    if (event.button?.isSecondary ?: false) {...}
    
    On Android:
    Unresolved reference 'isSecondary'.
    Unresolved reference 'button'.
    The documentation says ā€œSpecifies the pointer button state of which was changed. It has value only when event’s type is PointerEventType.Press or PointerEventType.Release and when button is applicable (only for Mouse and Stylus events).ā€ This tells me that
    button
    will just be
    null
    in case it is not applicable. I tried this with Compose 1.9.0-rc02 and Kotlin 2.2.20 on a Mac.
    e
    • 2
    • 5
  • j

    Joe

    09/12/2025, 9:03 PM
    Hello! I'm new to Compose Multiplatform but have experience in Compose for Android only. Can you explain how I should choose between the
    org.jetbrains.compose.ui.tooling.preview.Preview
    and the
    androidx.compose.ui.tooling.preview.Preview
    annotations when I work on the multiplatform composables and want to have previews for them?
    v
    • 2
    • 1
  • m

    min

    09/13/2025, 9:55 AM
    Is the following correct? 1.
    @Composable
    functions schedule changes to the slot table via a
    Composer
    2. The
    Composer
    records the scheduled changes in a list and hands it over to an
    Applier
    3. The
    Applier
    executes the scheduled changes and alters the slot table and the actual node tree Edit: If the
    Composer
    knows that we’re already in the middle of
    inserting
    new nodes, it directly alters the slot table? What does the
    Applier
    do in that case? Wait for that to be done so it can start altering the actual node tree?
    s
    • 2
    • 3
  • n

    Nathan Fallet

    09/14/2025, 12:39 AM
    We’re building a component library with Compose Multiplateform and Storytale. Really happy to finally migrate to Compose Multiplateform for our app! (While we already have our backend 100% Kotlin with Ktor) Feel free to give a feedback šŸ˜„ https://github.com/guimauvedigital/controlresell-ui
    c
    a
    • 3
    • 3
  • m

    min

    09/14/2025, 5:59 AM
    Why should each
    Applier
    only work either bottom up or top down but never both?
    j
    • 2
    • 19
  • d

    Didier Villevalois

    09/14/2025, 1:35 PM
    Hey everyone. M3 Expressive update for NavigationDrawer says to use "expanded navigation rail" instead of navigation drawer. So I am trying to use
    ModalWideNavigationRail
    in place of a
    ModalNavigationDrawer
    . However, I fail to align my
    TopAppBar
    navigation icon, to the one of the
    ModalWideNavigationRail
    . The latter takes a nullable
    header
    , but despite I pass
    null
    it allocates some space for it (see attached video). If I try to put something in the header, then I get big padding above my header content. However, when you look at the pictures of the M3 Expressive update for NavigationRail, there isn't such a padding above the header. Does anyone have a hint on what I am doing wrong? Or is this a bug?
    ModalWideNavigationRail-bogus-header.mp4
    • 1
    • 1
  • g

    ghosalmartin

    09/15/2025, 6:58 AM
    Can someone explain why the
    HorizontalViewPager
    on the last page of the
    VerticalPager
    doesn’t scroll and if theres anyway to fix it please? It works on all the other pages
    Copy code
    @Preview
    @Composable
    fun broken() {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(LocalContext.current)
        val metricsHeight = (metrics.bounds.height() / LocalDensity.current.density)
        val minHeight = (metricsHeight * .8f).dp
        val items = listOf(1,2,3)
        val pager = rememberPagerState { items.size }
        VerticalPager(state = pager, modifier = Modifier.fillMaxSize(), pageSize = PageSize.Fixed(minHeight)) { index ->
            Column(modifier = Modifier) {
                Text("vertical $index")
    
                val horizontalPagerState = rememberPagerState { items.size }
                HorizontalPager(horizontalPagerState, modifier = Modifier.fillMaxSize()) {
                    Text("index $it", modifier = Modifier.fillMaxSize())
                }
            }
        }
    }
    h
    • 2
    • 5
  • m

    min

    09/15/2025, 12:01 PM
    Are client libraries of Compose expected to declare their own implementors of
    Composition
    if necessary? Or is
    CompositionImpl
    the only class that matters?
    z
    • 2
    • 7
  • m

    min

    09/15/2025, 12:13 PM
    Copy code
    private fun ensureCompositionCreated() {
        if (composition == null) {
            try {
                creatingComposition = true
                composition = setContent(resolveParentCompositionContext()) {
                    Content()
                }
            } finally {
                creatingComposition = false
            }
        }
    }
    What’s going on in this method from the
    AbstractComposeView
    class?
    Copy code
    private var creatingComposition = false
    private fun checkAddView() {
        if (!creatingComposition) {
            throw UnsupportedOperationException(
                "Cannot add views to " +
                    "${javaClass.simpleName}; only Compose content is supported"
            )
        }
    }
    The class has these members also, and a bunch of methods (e.g.
    addView
    ) that guard their bodies with a call to
    checkAddView
    at the start:
    Copy code
    override fun addView(child: View?) {
        checkAddView()
        super.addView(child)
    }
    Does this mean that…
    Copy code
    composition = setContent(resolveParentCompositionContext()) {
                    Content()
                }
    …there might be parallel threads that also have concurrent access to the receiver (
    AbstractComposeView
    ) and they’re only allowed to call methods such as
    addView
    while the assignment above is running? What happens if: 1. Thread A calls
    ensureCompositionCreated
    on an
    AbstractComposeView
    2. While the assignment is running, thread B also calls the same method on the same instance 3. One thread finishes first and sets
    creatingComposition = false
    while the other is still running 4. Thread C calls
    addView
    which in turn first calls
    checkAddView
    on the same instance of
    AbstractComposeView
    Wouldn’t that result in the
    creatingComposition
    property incorrectly being set to
    false
    even though there’s a creation process running (namely in the slower thread)? Why should the methods guarded by
    checkAddView
    only be called a) concurrently b) while a composition is being created in parallel anyway?
    🧵 3
    z
    • 2
    • 6
  • c

    Carl Zeitler

    09/15/2025, 2:42 PM
    Cheers. I’m having issues with the newly introduced
    onFirstVisible
    modifier and hoping to get some input. When displaying `Row`s with
    horizontalScroll
    within a
    Column
    with
    verticalScroll
    , vertical scrolls are never considered for triggering the
    onFirstVisble
    callbacks. Horizontal scrolling still invokes the callbacks when applicable. This only happens if a
    Row
    is initially considered to be in the viewport (e.g. the
    Row
    is the first item in the
    Column
    ), otherwise, both scrolling directions work properly with
    onFirstVisible
    . Unfortunately I’ve tried to isolate this behavior in a demo project but wasn’t able to. Therefore I’m asking if anyone has an idea of what the underlying issue could be.
    a
    • 2
    • 6
  • j

    Jonathan

    09/15/2025, 3:46 PM
    Has anyone written a ViewModel unit testing using a
    SavedStateHandle
    in a Compose Multiplatform app? I’m currently trying to figure out away of saving a ā€œrouteā€ instance inside of the
    SavedStateHandle
    I pass to my tested ViewModel but I’m not finding an API to do so. Is this only something possible to achieve using mocking?
  • k

    Kacper

    09/15/2025, 3:54 PM
    LazyColumns verticalArrangement Hi guys, I have a problem with LazyColumns Arrangement.spacedBy 😜. After targeting android 16 there is a need to handle insets. The documentation states to use Spacers for LazyColumns. So I did
    Copy code
    LazyColumn(
        verticalArrangement = Arrangement.spacedBy(10.dp),
    ) {
        item {
            Spacer(modifier = Modifier.windowInsetsTopHeight(WindowInsets.statusBars))
        }
        // some content
        item {
            Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
        }
    }
    But this does not go well together. Now I will have additional spacings at the top and bottom even if insets are consumed by the parent (the lazy column will apply padding between items even if the item is empty). And here is my question, do anyone know how to handle such a scenario? I just want the first and last item to ignore this additional spacing provided by the spacedBy.
    c
    • 2
    • 1
  • m

    Mark

    09/15/2025, 4:28 PM
    When collecting a
    SharedFlow
    (application level coroutine scope with replay = 1) in compose using
    collectAsStateWithLifecycle
    (initialValue = null), I notice that on screen rotation the first value is
    null
    , but shouldn’t it be
    sharedFlow.replayCache.firstOrNull()
    ? The reason I ask, is because scroll position is being lost on rotation, but when I use ``replayCache.firstOrNull()`` as the
    initialValue
    everything works as expected.
    c
    w
    • 3
    • 4
  • p

    phteven

    09/15/2025, 5:16 PM
    Anyone knows a trick to make all CircularProgressIndicator rotate at the same position (sync their movement) even if they are rendered at different times.
    y
    t
    • 3
    • 4
  • p

    Paolo Pasianot

    09/16/2025, 8:37 AM
    Good morning coders, have you ever tried making a page turn animation in Compose? Do you know if there's a library for it? Do you have any tips for doing so? Thanks in advance.
    f
    • 2
    • 2
  • m

    Mark

    09/16/2025, 12:01 PM
    After seeing this post from @marcinmoskala I guess I’ve been making this mistake (not accessing a state via a lambda) all over the place. It seems extremely hard to not make this mistake in fact, because it’s not obvious. Any thoughts? https://x.com/marcinmoskala/status/1967861087576985999/photo/1
    šŸ‘€ 1
    r
    f
    m
    • 4
    • 4
  • m

    Muthu

    09/16/2025, 12:48 PM
    Hi everyone, I am trying to draw this box without using a Replacement span. Is it possible to draw?
    s
    • 2
    • 1
  • c

    Colton Idle

    09/16/2025, 6:29 PM
    I have essentially
    Button { Text(someText) }
    Do I need to do anything in compose to make this accessible? Or by virtue of it being a button that contains a text, it should work correctly? I can't test with talkback at the moment, so I'm just trying to see if adding a contentDescription via semantics modifier is needed in this case?
    e
    z
    • 3
    • 4
  • m

    min

    09/17/2025, 11:58 AM
    Copy code
    fun ComponentActivity.mySetContent(
        parent: CompositionContext? = null,
        content: @Composable () -> Unit,
    ) {
        val existingView = this.window.decorView
            .findViewById<ViewGroup>(android.R.id.content)
            .getChildAt(0) as? ComposeView
        val compositionDest = (existingView ?: ComposeView(this)).also { view ->
            view.setParentCompositionContext(parent)
            view.setContent(content)
        }
        if (existingView != compositionDest) {
            this.setContentView(compositionDest, ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            ))
            this.window.decorView.also { decorView ->
                if (decorView.findViewTreeLifecycleOwner() == null) {
                    decorView.setViewTreeLifecycleOwner(this)
                }
                if (decorView.findViewTreeViewModelStoreOwner() == null) {
                    decorView.setViewTreeViewModelStoreOwner(this)
                }
                if (decorView.findViewTreeSavedStateRegistryOwner() == null) {
                    decorView.setViewTreeSavedStateRegistryOwner(this)
                }
            }
        }
    }
    I’m reimplementing parts of Jetpack Compose to get a better idea of how it works. My understanding is that
    existingView
    is only not
    null
    if
    mySetContent
    has already been called on the current
    ComponentActivity
    object; that the
    ComposeView
    created in the assignment to
    compositionDest
    gets registered in the
    if
    body via the call to
    this.setContentView
    the first time the method is called; and that it’s this
    ComposeView
    object that every subsequent call to the method on the same instance gets access to via
    existingView
    . Am I correct, and if so, there should be nothing wrong with swapping out
    ComposeView
    for
    MyComposeView
    (my implementation) here, right?
    m
    z
    • 3
    • 7
  • l

    Lukasz Kalnik

    09/17/2025, 3:16 PM
    I have a
    BottomSheetScaffold
    with the following `scaffoldState`:
    Copy code
    val scaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = rememberStandardBottomSheetState(
            initialValue = Hidden,
            skipHiddenState = false,
            confirmValueChange = { newValue ->
                println("new value: $newValue")
                if (newValue == Hidden) viewModel.onCodeBottomSheetClosed()
                true
            }
        )
    )
    However the behavior of the state in
    confirmValueChange
    is quite weird (see 🧵).
    c
    • 2
    • 13
  • m

    min

    09/18/2025, 6:56 AM
    Why does
    GlobalSnapshotManager
    (in
    androidx.compose.ui.platform
    ) start a coroutine on
    AndroidUiDispatcher.Main
    ?
    • 1
    • 1
  • r

    ribesg

    09/18/2025, 3:37 PM
    How do we use Material 3 Expressive features with Compose Multiplatform 1.9.0 release? The release notes state:
    Copy code
    If the latest Material3 features are needed, please include it this way:
    implementation("org.jetbrains.compose.material3:material3:1.9.0-beta06")
    I don't know what "the latest Material3 features" is supposed to mean, but all Material 3 Expressive APIs are internal in that version
    i
    • 2
    • 2
  • s

    Sean Proctor

    09/18/2025, 9:02 PM
    Has anyone managed to use
    NavigationSuiteScaffoldLayout
    for any complicated use case? The source teases a demo:
    Copy code
    An usage example of using a custom modal wide rail can be found at androidx.compose.material3.demos.NavigationSuiteScaffoldCustomConfigDemo.
    I'm guessing that got renamed to ...Sample and the modal nav rail was removed.