安卓監聽剪切複製粘貼事件實例

本文的剪切複製粘貼事件只針對文本,URI 和 intent 不在討論範圍內。
實例代碼實現了2個功能:

  • 監聽剪切複製粘貼事件;
  • 獲取剪切複製或粘貼的文本;

剪切複製

有2個方法監聽剪切複製事件:剪切板和 EditText 的 onTextContextMenuItem() 方法。

二者的主要區別是:

  • 剪切板是系統層面的全局性質的監聽,而onTextContextMenuItem 只對某個 EditText 控件有效。
  • 剪切板只能監聽到剪切複製事件,而無法監聽到粘貼事件,而 onTextContextMenuItem 能既能監聽到剪切複製事件,又能監聽粘貼事件;

方法一:剪切板

關於剪切板,詳見官方文檔:ClipboardManager

在這裏囉嗦幾句關於 Clipboard 的知識點:

  • 剪切板不僅可以存文本,還可以存 URI 和 Intent;
  • 剪切板上只保持對 PrimaryClip 的引用,即最新一次的剪切數據;
  • OnPrimaryClipChangedListener 回調只對剪切和複製操作有效,即只有剪切板數據增加時才調用 OnPrimaryClipChangedListener;
  • 剪切板上有多個 ClipData 構成,每次剪切和複製事件都會產生一個 ClipData,ClipData 包含 ClipDescprition 和 若干個保存數據的 ClipData.Item;

監聽剪切和複製事件,如果是文本則保存對應文本:

    private void registerClipEvents() {

        final ClipboardManager manager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);

        manager.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
            @Override
            public void onPrimaryClipChanged() {

                if (manager.hasPrimaryClip() && manager.getPrimaryClip().getItemCount() > 0) {

                    CharSequence addedText = manager.getPrimaryClip().getItemAt(0).getText();

                    if (addedText != null) {
                        Log.d(TAG, "copied text: " + addedData);
                    }
                }
            }
        });
    }

注意,一定要在 onDestroy() 方法裏面去調用 addPrimaryClipChangedListener() 註銷掉,否則會出現內存泄露。

方法二:EditText#onTextContextMenuItem

在該方法中,我們可以監聽到剪切、複製和粘貼事件,但是需要繼承 EditText 重寫該方法:

public final class Listen2PasteEditText extends android.support.v7.widget.AppCompatEditText {

    private static final String TAG = "Listen2PasteEditText";

    private Context mContext;

    public Listen2PasteEditText(Context context) {
        super(context);
        mContext = context;
    }

    public Listen2PasteEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    @Override
    public boolean onTextContextMenuItem(int id) {

        switch (id) {
            case android.R.id.cut:
            if (mContext instanceof IClipCallback) {
                    ((IClipCallback) mContext).onCut(null);
                break;
            case android.R.id.copy:
            if (mContext instanceof IClipCallback) {
                    ((IClipCallback) mContext).onCopy(null);
                break;
            case android.R.id.paste:
                if (mContext instanceof IClipCallback) {
                    ((IClipCallback) mContext).onPaste(null);
                }
        }

        return super.onTextContextMenuItem(id);
    }
}

其中,IClipCallback 是個接口, Listen2PasteEditText 所在的 Activity 需要實現該接口。

IClipCallback 聲明如下:

public interface IClipCallback {
    void onCut(Object o);
    void onCopy(Object o);
    void onPaste(Object o);
}

注意,上述代碼只是讓我們監聽到了剪切和複製事件,要想獲取文本,還是要藉助剪切板,具體見 registerClipEvents() 方法,此處不再贅述。

粘貼

剪切板無法監聽到粘貼事件,只能通過 EditText#onTextContextMenuItem() 方法實現。

至於得到粘貼文本,還是需要通過剪切板獲得。

具體代碼見方法二。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章