Android 系统服务Android知识Android开发经验谈

教你使用剪切板——Android中的复制&粘贴

2017-07-10  本文已影响6979人  MrTrying

最近开发过程中有使用到复制/粘帖功能,也在其中遇到了一些问题,就顺势学习一下复制粘贴相关的知识。

一、前言

Android提供了一个强大的剪切板框架(以至于在复制某些内容粘帖到我的项目中的时候出现的格式问题的BUG)用于复制和粘帖。同时支持简单和复杂的数据类型,简单的文本数据直接存储在剪贴板中,而复杂的数据存储为一个引用,即粘贴应用程序解析为内容提供者(这里涉及到ContentProvider)。

二、框架&使用

框架图

要复制数据,应用程序将ClipData对象放在ClipboardManager全局剪贴板上。它ClipData包含一个或多个ClipData.Item对象和一个 ClipDescription对象。要粘贴数据,应用程序会从中ClipData获取其MIME类型ClipDescription,并从ClipData.Item或从内容提供者 获取数据ClipData.Item

可以看出Android剪贴板框架主要涉及到ClipboardManagerClipDataClipData.ItemClipDescription这四个类,下面详细说明

  1. ClipboardManager是系统全局的剪贴板对象,通过context.getSystemService(CLIPBOARD_SERVICE)获取。
  2. ClipData,即clip(剪切)对象,在系统剪贴板里只存在一个,当另一个clip对象进来时,前一个clip对象会消失。
  3. ClipData.Item,即 data item,它包含了文本、Uri或者Intent数据,一个clip对象可以包含一个或多个Item对象。通过 addItem(ClipData.Item item)可以实现往clip对象中添加Item
    • 文本:文本是直接放在 clip 对象中,然后放在剪贴板里;粘贴这个字符串的时候直接从剪贴板拿到这个对象,把字符串放入你的应用存储中。
    • Uri:对于复杂数据的剪贴拷贝并不是直接将数据放入内存,而是通过 Uri 来实现,毕竟 Uri 的中文名叫:统一资源标识符。通过 Uri 能定位手机上所有资源,这当然能实现拷贝了,只不过需要做一些额外的处理工作。(对于 Uri 不是很理解,如有误,望指正~)
    • Intent:复制的时候 Intent 会被直接放入 clip 对象,这相当于拷贝了一个快捷方式。
  4. ClipDescription ,即 clip metadata,它包含了 ClipData 对象的 metadata 信息。可以通过 getMimeType(int index) 获取(一般 index = 0,有兴趣的可以去看下 ClipData 的源码)。MimeType 一般有以下四种类型:
    // 对应 ClipData.newHtmlText(label, text, htmlText) 的 MimeType
    public static final String MIMETYPE_TEXT_HTML = "text/html";
    // 对应 ClipData.newIntent(label, intent) 的 MimeType
    public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
    // 对应 ClipData newPlainText(label, text) 的 MimeType
    public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
    // 对应 ClipData newPlainText(label, text) 的 MimeType
    public static final String MIMETYPE_TEXT_URILIST = "text/uri-list";

接下来看看简单的使用,以文本操作为例

    public void putTextIntoClip(Context context){
        ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
        //创建ClipData对象
        ClipData clipData = ClipData.newPlainText("simple text copy", "Clipboard test.");
        //添加ClipData对象到剪切板中
        clipboardManager.setPrimaryClip(clipData);
    }

创建ClipData的方法还有另外四个:

    //创建一个包含 htmlText 的 ClipData
    //一般在浏览器中对网页进行拷贝的时候会调用此方法,其中 htmlText 是包含 HTML 标签的字符串
    public static ClipData newHtmlText(CharSequence label, CharSequence text, String htmlText)
    //创建一个包含 Intent 的 ClipData
    public static  ClipData newIntent(CharSequence label, Intent intent)
    //创建一个包含 Uri 的 ClipData,MimeType 会根据 Uri 进行修改
    public static  ClipData newUri(ContentResolver resolver, CharSequence label, Uri uri)
    //与 newUri 相对应,但是并不会根据 Uri 修改 MimeType
    public static  ClipData newRawUri(CharSequence label, Uri uri)

从剪切板中获取数据,同样以文本操作为例

    public void getTextFromClip(Context context){
        ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
        //判断剪切版时候有内容
        if(!clipboardManager.hasPrimaryClip())
            return;
        ClipData clipData = clipboardManager.getPrimaryClip();
        //获取 ClipDescription
        ClipDescription clipDescription = clipboardManager.getPrimaryClipDescription();
        //获取 lable
        String lable = clipDescription.getLabel().toString();
        //获取 text
        String text = clipData.getItemAt(0).getText().toString();
    }

顺带说一下之前遇到的问题,我boss直接从网易新闻复制了内容,粘帖到我们自己的app中,之后文本的样式都不对,这是因为复制的内容是包含HTML标签的字符串,导致内容显示有问题,String text = clipData.getItemAt(0).coerceToText(context).toString();最后使用coerceToText()将剪贴板数据强制转换为文本解决问题。

三、官方建议

Designing Effective Copy/Paste Functionality
To design effective copy and paste functionality for your application, remember these points:

为设计有效的复制和粘贴功能,请记住以下几点:

参考资料:
API Guides: Copy and Paste:
https://developer.android.com/guide/topics/text/copy-paste.html#Provider

PS:文章不是很全面,翻译的也不是很好,请见谅

上一篇下一篇

猜你喜欢

热点阅读