英文:
Clickable modifier not working in Jetpack Compose
问题
我正在尝试在Modifier上实现一个扩展函数,该函数可以轻松地将点击操作设置为可组合项,以将特定文本复制到剪贴板:
以下是代码:
/**
* @param textCopied 要复制到剪贴板的文本。
* @param clipLabel 用于标识textCopied的标签。可以为null。
*
* Android 13在本地复制文本到剪贴板时会显示一条消息,因此我们不需要用户知道已经发生了复制以避免重复消息。
* 此方法将给定的textCopied复制到剪贴板,并在用户的Android版本低于13时显示一个toast。
* 更多信息请参见:https://developer.android.com/develop/ui/views/touch-and-input/copy-paste#duplicate-notifications
*/
fun Context.copyTextToClipboardAndNotify(textCopied: String, clipLabel: String? = null) {
val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
// 设置剪贴板文本。
clipboardManager.setPrimaryClip(ClipData.newPlainText(clipLabel, textCopied))
// 仅在Android 12及更低版本上显示toast。
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2)
Toast.makeText(this, getString(R.string.text_copied_to_clipboard_S, textCopied), Toast.LENGTH_SHORT).show()
}
/**
* @param textToCopy 点击可组合项时要复制的文本。
*
* 为可组合项设置点击操作,将提供的textToCopy复制到剪贴板。
*/
fun Modifier.copyOnClick(textToCopy: String?) = composed {
val context = LocalContext.current
textToCopy?.let {
clickable {
context.copyTextToClipboardAndNotify(it)
}
}
this
}
这是我在视图中使用它的方式:
Column(
modifier = Modifier.copyOnClick(username),
horizontalAlignment = Alignment.CenterHorizontally
) {
// 列内容在这里
}
然而,这根本不起作用。在调试时,我可以看到调试器在clickable{}
断点处停止,但当我点击视图时,它实际上并没有进入函数。
所以,为了尝试它,我将我的视图更改为:
val context = LocalContext.current
Column(
modifier = Modifier.clickable { context.copyTextToClipboardAndNotify(username) },
horizontalAlignment = Alignment.CenterHorizontally
) {
// 列内容在这里
}
这样就可以了!但显然比我想要实现的方式要不那么简洁。
为什么我的函数不能正常工作?我怀疑这与他们建议在Modifier工厂中使用的composed
函数有关。我不确定它具体做了什么,但似乎搞乱了事情。但我需要它来访问上下文。
英文:
I am trying to implement an extension function on Modifier that would easily allow me to set a click action to a composable that would copy a specific text to the clipboard:
Here it is:
/**
* @param textCopied Text to be copied to the clipboard.
* @param clipLabel Label to identify the textCopied. Can be null.
*
* Android 13 shows a message when text has been copied to the clipboard natively, so we don't need to user that it has happened to avoid duplicate messages.
* This method copies the given textCopied to the clipboard and shows a toast if the user is on an Android version lower than 13.
* More info on: https://developer.android.com/develop/ui/views/touch-and-input/copy-paste#duplicate-notifications
* */
fun Context.copyTextToClipboardAndNotify(textCopied: String, clipLabel: String? = null) {
val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
// When setting the clipboard text.
clipboardManager.setPrimaryClip(ClipData.newPlainText(clipLabel, textCopied))
// Only show a toast for Android 12 and lower.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2)
Toast.makeText(this, getString(R.string.text_copied_to_clipboard_S, textCopied), Toast.LENGTH_SHORT).show()
}
/**
* @param textToCopy Text to be copied when composable is clicked.
*
* Sets a click action to the composable to copy the provided textToCopy to the clipboard.
*/
fun Modifier.copyOnClick(textToCopy: String?) = composed {
val context = LocalContext.current
textToCopy?.let {
clickable {
context.copyTextToClipboardAndNotify(it)
}
}
this
}
And this is how I use it in the view:
Column(
modifier = Modifier.copyOnClick(username),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Column content here
}
This is not working at all though. When debugging, I can see that the debugger stops at the clickable{}
breakpoint but never really enters the function when I click the view.
So, to try it out, I changed my view to
val context = LocalContext.current
Column(
modifier = Modifier.clickable { context.copyTextToClipboardAndNotify(username) },
horizontalAlignment = Alignment.CenterHorizontally
) {
// Column content here
}
And this worked! But it's obviously way less clean than what I want to achieve.
Why is my function not working properly? I suspect it's something with this composed
function that they recommend using with Modifiers factories. I don't know exactly what it's doing, but seems to be messing things up. But I need it to access the context.
答案1
得分: 1
fun Modifier.copyOnClick(textToCopy: String?) = composed {
val context = LocalContext.current
textToCopy?.let {
clickable {
context.copyTextToClipboardAndNotify(it)
}
} ?: this
}
问题是你总是返回 Modifier,而不是 clickable。根据空值检查返回应该解决这个问题。
英文:
fun Modifier.copyOnClick(textToCopy: String?) = composed {
val context = LocalContext.current
textToCopy?.let {
clickable {
context.copyTextToClipboardAndNotify(it)
}
}
this
}
problem is you always return Modifier, never the clickable. Returning based on null check should solve the issue.
fun Modifier.copyOnClick(textToCopy: String?) = composed {
val context = LocalContext.current
textToCopy?.let {
clickable {
context.copyTextToClipboardAndNotify(it)
}
}?:this
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论