androidkotlinandroid-contextandroid-jetpack-composekotlin-multiplatform

Copying to clipboard on Kotlin Multiplatform


I couldn't find anyone doing this so far so I'll try and properly state the issues I am facing.

I have a compose-ui module in the shared module of my KMP app. The compose-ui has a commonMain directory where all of the compose UI resides (screens that are shared between the desktop and the android app). Now the issue is, to copy the text to the clipboard (on Android) you need Context, which cannot be accessed in the commonMain, okay, no issues, I'll have to expect/ actual function @Composable copyToClipboard(text: string), but using the IconButton and its OnClick : () -> Unit which results in an error that @Composable can only be called from composable context. I am not sure how to go about this, I somehow need context to access the clipboard manager but I cannot access it nor pass it.


Solution

  • You can use LocalClipboard, you'll have to build an extension to convert text to ClipEntry. In simple case, when you don't need to keep formatting, it can look like this:

    commonMain:

    expect fun String.toClipEntry(): ClipEntry
    

    androidMain

    actual fun String.toClipEntry() =
        android.content.ClipData.newPlainText(this, this).toClipEntry()
    

    iosMain

    actual fun String.toClipEntry() =
        ClipEntry.withPlainText(this)
    

    jvmMain

    actual fun String.toClipEntry() =
        ClipEntry(java.awt.datatransfer.StringSelection(this))
    

    Usage:

    val clipboard = LocalClipboard.current
    Button(
        onClick = { clipboard.setClipEntry("Text to be copied to clipboard".toClipEntry()) }
    )