Android剪下板
介紹
Android提供了一個強大的基於剪貼簿的複製和貼上框架。它既支援簡單的資料型別,也支援複雜的資料型別,包括文字字串、複雜的資料結構、文字和二進位制流資料,甚至還支援應用程式資源。
如下圖所示:

clip.png
由上圖可以簡單的得到Android剪下板模版主要由四個類構成: ClipboardManager
、 ClipData
、 ClipData.Item
、 ClipDescription
.
簡單的描述:系統複製資料,就是建立一個 ClipData
物件放在 ClipboardManager
全域性上. ClipData
可以包括多條 Item
子資料,子資料中複製內容可以是 text
, url
, intent
,但是都是這些子資料都是來自一次複製,每次複製會覆蓋之前的複製內容.同時, ClipData
中包含一個 ClipDescription
,用於描述本次複製內容的MimeType.
核心類
-
ClipboardManager
系統服務全域性的剪下板類.如何得到如下:
ClipboardManager mClipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
定義當剪貼簿上的主剪輯發生更改時呼叫的偵聽器回撥: OnPrimaryClipChangedListener
.
// 新增剪貼簿資料改變監聽器 mClipboardManager.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() { @Override public void onPrimaryClipChanged() { // 剪貼簿中的資料被改變,此方法將被回撥 System.out.println("onPrimaryClipChanged()"); } }); // 移除指定的剪貼簿資料改變監聽器 mClipboardManager.removePrimaryClipChangedListener(listener);
-
ClipData.Item
剪下板子資料類,它包含了
text
、html
、Uri
或者Intent
資料,一個clip
物件可以包含一個或多個Item
物件。一起來看看它的屬性:
final CharSequence mText; final String mHtmlText; final Intent mIntent; Uri mUri;
就是一個數據類.
-
ClipDescription
剪下板的描述類.包含了
ClipData
物件的metadata
資訊,一般情況mimeType
只有一個.一起看看它的屬性就知道幹什麼的類了.
public class ClipDescription implements Parcelable { //預設的MimeTYpe public static final String MIMETYPE_TEXT_PLAIN = "text/plain"; public static final String MIMETYPE_TEXT_HTML = "text/html"; public static final String MIMETYPE_TEXT_URILIST = "text/uri-list"; public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent"; public static final String EXTRA_TARGET_COMPONENT_NAME = "android.content.extra.TARGET_COMPONENT_NAME"; public static final String EXTRA_USER_SERIAL_NUMBER ="android.content.extra.USER_SERIAL_NUMBER"; //包含一個標籤 final CharSequence mLabel; //mimeType陣列 final String[] mMimeTypes; //可以儲存額外的資料 private PersistableBundle mExtras; ...... }
一般使用前面四種:text、html、uri、intent.其中url比較特殊.如果使用 Android
資源 MimeType
需要由 ContentResolver
提供.
什麼是uri:
通用資源標誌符(Universal Resource Identifier, 簡稱"URI")。
Uri代表要操作的資料,Android上可用的每種資源 - 影象、視訊片段等都可以用Uri來表示。
Android的Uri由以下三部分組成: "content://"、資料的路徑、標示ID(可選)
-
ClipData
剪下物件,在有且僅有一個剪下板物件在系統服務中.言外之意,每一次複製前一次複製內容都會消失.
一起來看看它的屬性:
public class ClipData implements Parcelable { //預設mimetype。 text/plain static final String[] MIMETYPES_TEXT_PLAIN = new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN }; //text/html static final String[] MIMETYPES_TEXT_HTML = new String[] { ClipDescription.MIMETYPE_TEXT_HTML }; //urllist static final String[] MIMETYPES_TEXT_URILIST = new String[] { ClipDescription.MIMETYPE_TEXT_URILIST }; //intent static final String[] MIMETYPES_TEXT_INTENT = new String[] { ClipDescription.MIMETYPE_TEXT_INTENT }; //剪下板描述類 final ClipDescription mClipDescription; final Bitmap mIcon; //用於存放剪下板子資料 final ArrayList<Item> mItems; ....... }
建立方式:
/** * Create a new ClipData holding data of the type * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}. * * @param label User-visible label for the clip data. * @param text The actual text in the clip. * @return Returns a new ClipData containing the specified data. */ static public ClipData newPlainText(CharSequence label, CharSequence text) { Item item = new Item(text); return new ClipData(label, MIMETYPES_TEXT_PLAIN, item); } /** * Create a new ClipData holding data of the type * {@link ClipDescription#MIMETYPE_TEXT_HTML}. * * @param label User-visible label for the clip data. * @param text The text of clip as plain text, for receivers that don't * handle HTML.This is required. * @param htmlText The actual HTML text in the clip. * @return Returns a new ClipData containing the specified data. */ static public ClipData newHtmlText(CharSequence label, CharSequence text, String htmlText) { Item item = new Item(text, htmlText); return new ClipData(label, MIMETYPES_TEXT_HTML, item); } /** * Create a new ClipData holding an Intent with MIME type * {@link ClipDescription#MIMETYPE_TEXT_INTENT}. * * @param label User-visible label for the clip data. * @param intent The actual Intent in the clip. * @return Returns a new ClipData containing the specified data. */ static public ClipData newIntent(CharSequence label, Intent intent) { Item item = new Item(intent); return new ClipData(label, MIMETYPES_TEXT_INTENT, item); } /** * Create a new ClipData holding a 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}. * * @param resolver ContentResolver used to get information about the URI. * @param label User-visible label for the clip data. * @param uri The URI in the clip. * @return Returns a new ClipData containing the specified data. */ static public ClipData newUri(ContentResolver resolver, CharSequence label, Uri uri) { //建立item Item item = new Item(uri); /*獲取mimeType*/ String[] mimeTypes = null; if ("content".equals(uri.getScheme())) { String realType = resolver.getType(uri); mimeTypes = resolver.getStreamTypes(uri, "*/*"); if (realType != null) { if (mimeTypes == null) { mimeTypes = new String[] { realType }; } else { String[] tmp = new String[mimeTypes.length + 1]; tmp[0] = realType; System.arraycopy(mimeTypes, 0, tmp, 1, mimeTypes.length); mimeTypes = tmp; } } } if (mimeTypes == null) { mimeTypes = MIMETYPES_TEXT_URILIST; } return new ClipData(label, mimeTypes, item); } /** * Create a new ClipData holding an URI with MIME type * {@link ClipDescription#MIMETYPE_TEXT_URILIST}. * Unlike {@link #newUri(ContentResolver, CharSequence, Uri)}, nothing * is inferred about the URI -- if it is a content: URI holding a bitmap, * the reported type will still be uri-list.Use this with care! * * @param label User-visible label for the clip data. * @param uri The URI in the clip. * @return Returns a new ClipData containing the specified data. */ static public ClipData newRawUri(CharSequence label, Uri uri) { //建立item Item item = new Item(uri); return new ClipData(label, MIMETYPES_TEXT_URILIST, item); }
clipData
物件建立後塞入 Clipboardmanager
即可:
//Clipboardmanager方法 /** * Sets the current primary clip on the clipboard.This is the clip that * is involved in normal cut and paste operations. * * @param clip The clipped data item to set. */ public void setPrimaryClip(ClipData clip) { try { if (clip != null) { clip.prepareToLeaveProcess(true); } getService().setPrimaryClip(clip, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
- 轉換成字串
//任何作為HTML格式返回的文字都將作為具有樣式跨度的文字返回。 CharSequence coerceToStyledText(Context context); //如果getText()是非空的,則返回該值。 //如果getUri()非null,則嘗試從其內容提供程式檢索其資料作為文字流。如果成功,將文字複製到字串中並返回。如果它不是內容:URI或內容提供程式不提供文字表示,則將原始URI作為字串返回。 //如果getIntent()非null,則將其轉換為intent: URI並返回。 //否則,返回一個空字串。 CharSequence coerceToText(Context context) ; //如果getHtmlText()非null,則返回該值。 //如果getText()是非空的,返回它,轉換為有效的HTML文字。如果此文字包含樣式跨度,則使用HTML . tohtml (span)將其轉換為HTML格式。 //如果getUri()非null,則嘗試從其內容提供程式檢索其資料作為文字流。 //如果提供程式可以提供文字/html資料,則首選該資料並按原樣返回。否則,將返回任何文字/*資料並轉義到HTML。 //如果它不是內容:URI或內容提供程式不提供文字表示,將返回包含到URI連結的HTML文字。 //如果getIntent()非null,則將其轉換為intent: URI並以HTML連結的形式返回。 //否則,返回一個空字串。 String coerceToHtmlText(Context context)
詳細的內容可以檢視官網,地址我也寫出來了,在最下面,哈哈哈.
-
注意
1、剪下板只會儲存最近一次複製的內容.
2、
MimeType
一般只有一個.(可以有多個)3、系統全域性的剪下板,其他應用也可以使用.
工具類
package com.rnx.react.modules.clip; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipboardManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.Uri; import java.util.List; /** * @Auther: weiwei.zhang06 * @Date: 2018/12/5 18:59 */ public class ClipboardHelper { public static final String TAG = ClipboardHelper.class.getSimpleName(); private Context mContext; private volatile static ClipboardHelper mInstance; private ClipboardManager mClipboardManager; private ClipboardHelper(Context context) { mContext = context; mClipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); } /** * 獲取ClipboardUtil例項,記得初始化 * * @return 單例 */ public static ClipboardHelper getInstance(Context context) { if (mInstance == null) { synchronized (ClipboardHelper.class) { if (mInstance == null) { mInstance = new ClipboardHelper(context.getApplicationContext()); } } } return mInstance; } /** * 判斷剪貼簿內是否有資料 * * @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 crContentResolver used to get information about the URI. * @param label User-visible label for the clip data. * @param uriThe 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 labelUser-visible label for the clip data. * @param mimeType mimeType is one of them:{@link ClipDescription#MIMETYPE_TEXT_PLAIN}, *{@link ClipDescription#MIMETYPE_TEXT_HTML}, *{@link ClipDescription#MIMETYPE_TEXT_URILIST}, *{@link ClipDescription#MIMETYPE_TEXT_INTENT}. * @param items放入剪貼簿中的資料 */ public void copyMultiple(String label, String mimeType, List<ClipData.Item> items) { if (items == null || items.size() == 0) { throw new IllegalArgumentException("argument: items error"); } 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 void copyMultiple(String label, String[] mimeTypes, List<ClipData.Item> items) { if (items == null || items.size() == 0) { throw new IllegalArgumentException("argument: items error"); } int size = items.size(); ClipData clip = new ClipData(label, mimeTypes, 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(ClipData.newPlainText(null, "")); } public ClipData getClipData() { if (!hasPrimaryClip()) { return null; } return mClipboardManager.getPrimaryClip(); } }
官網: ofollow,noindex">https://developer.android.com/guide/topics/text/copy-paste#java
ClipboardManger api: https://developer.android.com/reference/android/content/ClipboardManager
ClipData api: https://developer.android.com/reference/android/content/ClipData
ClipData.item api: https://developer.android.com/reference/android/content/ClipData.Item
ClipDescription api: https://developer.android.com/reference/android/content/ClipDescription