Jetpack Compose has a ClipboardManager, allowing us to get or set the value on the clipboard. I notice however that getText()
does not return a State
, or any observable value.
@Composable fun ClipboardContents() {
val cb = LocalClipboardManager.current
Text(cb.getText())
}
How can I make sure that my Composable
function responds to changes in the Clipboard?
You need to create State<AnnotatedString>
that will be updated each time ClipboardManager
clip has changed. This doesn't come out of the box you have to implement a functions that will observe for primary clip changes, then utilize that to create a state object that will trigger the recomposition.
@Composable
fun rememberClipboardText(): State<AnnotatedString?> {
val clipboardManager = LocalClipboardManager.current
val text = remember { mutableStateOf(clipboardManager.getText()) }
onClipDataChanged {
text.value = clipboardManager.getText()
}
return text
}
@SuppressLint("ComposableNaming")
@Composable
fun onClipDataChanged(onPrimaryClipChanged: ClipData?.() -> Unit) {
val clipboardManager =
LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val callback = remember {
ClipboardManager.OnPrimaryClipChangedListener {
onPrimaryClipChanged(clipboardManager.primaryClip)
}
}
DisposableEffect(clipboardManager) {
clipboardManager.addPrimaryClipChangedListener(callback)
onDispose {
clipboardManager.removePrimaryClipChangedListener(callback)
}
}
}
then the usage will be something like this:
@Composable
fun ClipboardContents() {
val clipBoardText by rememberClipboardText()
clipBoardText?.let { Text(it) }
}