博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 剪贴板详解
阅读量:6681 次
发布时间:2019-06-25

本文共 9770 字,大约阅读时间需要 32 分钟。

转自:

Android提供了一个强大的剪贴板框架,用于复制和粘贴。它支持文本、二进制数据流或其它复杂的数据。
Android 剪贴板框架如图:
Android 剪贴板详解
从图中可以看出,Android 剪贴板框架主要涉及到ClipboardManager,ClipData,ClipData.item,ClipDescription四个类。
这四个类的简介如下:
1.ClipboardManager是系统全局的剪切板对象,通过context.getSystemService(CLIPBOARD_SERVICE)获得。
2.ClipData,即clip对象,在系统剪切板中只能存在一个,当另一个clip对象进来时,前一个自动销毁。
3.ClipData.item,即data item,它可以包含文本,Uri,或intent数据,一个clip对象可以包括一个或多个item对象。通过addItem(ClipData.Item item)可以实现在clip对象中添加item。

文本:直接放在clip对象中,然后放在剪切板里,粘贴文本时直接从剪切板里拿到clip对象,把字符串 放入应用存储中。

Uri:对于复杂数据的剪贴拷贝并不是直接将数据放入内存,而是通过uri来实现,通过uri定位手机上的 资源,从而实现拷贝。
intent:复制的时候intent后被直接放入clip对象中,相当于拷贝了一个快捷方式。
4.ClipDescription:即clip metadata,它包括了ClipData对象的metadata信息。可以通过getMimeType(int index)获取,一般index=0.MimeType一般有以下四种类型:

// 对应 ClipData newPlainText(label, text) 的 MimeTypepublic static final String MIMETYPE_TEXT_PLAIN = "text/plain";// 对应 ClipData.newHtmlText(label, text, htmlText) 的 MimeTypepublic static final String MIMETYPE_TEXT_HTML = "text/html";// 对应 ClipData.newUri(cr, label, uri) 的 MimeTypepublic static final String MIMETYPE_TEXT_URILIST = "text/uri-list";// 对应 ClipData.newIntent(label, intent) 的 MimeTypepublic static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";

但MIMETYPE_TEXT_URILIST有点特殊,当Uri为content://uri时,她会转为具体的MimeType,后面有例子。

剪贴板的简单使用

以拷贝文本为例,剪贴板的使用可以分为以下几步:

//1.获得ClipboardManager        ClipboardManager clipboardManager=(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);//2.将数据放到clip对象中         ClipData clipData=ClipData.newPlainText("textCopy",getResources().getString(R.string.source));                            // 类似的方法还有                            //创建一个包含 htmlText 的 ClipData                            //一般在浏览器中对网页进行拷贝的时候会调用此方法                            //其中 htmlText 是包含 HTML 标签的字符串                            //static public ClipData newHtmlText(CharSequence label, CharSequence text, String htmlText);                            //创建一个包含 Intent 的 ClipData                            //static public ClipData newIntent(CharSequence label, Intent intent);                            //创建一个包含 Uri 的 ClipData,MimeType 会根据 Uri 进行修改                            //static public ClipData newUri(ContentResolver resolver, CharSequence label, Uri uri);                            //与 newUri 相对应,但是并不会根据 Uri 修改 MimeType                            //static public ClipData newRawUri(CharSequence label, Uri uri);//3.将clipdata放入剪切板中         clipboardManager.setPrimaryClip(clipData);//4.从剪切板中取出数据        if(clipboardManager.hasPrimaryClip()){            ClipData clipData1=clipboardManager.getPrimaryClip();            ClipDescription description=clipboardManager.getPrimaryClipDescription();            String label= (String) description.getLabel();            String text=clipData.getItemAt(0).getText().toString();            tv.setText(text);        }

其他数据的拷贝参考:

对于剪贴板大部分操作都封装在 ClipboardUtil.java 里,使用时请记录调用 init(Context context) 方法进行初始化,建议在 Application.onCreate() 中进行,否则会造成内存泄漏。

/**

  • 剪贴板工具类
  • Created by littlejie on 2016/4/15.

    */

    public class ClipboardUtil {public static final String TAG = ClipboardUtil.class.getSimpleName();private static final String MIME_CONTACT = "vnd.android.cursor.dir/person";/** * 由于系统剪贴板在某些情况下会多次调用,但调用间隔基本不会超过5ms * 考虑到用户操作,将阈值设为100ms,过滤掉前几次无效回调 */private static final int THRESHOLD = 100;private Context mContext;private static ClipboardUtil mInstance;private ClipboardManager mClipboardManager;private Handler mHandler = new Handler();private ClipboardManager.OnPrimaryClipChangedListener onPrimaryClipChangedListener = new ClipboardManager.OnPrimaryClipChangedListener() {    @Override    public void onPrimaryClipChanged() {        mHandler.removeCallbacks(mRunnable);        mHandler.postDelayed(mRunnable, THRESHOLD);    }};private ClipboardChangedRunnable mRunnable = new ClipboardChangedRunnable();private List
    mOnPrimaryClipChangedListeners = new ArrayList<>();/** * 自定义 OnPrimaryClipChangedListener * 用于处理某些情况下系统多次调用 onPrimaryClipChanged() */public interface OnPrimaryClipChangedListener { void onPrimaryClipChanged(ClipboardManager clipboardManager);}private class ClipboardChangedRunnable implements Runnable { @Override public void run() { for (OnPrimaryClipChangedListener listener : mOnPrimaryClipChangedListeners) { listener.onPrimaryClipChanged(mClipboardManager); } }}private ClipboardUtil(Context context) { mContext = context; mClipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); mClipboardManager.addPrimaryClipChangedListener(onPrimaryClipChangedListener);}/** * 单例。暂时不清楚此处传 Activity 的 Context 是否会造成内存泄漏 * 建议在 Application 的 onCreate 方法中实现 * * @param context * @return */public static ClipboardUtil init(Context context) { if (mInstance == null) { mInstance = new ClipboardUtil(context); } return mInstance;}/** * 获取ClipboardUtil实例,记得初始化 * * @return */public static ClipboardUtil getInstance() { return mInstance;}public void addOnPrimaryClipChangedListener(OnPrimaryClipChangedListener listener) { if (!mOnPrimaryClipChangedListeners.contains(listener)) { mOnPrimaryClipChangedListeners.add(listener); }}public void removeOnPrimaryClipChangedListener(OnPrimaryClipChangedListener listener) { mOnPrimaryClipChangedListeners.remove(listener);}/** * 判断剪贴板内是否有数据 * * @return */public boolean hasPrimaryClip() { return mClipboardManager.hasPrimaryClip();}/** * 获取剪贴板中第一条String * * @return */public String getClipText() { if (!hasPrimaryClip()) { return null; } ClipData data = mClipboardManager.getPrimaryClip(); if (data != null && mClipboardManager.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { return data.getItemAt(0).getText().toString(); } return null;}/** * 获取剪贴板中第一条String * * @param context * @return */public String getClipText(Context context) { return getClipText(context, 0);}/** * 获取剪贴板中指定位置item的string * * @param context * @param index * @return */public String getClipText(Context context, int index) { if (!hasPrimaryClip()) { return null; } ClipData data = mClipboardManager.getPrimaryClip(); if (data == null) { return null; } if (data.getItemCount() > index) { return data.getItemAt(index).coerceToText(context).toString(); } return null;}/** * 将文本拷贝至剪贴板 * * @param text */public void copyText(String label, String text) { ClipData clip = ClipData.newPlainText(label, text); mClipboardManager.setPrimaryClip(clip);}/** * 将HTML等富文本拷贝至剪贴板 * * @param label * @param text * @param htmlText */public void copyHtmlText(String label, String text, String htmlText) { ClipData clip = ClipData.newHtmlText(label, text, htmlText); mClipboardManager.setPrimaryClip(clip);}/** * 将Intent拷贝至剪贴板 * * @param label * @param intent */public void copyIntent(String label, Intent intent) { ClipData clip = ClipData.newIntent(label, intent); mClipboardManager.setPrimaryClip(clip);}/** * 将Uri拷贝至剪贴板 * If the URI is a content: URI, * this will query the content provider for the MIME type of its data and * use that as the MIME type. Otherwise, it will use the MIME type * {@link ClipDescription#MIMETYPE_TEXT_URILIST}. * 如 uri = "content://contacts/people",那么返回的MIME type将变成"vnd.android.cursor.dir/person" * * @param cr ContentResolver used to get information about the URI. * @param label User-visible label for the clip data. * @param uri The URI in the clip. */public void copyUri(ContentResolver cr, String label, Uri uri) { ClipData clip = ClipData.newUri(cr, label, uri); mClipboardManager.setPrimaryClip(clip);}/** * 将多组数据放入剪贴板中,如选中ListView多个Item,并将Item的数据一起放入剪贴板 * * @param label User-visible label for the clip data. * @param mimeType mimeType is one of them:{@link android.content.ClipDescription#MIMETYPE_TEXT_PLAIN}, * {@link android.content.ClipDescription#MIMETYPE_TEXT_HTML}, * {@link android.content.ClipDescription#MIMETYPE_TEXT_URILIST}, * {@link android.content.ClipDescription#MIMETYPE_TEXT_INTENT}. * @param items 放入剪贴板中的数据 */public void copyMultiple(String label, String mimeType, List
    items) { if (items == null) { throw new NullPointerException("items is null"); } int size = items.size(); ClipData clip = new ClipData(label, new String[]{mimeType}, items.get(0)); for (int i = 1; i < size; i++) { clip.addItem(items.get(i)); } mClipboardManager.setPrimaryClip(clip);}public CharSequence coercePrimaryClipToText() { if (!hasPrimaryClip()) { return null; } return mClipboardManager.getPrimaryClip().getItemAt(0).coerceToText(mContext);}public CharSequence coercePrimaryClipToStyledText() { if (!hasPrimaryClip()) { return null; } return mClipboardManager.getPrimaryClip().getItemAt(0).coerceToStyledText(mContext);}public CharSequence coercePrimaryClipToHtmlText() { if (!hasPrimaryClip()) { return null; } return mClipboardManager.getPrimaryClip().getItemAt(0).coerceToHtmlText(mContext);}/** * 获取当前剪贴板内容的MimeType * * @return 当前剪贴板内容的MimeType */public String getPrimaryClipMimeType() { if (!hasPrimaryClip()) { return null; } return mClipboardManager.getPrimaryClipDescription().getMimeType(0);}/** * 获取剪贴板内容的MimeType * * @param clip 剪贴板内容 * @return 剪贴板内容的MimeType */public String getClipMimeType(ClipData clip) { return clip.getDescription().getMimeType(0);}/** * 获取剪贴板内容的MimeType * * @param clipDescription 剪贴板内容描述 * @return 剪贴板内容的MimeType */public String getClipMimeType(ClipDescription clipDescription) { return clipDescription.getMimeType(0);}/** * 清空剪贴板 */public void clearClip() { mClipboardManager.setPrimaryClip(null);}

}

 

转载于:https://blog.51cto.com/13652962/2354154

你可能感兴趣的文章
ひとり上手 中岛美雪 (漫步人生路 )
查看>>
win8.1下解决Visual C++不兼容的方法
查看>>
spark-sql中数据类型比较(double vs decimal)
查看>>
intellij 修改jsp 或者 html 自动加载页面变化
查看>>
MongoDB 常用命令
查看>>
B/S结构 进销存 客户管理 人资管理系统
查看>>
iOS 学习资料整理 {非常有用,强烈推荐}
查看>>
Linux上安装使用boost入门指导
查看>>
Tomcat去除项目名
查看>>
spring boot Controller不起作用的解决方案
查看>>
分布式ID生成算法总结
查看>>
Hadoop运维记录系列(二十三)
查看>>
debian下vim设置调试python 以及我的.vimrc
查看>>
LVS负载均衡集群技术学习笔记
查看>>
目录管理和文件管理
查看>>
一种基于状态机的 DOM 树生成技术(1)
查看>>
广播事件的两种类型。
查看>>
cmd进入控制Mysql&出现乱码的问题
查看>>
POJ 2407 Relatives 题解《挑战程序设计竞赛》
查看>>
Build RESTful APIs with Spring MVC: Testing
查看>>