https://kotlinlang.org logo
Docs
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
compose
  • p

    Piotr Prus

    12/13/2021, 7:03 PM
    Anyone knows any open source app that uses compose and mapView? I know the crane sample app, but I need a sample that uses maps and bottomNavBar or something similar that save states. I have a problem retaining mapview state on fragment recreation.
    j
    3 replies · 2 participants
  • n

    Nat Strangerweather

    12/13/2021, 10:29 PM
    Hi, I'm trying to pass a variable out of my LaunchedEffect so I can use it. I'm not sure how to accomplish that. Any ideas?
    z
    a
    +1
    11 replies · 4 participants
  • m

    Miguel Vargas

    12/14/2021, 12:00 AM
    AndroidViews inside a LazyColumn recompose and recreates the Views as I scroll. I tried using
    remember
    to save the AndroidView as follows but it’s still recreating the Views as I scroll up and down. Is there any way to make it more efficient?
    @Composable
    fun ViewInLazyColumn() {
        LazyColumn {
            items(100) { idx ->
                val context = LocalContext.current
    
                val view = remember { MyView(context, idx.toString()) }
                AndroidView(factory = { view }) } } }
    
    class MyView(context: Context, value: String) : TextView(context) {
        init {
            // View keeps getting recreated
            println("init MyView $value") 
            text = value } }
    a
    5 replies · 2 participants
  • l

    Libor Bicanovsky

    12/14/2021, 12:35 AM
    Fyi, if anyone is using code similar to this:
    condition?.let {
     //some composable
    } ?: //other composable
    In 1.1.0-beta04 this will not work correctly and the second condition will never be evaluated/displayed. It works correctly in previous versions (such as 1.0.5). Just wanted to mention it since it caught us out!
    z
    c
    4 replies · 3 participants
  • m

    mattinger

    12/14/2021, 2:23 AM
    Anyone know if there’s any easy way to get a robolectric test to wait for a coroutine launched by a “rememberCoroutineScope” scope?
    z
    j
    10 replies · 3 participants
  • o

    OG

    12/14/2021, 6:50 AM
    Hello 👋 I'm experimenting a bit with compose navigation and was wondering if I could get some insight on something before I try "reinventing the wheel" or doing hacky workarounds. Will reply in thread with more detail
    j
    l
    +1
    14 replies · 4 participants
  • t

    Tgo1014

    12/14/2021, 8:39 AM
    Is there a way to set the default font family or I’ve to override in all “styles” (body1, h1, etc)?
    f
    s
    +2
    11 replies · 5 participants
  • a

    Ankit Shah

    12/14/2021, 11:18 AM
    Hello everyone, I have a question related to the navigation in jetpack compose, I do have a page with formfields in jetpack compose and filled some data in those. Now once I navigate to other page and if I go back I loose all the form data. I want to preserve the data when I go back. how can I achieve it using navcontroller?
    i
    1 reply · 2 participants
  • b

    Brian G

    12/14/2021, 3:08 PM
    Any word on scroll indicators in Jetpack Compose? I don't see them on the roadmap either. Is Compose never going to have scroll indicators built-in?
    ☝️🏽 2
    z
    a
    4 replies · 3 participants
  • p

    PHondogo

    12/14/2021, 3:25 PM
    Hello! Compose application crashes with
    java.lang.NoSuchMethodError: No static method infiniteRepeatable-9IiC70o$default(Landroidx/compose/animation/core/DurationBasedAnimationSpec;Landroidx/compose/animation/core/RepeatMode;JILjava/lang/Object;)Landroidx/compose/animation/core/InfiniteRepeatableSpec; in class Landroidx/compose/animation/core/AnimationSpecKt; or its super classes (declaration of 'androidx.compose.animation.core.AnimationSpecKt'
    z
    7 replies · 2 participants
  • m

    mattinger

    12/14/2021, 5:07 PM
    So, i’m trying to use the accompanist permissions. The issue i’m running into is that i’m doing my checking when a particular button is clicked. As such, PermissionsRequired isn’t a great solution for me. Instead, i’ve built a composable that’s turned on and off with a flag. I’m not 100% happy with this, but wondering if there’s a better way. See thread for that function
    3 replies · 1 participant
  • b

    Brian Donovan

    12/14/2021, 5:10 PM
    Hi all, I’m trying to make my screen scrollable but having no luck. This is an image of the code and emulator
    1 reply · 1 participant
  • l

    Lucien Guimaraes

    12/14/2021, 6:52 PM
    About AnnotatedString API to have multiple styles for a text, how to achieve it with a string resource? Let's say I have the following one:
    <string name="news_count_title">{{count}} {{text}}</string>
    . I would like
    count
    and
    text
    to have different styles. How to properly achieve it in Compose?
    s
    c
    +1
    8 replies · 4 participants
  • c

    Colton Idle

    12/14/2021, 9:01 PM
    What's the default size for
    Text
    ? I clicked into a Text and I see
    fontSize: TextUnit = TextUnit.Unspecified,
    k
    3 replies · 2 participants
  • c

    Colton Idle

    12/14/2021, 9:13 PM
    I have this Box that stretches/scales on the Y axis. My problem is that the contents within the box are clipped unless I add padding even though I have clip=false.
    Box(
          modifier.fillMaxWidth().graphicsLayer {
            scaleY = 1000f
            clip = false
          },
    Is there a way to prevent this clipping? I thought compose didn't clip by default? Even if it did, I thought clipToBounds() would allow me to pass in "false" but it does not.
    a
    n
    13 replies · 3 participants
  • j

    jeff

    12/14/2021, 10:43 PM
    Hoping someone can help me understand this recomposition behavior:
    class Helper {
      val string = "string"
    }
    
    @Composable
    fun RecompRepro(mutableState: MutableState<String>, helper: Helper) {
      LogCompositions(msg = "Root")
      Column(Modifier.height(100.dp)) {
        Text(mutableState.value)
        CustomComposableText(helper = helper)
      }
    }
    
    @Composable
    fun CustomComposableText(helper: Helper) {
      LogCompositions(msg = "CustomComposableText")
      Text(helper.string)
    }
    if I change the value of mutableState 3 times, "Root" is printed 3 times and "CustomComposableText" is printed 1 time. That is as expected. But if I change
    val string
    to
    var string
    in
    Helper
    , then all of a sudden CustomComposableText is printed 3 times. Why?
    i
    10 replies · 2 participants
  • b

    bbade_

    12/15/2021, 12:20 AM
    Question about MaterialTheme and overriding a color in a segment of code. If i had a layout
    Column
      Button1
      *OddUi*
      Button3
    Lets say i wanted to override
    primary
    and
    onPrimary
    when rendering the OddUi content. What’s the best way of doing this? MaterialTheme’s colors are
    mutableStateOf
    , so do i write
    Button1()
    MaterialTheme.primary = somethingElse
    MaterialTheme.Colors.onPrimary = somethingElse
    OddUi()
    // restore the two colors
    Button2
    This feels odd or would i write
    Button1()
    CompositionLocalProvider(LocalColors provides MaterialTheme.colors.copy(primary = ..., onPrimary = ...) {
       OddUi()
    }
    Button2
    With this though, localColors is internal, so i can’t override it, right? Is there a third option?
    c
    l
    +1
    11 replies · 4 participants
  • c

    Colton Idle

    12/15/2021, 3:05 AM
    I have a bottomSheet that I hide() on an event lambda i.e.
    val successEvent = {
      scope.launch {
        bottomSheetState.hide()
      }
    }
    This works greats except that if the user happens to be touching the bottom sheet while I call hide(), then it won't actually hide. Is there another way to force the sheet to hide if I really need it to hide, or am I out of luck/file a feature request?
    a
    2 replies · 2 participants
  • n

    nilTheDev

    12/15/2021, 6:43 AM
    I am trying to create a sudoku game. All the cells of the sudoku board are
    boxes
    - nested in
    rows
    and
    columns
    - with some border around them. However, in some of the
    boxes
    the border appears to be thicker than others. Anybody knows why this is happening? In the code, the thickness of the border of all the
    boxes
    are same.
    t
    a
    11 replies · 3 participants
  • p

    PHondogo

    12/15/2021, 7:06 AM
    Hello! Have anyone faced with
    java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/compose/animation/core/StartOffset;
    when calling
    InfiniteRepeatableSpec(
                    animation = tween(200, easing = LinearEasing),
                    repeatMode = RepeatMode.Restart,
                    initialStartOffset = StartOffset(0)
                )
    ?
    a
    d
    3 replies · 3 participants
  • j

    jean

    12/15/2021, 9:11 AM
    I had an issue a few month ago with image loaded with coil inside a lazy list https://kotlinlang.slack.com/archives/CJLTWPH7S/p1619166350451300. I just updated my project to use
    "io.coil-kt:coil-compose:1.4.0"
    instead of
    accompanist
    and I’m back at the same problem. Images are not loading when I set them from the
    items
    block of the
    LazyListScope
    block. Do I need to change anything?
    Image(
        painter = rememberImagePainter(url),
        contentDescription = stringResource(id = R.string.description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .width(150.dp)
            .height(267.dp),
    )
    c
    5 replies · 2 participants
  • g

    Guilherme Delgado

    12/15/2021, 10:39 AM
    I’ve a formulary app with a lot of different input types (text, radio, check, signature, etc...) I can zoom in/out and drag the form around. I’ve notice performance issues (lots of lag when zooming and panning) when doing this:
    inputs.forEach {
       TextFieldWrapper(
           id = ...,
           text = ...,
           onTextChanged = { my callback implementation }
       )
       ...
    }
    More in thread.
    z
    8 replies · 2 participants
  • l

    loloof64

    12/15/2021, 10:53 AM
    Hi ! Is it possible to know which item of a LazyColumn has been clicked ? More in 🧵
    e
    a
    +1
    9 replies · 4 participants
  • l

    loloof64

    12/15/2021, 11:02 AM
    Can I get the output of
    println()
    call from an interactive
    @Preview
    in Android Studio ?
    🇳🇴 3
    1 reply · 1 participant
  • h

    Hachemi Hamadi

    12/15/2021, 11:30 AM
    Hello, I am facing weird issue on some devices (Xiaomi mainly). Here is the output of the error stack :
    E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.cardshop.app.compose, PID: 12745
        java.lang.IllegalStateException: measure() may not be called multiple times on the same Measurable
            at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:86)
            at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:71)
            at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1293)
            at androidx.compose.foundation.layout.RowColumnImplKt$rowColumnMeasurePolicy$1.measure-3p2s80s(RowColumnImpl.kt:89)
            at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:51)
            at androidx.compose.foundation.ScrollingLayoutModifier.measure-3p2s80s(Scroll.kt:342)
            at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:39)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:131)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:131)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:131)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:131)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:131)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:131)
            at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:306)
            at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:39)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:131)
            at androidx.compose.foundation.layout.PaddingModifier.measure-3p2s80s(Padding.kt:364)
            at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:39)
            at androidx.compose.foundation.layout.FillModifier.measure-3p2s80s(Size.kt:658)
            at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:39)
            at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$3.invoke(OuterMeasurablePlaceable.kt:100)
            at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$3.invoke(OuterMeasurablePlaceable.kt:99)
            at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:126)
            at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:88)
            at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:76)
            at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:99)
            at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.kt:1302)
            at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release$default(LayoutNode.kt:1298)
            at androidx.compose.ui.node.LayoutNode.onBeforeLayoutChildren(LayoutNode.kt:1080)
            at androidx.compose.ui.node.LayoutNode.layoutChildren$ui_release(LayoutNode.kt:961)
            at androidx.compose.ui.node.LayoutNode.onNodePlaced$ui_release(LayoutNode.kt:954)
            at androidx.compose.ui.node.InnerPlaceable.placeAt-f8xVGno(InnerPlaceable.kt:125)
            at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
            at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
            at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:203)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper$measure$1$1.placeChildren(DelegatingLayoutNodeWrapper.kt:138)
            at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.placeAt-f8xVGno(DelegatingLayoutNodeWrapper.kt:126)
            at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:31)
            at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:370)
    🧵 2
    :thread-please: 2
    l
    f
    5 replies · 3 participants
  • l

    loloof64

    12/15/2021, 12:09 PM
    Reading at navigation documentation (https://developer.android.com/jetpack/compose/navigation#nav-with-args), I've seen that we can navigate with string argument. But is there a way to pass custom argument ? Or must I serialize/deserialize between my custom
    class
    and
    String
    ? Or is even this last very bad practice ?
    l
    c
    +2
    37 replies · 5 participants
  • c

    Colton Idle

    12/15/2021, 3:14 PM
    This might be a dumb question, but what's the easiest way to consume release notes for compose updates. I know I can go to https://developer.android.com/jetpack/androidx/releases/compose-animation for example and then click through each artifact, but is there just like a general "release notes for compose 1.1.0-beta04" that includes all artifacts?
    👀 1
    a
    z
    3 replies · 3 participants
  • t

    trevjones

    12/15/2021, 3:35 PM
    Back in the old days I could drop something like this into my custom test runner onStart
    Espresso.setFailureHandler { error, viewMatcher ->
        val scan = Radiography.scan(viewStateRenderers = DefaultsIncludingPii)
        error.addSuppressed(RuntimeException("\n$scan"))
        error.addSuppressed(RuntimeException(idlingRegistryStatus))
        DefaultFailureHandler(targetContext).handle(error, viewMatcher)
    }
    Is there a good way to do similar with the compose rule + testing apis?
    z
    2 replies · 2 participants
  • j

    Javier

    12/15/2021, 3:44 PM
    Is it possible to change the compositionLocal inside AppBar to avoid adding an alpha to the content?
    ➕ 1
    l
    c
    5 replies · 3 participants
  • b

    Billy Newman

    12/15/2021, 3:54 PM
    Hello all! Is it possible to get attributes, say for instance the background color, of composable that is passed as a parameter? See reply for example.
    k
    a
    +2
    17 replies · 5 participants
Powered by Linen
Title
b

Billy Newman

12/15/2021, 3:54 PM
Hello all! Is it possible to get attributes, say for instance the background color, of composable that is passed as a parameter? See reply for example.
Something like this:
@Composable
fun Content(someComposable: (@Composable () -> Unit)? = null) {
  val background = someComposable?.background()  // This does not work
}
k

Kirill Grouchnikov

12/15/2021, 4:14 PM
There is no such thing. This
someComposable
is not a view / container / component in the traditional sense. It may emit one UI component, it may emit more than one, or it may not emit anything.
b

Billy Newman

12/15/2021, 4:17 PM
Ok makes sense. Ideas on another to achieve what I am after? Looking into a custom scope for that composable. Still not 100% sure how to implement, but something like this:
interface CustomScope {
   
   @Stable
   fun Modifier.background(background: Color): Modifier

}

@Composable
fun Content(someComposable: (@Composable CustomScope.() -> Unit)? = null) {
...
}
a

Adam Powell

12/15/2021, 4:19 PM
what exactly is it that you're after? The compose way is generally to tell your children what to do and expect them to do it, not assemble your children and then query their state after the fact
it's highly unusual for a parent to ask a child about the nature of its background drawing and wanting to do that is a bit of an encapsulation break, like using reflection to inspect the private properties of an object
b

Billy Newman

12/15/2021, 4:43 PM
Sure, specifically I have a common composable for a draggable view. That draggable view has a “drag handle view” at the top. However that common view can also be customized with a header:
@Composable
fun CommonContent(header: (@Composable () -> Unit)? = null) {
  DragHandle()

  header?.invoke()
}
@Composable
fun CustomContent() {

  CommonContent() {
    // custom header
    Column(Modifier.background(Color.Blue)) { ... }
  }
}
I would like for the drag handle view to have the same background color as the custom header. And I don’t really want to duplicate code. IE in this case a drag handle is “common” and should always be present regardless of the custom header.
c

Casey Brooks

12/15/2021, 4:57 PM
Since your custom header is a child of
CommonContent
, you can use CompositionLocals to implicitly pass parameters down through the composition tree https://developer.android.com/jetpack/compose/compositionlocal
➕ 1
c

Chris Sinco [G]

12/15/2021, 5:04 PM
Adding to Casey’s suggestion, using colors from
MaterialTheme
like
MaterialTheme.colors.background
can be useful here because from the code POV you are using a semantic color key, but can use CompositionLocal to override in specific parts in the hierarchy if needed.
You could also consider a color parameter for DragHandle that defaults to something
b

Billy Newman

12/15/2021, 5:11 PM
Sure I can always pass more information in the CommonContent composable…
@Composable
fun CommonContent(
  header: (@Composable () -> Unit)? = null,
  headerColor: Color = Color.White
) {
  DragHandle(headerColor)

  header?.invoke()
}
But where does that end. Passing in every attribute the drag handle would have in common with the header component seems excessive.
Not sure I fully understand how to use CompositionLocals in this case. Not really sure I want to pass parameters “down”
Also @Adam Powell looking at implementations of customs scopes like Row and Column, they end up using:
interface ParentDataModifier : Modifier.Element {
    /**
     * Provides a parentData, given the [parentData] already provided through the modifier's chain.
     */
    fun Density.modifyParentData(parentData: Any?): Any?
}
To allow the child to modify something on the parent right? Seems like exactly what I am trying to do.
c

Chris Sinco [G]

12/15/2021, 5:17 PM
Not really sure I want to pass parameters “down”
Right, this is where CompositionLocals can be useful as it passes things down in the hierarchy, and it works particularly well for color overrides at certain parts of a UI hierarchy
c

Casey Brooks

12/15/2021, 5:20 PM
It would look something like this:
val LocalHeaderColor = compositionLocalOf { Color.Unspecified }

@Composable
fun CommonContent(
  header: (@Composable () -> Unit)? = null,
  headerColor: Color = Color.White
) {
    CompositionLocalProvider(LocalHeaderColor provides headerColor) {
        DragHandle()
        header?.invoke()
    }
}
The content of both
DragHandle
and the
header
lambda can then reference the configured header color with
LocalHeaderColor.current
, without having to pass it explicitly through function parameters
✔️ 1
b

Billy Newman

12/15/2021, 6:32 PM
Casey, thanks for the example, still new to compose. I will give this a go, I greatly appreciate the help!
c

Chris Sinco [G]

12/15/2021, 6:38 PM
+1 great example Casey!
:thank-you: 1
a

Adam Powell

12/15/2021, 6:45 PM
the ParentDataModifiers and scoped modifier factories are less about modifying something on the parent and more about the parent passing down the capability for child elements to annotate the layout nodes they emit in a particular way
View count: 1