可点击修饰符在Jetpack Compose中不起作用。

huangapple go评论173阅读模式
英文:

Clickable modifier not working in Jetpack Compose

问题

我正在尝试在Modifier上实现一个扩展函数,该函数可以轻松地将点击操作设置为可组合项,以将特定文本复制到剪贴板:

以下是代码:

  1. /**
  2. * @param textCopied 要复制到剪贴板的文本。
  3. * @param clipLabel 用于标识textCopied的标签。可以为null。
  4. *
  5. * Android 13在本地复制文本到剪贴板时会显示一条消息,因此我们不需要用户知道已经发生了复制以避免重复消息。
  6. * 此方法将给定的textCopied复制到剪贴板,并在用户的Android版本低于13时显示一个toast。
  7. * 更多信息请参见:https://developer.android.com/develop/ui/views/touch-and-input/copy-paste#duplicate-notifications
  8. */
  9. fun Context.copyTextToClipboardAndNotify(textCopied: String, clipLabel: String? = null) {
  10. val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
  11. // 设置剪贴板文本。
  12. clipboardManager.setPrimaryClip(ClipData.newPlainText(clipLabel, textCopied))
  13. // 仅在Android 12及更低版本上显示toast。
  14. if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2)
  15. Toast.makeText(this, getString(R.string.text_copied_to_clipboard_S, textCopied), Toast.LENGTH_SHORT).show()
  16. }
  17. /**
  18. * @param textToCopy 点击可组合项时要复制的文本。
  19. *
  20. * 为可组合项设置点击操作,将提供的textToCopy复制到剪贴板。
  21. */
  22. fun Modifier.copyOnClick(textToCopy: String?) = composed {
  23. val context = LocalContext.current
  24. textToCopy?.let {
  25. clickable {
  26. context.copyTextToClipboardAndNotify(it)
  27. }
  28. }
  29. this
  30. }

这是我在视图中使用它的方式:

  1. Column(
  2. modifier = Modifier.copyOnClick(username),
  3. horizontalAlignment = Alignment.CenterHorizontally
  4. ) {
  5. // 列内容在这里
  6. }

然而,这根本不起作用。在调试时,我可以看到调试器在clickable{}断点处停止,但当我点击视图时,它实际上并没有进入函数。

所以,为了尝试它,我将我的视图更改为:

  1. val context = LocalContext.current
  2. Column(
  3. modifier = Modifier.clickable { context.copyTextToClipboardAndNotify(username) },
  4. horizontalAlignment = Alignment.CenterHorizontally
  5. ) {
  6. // 列内容在这里
  7. }

这样就可以了!但显然比我想要实现的方式要不那么简洁。

为什么我的函数不能正常工作?我怀疑这与他们建议在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:

  1. /**
  2. * @param textCopied Text to be copied to the clipboard.
  3. * @param clipLabel Label to identify the textCopied. Can be null.
  4. *
  5. * Android 13 shows a message when text has been copied to the clipboard natively, so we don&#39;t need to user that it has happened to avoid duplicate messages.
  6. * This method copies the given textCopied to the clipboard and shows a toast if the user is on an Android version lower than 13.
  7. * More info on: https://developer.android.com/develop/ui/views/touch-and-input/copy-paste#duplicate-notifications
  8. * */
  9. fun Context.copyTextToClipboardAndNotify(textCopied: String, clipLabel: String? = null) {
  10. val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
  11. // When setting the clipboard text.
  12. clipboardManager.setPrimaryClip(ClipData.newPlainText(clipLabel, textCopied))
  13. // Only show a toast for Android 12 and lower.
  14. if (Build.VERSION.SDK_INT &lt;= Build.VERSION_CODES.S_V2)
  15. Toast.makeText(this, getString(R.string.text_copied_to_clipboard_S, textCopied), Toast.LENGTH_SHORT).show()
  16. }
  17. /**
  18. * @param textToCopy Text to be copied when composable is clicked.
  19. *
  20. * Sets a click action to the composable to copy the provided textToCopy to the clipboard.
  21. */
  22. fun Modifier.copyOnClick(textToCopy: String?) = composed {
  23. val context = LocalContext.current
  24. textToCopy?.let {
  25. clickable {
  26. context.copyTextToClipboardAndNotify(it)
  27. }
  28. }
  29. this
  30. }

And this is how I use it in the view:

  1. Column(
  2. modifier = Modifier.copyOnClick(username),
  3. horizontalAlignment = Alignment.CenterHorizontally
  4. ) {
  5. // Column content here
  6. }

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

  1. val context = LocalContext.current
  2. Column(
  3. modifier = Modifier.clickable { context.copyTextToClipboardAndNotify(username) },
  4. horizontalAlignment = Alignment.CenterHorizontally
  5. ) {
  6. // Column content here
  7. }

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。根据空值检查返回应该解决这个问题。

英文:
  1. fun Modifier.copyOnClick(textToCopy: String?) = composed {
  2. val context = LocalContext.current
  3. textToCopy?.let {
  4. clickable {
  5. context.copyTextToClipboardAndNotify(it)
  6. }
  7. }
  8. this
  9. }

problem is you always return Modifier, never the clickable. Returning based on null check should solve the issue.

  1. fun Modifier.copyOnClick(textToCopy: String?) = composed {
  2. val context = LocalContext.current
  3. textToCopy?.let {
  4. clickable {
  5. context.copyTextToClipboardAndNotify(it)
  6. }
  7. }?:this
  8. }

huangapple
  • 本文由 发表于 2023年8月9日 17:44:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866493.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定