浅析Android中的复制粘贴控制

我们都知道在Android系统的WebView中或者EditText上长按可以实现复制粘贴的功能,但是我们如果想要复制粘贴更多东西而不仅仅是文本,或者在粘贴时对粘贴的对象进行处理过滤一些不希望粘贴出来的东西,在看完这篇文章后你会对Android的复制粘贴有一个更深刻的认识。

概述

当我们需要使用复制粘贴功能时,首先要获得ClipboardManager对象

ClipboardManager mCM = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);

接下来我们就可以利用这个对象进行复制和粘贴操作了,如果想把一段文字复制到剪切板

mCM.setPrimaryClip(ClipData.newPlainText(null, “Hello ClipBoard”));

我们就把Hello ClipBoard复制到了剪切板。

如果想要获取剪切板的文本

ClipData data = mCM.getPrimaryClip();
ClipData.Item item = data.getItemAt(0);
String copyStr = item.getText().toString()

这样就实现了最简单的复制粘贴功能,当然,剪切板的功能可不止如此。

复制粘贴的类型

当使用ClipboardManager进行复制粘贴时,我们可以操作三种形式的数据,

Text:字符串

我们可以把字符串放入剪切板中吗,就如上面所示。

URI:一个Uri对象

表示任何形式的URI。这种形式主要用于从一个content provider中复制复杂的数据。复制的时候把一个Uri 对象放在一个clip对象中,然后再放在剪贴板里;粘贴的时候取出这个clip对象,得到Uri,把它解析为一个数据资源比如content provider,然后从资源中复制数据到应用存储中。

Intent:Intent对象

复制的时候把Intent对象放在clip对象中,再放入剪贴板;粘贴数据时,从clip对象中得到Intent对象,放入应用存储区域中。

剪切板只在同一时间储存一个剪切对象,当我们把一个剪切对象复制到剪切板时,剪切板中原有的剪切对象就会消失

剪切板相关的类

ClipboardManager

ClipboardManager代表了系统的剪贴板,我们不直接初始化这个类,而是通过getSystemService(CLIPBOARD_SERVICE)获取。

ClipData, ClipData.Item 和 ClipDescription

我们需要创建一个ClipData对象来把数据复制到剪切板中,这个ClipData对象包含一个数据的描述ClipDescription和一个或多个数据对象ClipData.Item

其中ClipDescription是对剪切对象的描述,而ClipData.Item是要复制到剪切板的具体内容

而如何获取这个ClipData对象呢,针对三种不同的剪切数据我们有三种不同的方法

newPlainText(CharSequence label, CharSequence text)

这个方法用于返回一个Text类型的ClipData对象,其中label为数据描述,text为数据,label的MIME类型是MIMETYPE_TEXT_PLAIN

newUri (ContentResolver resolver, CharSequence label, Uri uri)

这个方法用于返回一个URI类型的ClipData对象

newIntent (CharSequence label, Intent intent)

这个方法用于返回一个Intent类型的ClipData对象

URI和Intent的剪切板功能我们用的不多,这里主要以文本对象为例说明其用法。

文本的复制与粘贴

1.要操作剪切板我们首先需要ClipboardManager对象

ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

2.如果需要复制,我们首先需要获取一个ClipData对象,对于文本来说,用

ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");

获取该对象。然后将该对象放入剪切板中clipboard.setPrimaryClip(clip);,就可以使用剪切板了。

3.如果需要粘贴,我们首先需要取出剪切板中的对象

ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);

然后转换为StringString pasteData = item.getText();就可以使用了

当然我们这里要说的并不是这么简单,如果复制粘贴的时候需要屏蔽一些关键字,我们就需要去监听复制粘贴的事件了,这里以EditText为例说明如何监听其复制粘贴事件。

EditText复制粘贴事件的监听

要实现复制粘贴事件的监听,我们需要继承EditText,重写它的onTextContextMenuItem方法,同时新建一个EditTextClipListener的接口,用于监听的回调,具体代码如下

/**
 * ClipControlEditText.java
 */
public class ClipControlEditText extends android.support.v7.widget.AppCompatEditText {

    //事件监听器
    private ArrayList<EditTextClipListener> listeners;

    public ClipControlEditText(Context context) {
        super(context);
        listeners = new ArrayList<>();
    }

    public ClipControlEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        listeners = new ArrayList<>();
    }

    public ClipControlEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        listeners = new ArrayList<>();
    }

    public void addListener(EditTextClipListener listener) {
        try {
            listeners.add(listener);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }


    @Override
    public boolean onTextContextMenuItem(int id) {
        switch (id){
            case android.R.id.cut: //剪切
                onTextCut();
                break;
            case android.R.id.paste: //复制
                onTextPaste();
                break;
            case android.R.id.copy: //粘贴
                onTextCopy();
                break;
        }
        return super.onTextContextMenuItem(id);
    }

    public void onTextCut(){
        if (listeners != null) {
            for (EditTextClipListener listener : listeners) {
                listener.onCut();
            }
        }
    }

    public void onTextCopy(){
        if (listeners != null) {
            for (EditTextClipListener listener : listeners) {
                listener.onCopy();
            }
        }
    }

    public void onTextPaste(){
        if (listeners != null) {
            for (EditTextClipListener listener : listeners) {
                listener.onPaste();
            }
        }
    }
}

EditTextClipListener接口有三个方法分别是onCut()、onCopy()和onPaste()

public interface EditTextClipListener {
    void onCut();
    void onCopy();
    void onPaste();
}

接下来就可以在需要的地方监听了,在需要的地方调用

et.addListener(new EditTextClipListener(){
    @Override
    public void onCut() {

    }
    @Override
    public void onCopy() {

    }
    @Override
    public void onPaste() {

    }
});

就可以监听EditText的复制粘贴同时处理一些其他的事情了,回到上文,如果我们想在复制粘贴时屏蔽某些字符,只要在回调方法中拿到剪切板中的对象,然后对对象进行一系列处理,再把处理后的对象放回剪切板中,就可以在粘贴时屏蔽需要的内容了

ClipData data = mCM.getPrimaryClip();
ClipData.Item item = data.getItemAt(0);
if (item != null && !TextUtils.isEmpty(item.getText())) {
    String pasteStr = removeSomething(item.getText()) //删除字符串中的关键字
    ClipData newData = ClipData.newPlainText(data.getDescription().getLabel(), pasteStr2);
    mCM.setPrimaryClip(newData);
}

至于如何处理URI和Intent对象的复制粘贴,可以参考谷歌官方文档对于复制和粘贴的介绍