很多 App 现在都会用到一键复制或者一键粘贴的功能,比如『淘宝』,支持一键复制物流单号,也支持直接从剪贴板中读取所复制的淘口令。

一键复制和一键粘贴的操作如何实现呢?

Android 为我们提供了剪贴板框架,允许复制和粘贴不同类型的数据,比如文本、图像、二进制流数据或者其他复杂的数据类型,另外,它还支持复制多条记录,很多输入法都实现了多条记录的剪贴板,功能很强大。

当然,最常用的还是对文本进行操作啦,那就介绍一下复制和粘贴文本的实现方法。

复制实现如下:

fun copyText(text: CharSequence) {
    val cm = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
    cm.setPrimaryClip(ClipData.newPlainText(context.packageName, text))
}

无论是复制还是粘贴,都离不开 ClipboardManager 这个剪贴板管理服务,通过 newPlainText() 静态方法创建 ClipData 对象,再通过 setPrimaryClip() 方法传给 ClipboardManager 即可,newPlainText() 方法接收两个参数,分别是 labeltext,通常情况下我们只需要设置 text 即可,它是我们需要复制的文本,而 label 一般不会与用户打交道,更多是用于开发者的标记。

粘贴实现如下:

fun getText(): CharSequence {
    val cm = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
    cm.primaryClip?.let {
        if (it.itemCount > 0) {
            return it.getItemAt(0).coerceToText(context)
        }
    }
    return ""
}

既然复制是将文字封装成 ClipData 传给 ClipboardManager,那么粘贴则是反过来,也就是从 ClipboardManager 中取出 ClipData 并解析出文字,这里需要注意判空,避免空指针异常或者数组越界,一般情况下我们只会用到剪贴板第一条数据,获取之后调用 coerceToText() 转换成文字,因为剪贴板除了文字外还支持 URI 等类型,这个方法可以帮我们一并处理。

像『淘宝』就是每次 App 回到前台时就获取一次剪贴板,如果是淘口令则执行对应的操作。

这篇文章本来到这里就该结束了,但我突然发现了一个新功能:

剪贴板监听

其实 ClipboardManager 提供了监听剪贴板的方法:

fun addClipChangedListener() {
    val cm = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
    cm.addPrimaryClipChangedListener { 
        val text = getText()
        ...
    }
}

但是回调中并没有返回最新的内容,仍需自行获取。