教你使用剪切板——Android中的復制&粘貼

最近開發(fā)過程中有使用到復制/粘帖功能侣诵,也在其中遇到了一些問題,就順勢學習一下復制粘貼相關的知識峦筒。

一氏义、前言

Android提供了一個強大的剪切板框架(以至于在復制某些內容粘帖到我的項目中的時候出現(xiàn)的格式問題的BUG)用于復制和粘帖锄列。同時支持簡單和復雜的數(shù)據(jù)類型,簡單的文本數(shù)據(jù)直接存儲在剪貼板中惯悠,而復雜的數(shù)據(jù)存儲為一個引用邻邮,即粘貼應用程序解析為內容提供者(這里涉及到ContentProvider)。

二克婶、框架&使用

框架圖

要復制數(shù)據(jù)筒严,應用程序將ClipData對象放在ClipboardManager全局剪貼板上。它ClipData包含一個或多個ClipData.Item對象和一個 ClipDescription對象情萤。要粘貼數(shù)據(jù)鸭蛙,應用程序會從中ClipData獲取其MIME類型ClipDescription,并從ClipData.Item或從內容提供者 獲取數(shù)據(jù)ClipData.Item筋岛。

可以看出Android剪貼板框架主要涉及到ClipboardManager娶视、ClipDataClipData.Item睁宰、ClipDescription這四個類歇万,下面詳細說明

  1. ClipboardManager是系統(tǒng)全局的剪貼板對象,通過context.getSystemService(CLIPBOARD_SERVICE)獲取勋陪。
  2. ClipData贪磺,即clip(剪切)對象,在系統(tǒng)剪貼板里只存在一個诅愚,當另一個clip對象進來時寒锚,前一個clip對象會消失。
  3. ClipData.Item违孝,即 data item刹前,它包含了文本、Uri或者Intent數(shù)據(jù)雌桑,一個clip對象可以包含一個或多個Item對象喇喉。通過 addItem(ClipData.Item item)可以實現(xiàn)往clip對象中添加Item
    • 文本:文本是直接放在 clip 對象中校坑,然后放在剪貼板里拣技;粘貼這個字符串的時候直接從剪貼板拿到這個對象,把字符串放入你的應用存儲中耍目。
    • Uri:對于復雜數(shù)據(jù)的剪貼拷貝并不是直接將數(shù)據(jù)放入內存膏斤,而是通過 Uri 來實現(xiàn),畢竟 Uri 的中文名叫:統(tǒng)一資源標識符邪驮。通過 Uri 能定位手機上所有資源莫辨,這當然能實現(xiàn)拷貝了,只不過需要做一些額外的處理工作。(對于 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);
        //創(chuàng)建ClipData對象
        ClipData clipData = ClipData.newPlainText("simple text copy", "Clipboard test.");
        //添加ClipData對象到剪切板中
        clipboardManager.setPrimaryClip(clipData);
    }

創(chuàng)建ClipData的方法還有另外四個:

    //創(chuàng)建一個包含 htmlText 的 ClipData
    //一般在瀏覽器中對網(wǎng)頁進行拷貝的時候會調用此方法,其中 htmlText 是包含 HTML 標簽的字符串
    public static ClipData newHtmlText(CharSequence label, CharSequence text, String htmlText)
    //創(chuàng)建一個包含 Intent 的 ClipData
    public static  ClipData newIntent(CharSequence label, Intent intent)
    //創(chuàng)建一個包含 Uri 的 ClipData档桃,MimeType 會根據(jù) Uri 進行修改
    public static  ClipData newUri(ContentResolver resolver, CharSequence label, Uri uri)
    //與 newUri 相對應枪孩,但是并不會根據(jù) Uri 修改 MimeType
    public static  ClipData newRawUri(CharSequence label, Uri uri)

從剪切板中獲取數(shù)據(jù),同樣以文本操作為例

    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直接從網(wǎng)易新聞復制了內容蔑舞,粘帖到我們自己的app中,之后文本的樣式都不對嘹屯,這是因為復制的內容是包含HTML標簽的字符串攻询,導致內容顯示有問題,String text = clipData.getItemAt(0).coerceToText(context).toString();最后使用coerceToText()將剪貼板數(shù)據(jù)強制轉換為文本解決問題州弟。

三钧栖、官方建議

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

  • At any time, there is only one clip on the clipboard. A new copy operation by any application in the system overwrites the previous clip. Since the user may navigate away from your application and do a copy before returning, you can't assume that the clipboard contains the clip that the user previously copied in your application.

  • The intended purpose of multiple ClipData.Item objects per clip is to support copying and pasting of multiple selections rather than different forms of reference to a single selection. You usually want all of the ClipData.Item objects in a clip to have the same form, that is, they should all be simple text, content URI, or Intent, but not a mixture.

  • When you provide data, you can offer different MIME representations. Add the MIME types you support to the ClipDescription, and then implement the MIME types in your content provider.

  • When you get data from the clipboard, your application is responsible for checking the available MIME types and then deciding which one, if any, to use. Even if there is a clip on the clipboard and the user requests a paste, your application is not required to do the paste. You should do the paste if the MIME type is compatible. You may choose to coerce the data on the clipboard to text using coerceToText() if you choose. If your application supports more than one of the available MIME types, you can allow the user to choose which one to use.

為設計有效的復制和粘貼功能,請記住以下幾點:

  • 任何時候婆翔,剪切板只有一個clip拯杠。系統(tǒng)中任何一個app的復制操作都會覆蓋上一次操作。用于用戶可以到導航你的app啃奴,在返回之前復制一次潭陪,你不能假設剪切板中包含用戶在你的app中復制剪切的數(shù)據(jù)。
  • clip的多個ClipData.Item對象是支持復制和粘貼多個選擇最蕾,而不是對單個選擇的不同形式的引用依溯。你通常希望ClipData.Item剪輯中的所有 對象具有相同的形式,即它們應該是簡單的文本揖膜,內容URI或者Intent混合誓沸。
  • 當你提供數(shù)據(jù)是,你可以提供不同的MIME屬性壹粟,添加MIME類型到ClipDescription中,然后在內容提供者中事項MIME類型。
  • 當你獲取剪切板的數(shù)據(jù)時趁仙,你的app檢查MIME類型的可用性然后確定使用的MIME類型洪添。即使用戶請求粘帖剪切板上的數(shù)據(jù),你的app也不是需要粘帖的雀费。如果MIME類型兼容你應該粘帖干奢。你也可以選擇用coerceToText()方法強制將數(shù)據(jù)轉化為文本。如果你的app支持多種MIME類型盏袄,你可能允許用戶選擇使用MIME類型

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末忿峻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子辕羽,更是在濱河造成了極大的恐慌逛尚,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刁愿,死亡現(xiàn)場離奇詭異绰寞,居然都是意外死亡,警方通過查閱死者的電腦和手機铣口,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門滤钱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人脑题,你說我怎么就攤上這事件缸。” “怎么了叔遂?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵他炊,是天一觀的道長。 經(jīng)常有香客問我掏熬,道長佑稠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任旗芬,我火速辦了婚禮舌胶,結果婚禮上,老公的妹妹穿的比我還像新娘疮丛。我一直安慰自己幔嫂,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布誊薄。 她就那樣靜靜地躺著履恩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呢蔫。 梳的紋絲不亂的頭發(fā)上切心,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天飒筑,我揣著相機與錄音,去河邊找鬼绽昏。 笑死协屡,一個胖子當著我的面吹牛,可吹牛的內容都是我干的全谤。 我是一名探鬼主播肤晓,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼认然!你這毒婦竟也來了补憾?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卷员,失蹤者是張志新(化名)和其女友劉穎盈匾,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體子刮,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡威酒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挺峡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葵孤。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖橱赠,靈堂內的尸體忽然破棺而出尤仍,到底是詐尸還是另有隱情,我是刑警寧澤狭姨,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布宰啦,位于F島的核電站,受9級特大地震影響饼拍,放射性物質發(fā)生泄漏赡模。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一师抄、第九天 我趴在偏房一處隱蔽的房頂上張望漓柑。 院中可真熱鬧,春花似錦叨吮、人聲如沸辆布。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锋玲。三九已至,卻和暖如春涵叮,著一層夾襖步出監(jiān)牢的瞬間惭蹂,已是汗流浹背伞插。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剿干,地道東北人蜂怎。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓穆刻,卻偏偏與公主長得像置尔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子氢伟,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容