Android複製粘貼

Android實現複製/粘貼

參考:

http://developer.android.com/guide/topics/text/copy-paste.html

The Clipboard Framework

  當使用clipboard framework時,把數據放在一個剪切對象(clip object)裏,然後這個對象會放在系統的剪貼板裏。

  clip object可以有三種形式:

  Text:文字字符串。

  文字是直接放在clip對象中,然後放在剪貼板裏;粘貼這個字符串的時候直接從剪貼板拿到這個對象,把字符串放入你的應用存儲中。

  URI:一個Uri 對象。

  表示任何形式的URI。這種形式主要用於從一個content provider中複製複雜的數據。

  複製的時候把一個Uri 對象放在一個clip對象中,然後再放在剪貼板裏;粘貼的時候取出這個clip對象,得到Uri,把它解析爲一個數據資源比如content provider,然後從資源中複製數據到應用存儲中。

  Intent: Intent對象。

  這支持了複製應用快捷方式。

  複製的時候把Intent對象放在clip對象中,再放入剪貼板;粘貼數據時,從clip對象中得到Intent對象,放入應用存儲區域中。

 

  剪貼板每次僅會持有一個clip對象,當應用放另一個clip對象進來時,前一個就消失了。

 

剪貼板的類

ClipboardManager

  ClipboardManager代表了系統的剪貼板,通過getSystemService(CLIPBOARD_SERVICE)獲取。

  全名爲android.text.ClipboardManager從API 11開始就廢棄了。

  取而代之的是它的子類:android.content.ClipboardManager (since API Level 11)。

if(Build.VERSION.SDK_INT > 11){
  
      android.content.ClipboardManager;

}else{

      android.text.ClipboardManager;

}

 

ClipData, ClipDescription, and ClipData.Item

  前面說的clip對象就是ClipData類的對象,其中包含了一個 ClipDescription對象和一個或多個ClipData.Item對象。

  ClipDescription對象中包含了一個數組,描述clip對象的MIME類型。

  ClipData.Item對象中包含文字、URI或者Intent數據。一個clip對象中可以包含一個或多個Item對象

 

  比如你想要複製list中的多項數據,你可以爲list中的每一項創建一個ClipData.Item對象,然後把它們放進一個ClipData對象中,這樣就一次性把多項數據都放在了剪貼板中。

  注意ClipData這個類是API 11纔有的。

 

ClipData中的簡潔方法

  ClipData類中有一些靜態的簡潔方法,用於創建只有一個ClipData.Item和一條簡單描述( ClipDescription)的ClipData對象。

  newPlainText(label, text)返回ClipData對象,數據是文字text,描述是label,MIME類型是MIMETYPE_TEXT_PLAIN

  類似的有:

  newUri(resolver, label, URI)

  newIntent(label, intent)

 

 

把剪貼板中的數據強轉爲文字

  剪貼板中的非text數據可以通過ClipData.Item.coerceToText()方法轉換爲text處理。

  1.這個方法首先會檢測item是不是包含text,如果有就直接返回。

  2.不包含text,之後看是否有URI:

  如果這個URI是content URI,並且provider返回文字流,coerceToText()就返回該文字流;

  如果provider不返回文字流,或者這個URI根本不是content URI,coerceToText()方法會返回URI的表達,即 Uri.toString()

  3.最後,如果這個item即不包含text也沒有URI,那麼它就應該包含Intent, coerceToText() 方法會把Intent對象轉化爲一個Intent URI返回,  和 Intent.toUri(URI_INTENT_SCHEME)一樣。

 

Android clipboard framework總結

  如圖:

 

 

 

複製到剪貼板

  1.首先,獲取剪貼板服務:

// Gets a handle to the clipboard service.
ClipboardManager clipboard = (ClipboardManager)
        getSystemService(Context.CLIPBOARD_SERVICE);

 

  2.然後把數據放在ClipData對象中。

  對文字:

// Creates a new text clip to put on the clipboard
ClipData clip = ClipData.newPlainText("simple text","Hello, World!");

  對URI:

複製代碼
// Creates a Uri based on a base Uri and a record ID based on the contact's last name
// Declares the base URI string
private static final String CONTACTS = "content://com.example.contacts";

// Declares a path string for URIs that you use to copy data
private static final String COPY_PATH = "/copy";

// Declares the Uri to paste to the clipboard
Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + "/" + lastName);

...

// Creates a new URI clip object. The system uses the anonymous getContentResolver() object to
// get MIME types from provider. The clip object's label is "URI", and its data is
// the Uri previously created.
ClipData clip = ClipData.newUri(getContentResolver(),"URI",copyUri);
複製代碼

  對Intent:

複製代碼
// Creates the Intent
Intent appIntent = new Intent(this, com.example.demo.myapplication.class);

...

// Creates a clip object with the Intent in it. Its label is "Intent" and its data is
// the Intent object created previously
ClipData clip = ClipData.newIntent("Intent",appIntent);
複製代碼

 

  3.把clip對象放在剪貼板中:

// Set the clipboard's primary clip.
clipboard.setPrimaryClip(clip);

從剪貼板中粘貼

  以文字的粘貼爲例,其他略。

  例子如下:

複製代碼
package com.example.helloclipboard;

import android.os.Bundle;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class HelloClipboardMainActivity extends Activity {

    private EditText mEditText1 = null;
    private TextView mResultTextView = null;

    private ClipboardManager mClipboard = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hello_clipboard_main);

        mResultTextView = (TextView) findViewById(R.id.textView1);
        mEditText1 = (EditText) findViewById(R.id.editText1);
        Button copyButton = (Button) findViewById(R.id.button1);

        Button pasteButton = (Button) findViewById(R.id.button2);

        copyButton.setOnClickListener(mOnClickListener);
        pasteButton.setOnClickListener(mOnClickListener);

    }

    private OnClickListener mOnClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {

            switch (v.getId()) {
            case R.id.button1:
                copyFromEditText1();
                break;
            case R.id.button2:
                pasteToResult();
                break;

            default:
                break;
            }
        }
    };

    private void copyFromEditText1() {

        // Gets a handle to the clipboard service.
        if (null == mClipboard) {
            mClipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

        }

        // Creates a new text clip to put on the clipboard
        ClipData clip = ClipData.newPlainText("simple text",
                mEditText1.getText());

        // Set the clipboard's primary clip.
        mClipboard.setPrimaryClip(clip);
    }

    private void pasteToResult() {
        // Gets a handle to the clipboard service.
        if (null == mClipboard) {
            mClipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        }

        String resultString = "";
        // 檢查剪貼板是否有內容
        if (!mClipboard.hasPrimaryClip()) {
            Toast.makeText(HelloClipboardMainActivity.this,
                    "Clipboard is empty", Toast.LENGTH_SHORT).show();
        }
        else {
            ClipData clipData = mClipboard.getPrimaryClip();
            int count = clipData.getItemCount();

            for (int i = 0; i < count; ++i) {

                ClipData.Item item = clipData.getItemAt(i);
                CharSequence str = item
                        .coerceToText(HelloClipboardMainActivity.this);
                Log.i("mengdd", "item : " + i + ": " + str);

                resultString += str;
            }

        }
        mResultTextView.setText(resultString);
    }
}
複製代碼

 

 

設計有效的複製粘貼功能

  爲了設計有效的複製粘貼功能,以下幾點需要注意:

  1.任何時間,都只有一個clip對象在剪貼板裏。

  新的複製操作都會覆蓋前一個clip對象,因爲用戶可能從你的應用中退出,從其他應用中拷貝一個東西,所以你不能假定用戶在你的應用中拷貝的上一個東西一定還放在剪貼板裏。

 

  2.一個clip對象,即ClipData中的多個ClipData.Item 對象是爲了支持多選項的複製粘貼,而不是爲了支持單選的多種形式。

  你通常需要clip對象中的所有的項目,即ClipData.Item有一樣的形式,比如都是文字,都是URI或都是Intent,而不是混合各種形式。

 

  3.當你提供數據時,你可以提供不同的MIME表達方式。

  將你支持的MIME類型加入到ClipDescription中去,然後在你的content provider中實現它。

 

  4.當你從剪貼板得到數據時,你的應用有責任檢查可用的MIME類型,然後決定使用哪一個。

  即便有一個clip對象在剪貼板中並且用戶要求粘貼,你的應用有可能不需要進行粘貼操作。

  你應該在MIME類型兼容的時候執行粘貼操作。你可以選擇使用 coerceToText()方法將粘貼的內容轉換爲文字。

  如果你的應用支持多種類型,你可以讓用戶自己選用哪一個。