1. 程式人生 > >Android自定義文字選中模式(全選、複製,剪下,粘帖)

Android自定義文字選中模式(全選、複製,剪下,粘帖)

為了方便操作,在PC端我們常用的Ctrl+A(全選)/Ctrl+C(複製)/Ctrl+X(剪下)/Ctrl+V(粘帖)提高了我們的辦公效率。然後在手機端怎麼實現呢?我花了一天的時間研究了一下。

  • 首先說一下TextView的選中,要想選中TextView中的文字有兩種方式:
    1、setSelectAllOnFocus(true);
    2、android:textIsSelectable=”true”
  • 然後看一下EditText
    這裡寫圖片描述
    從上面的圖可以看出EditText是繼承於TextView的,所以setSelectAllOnFocus(true)和android:textIsSelectable=”true”對它也同樣適用,不過EditText預設setSelectAllOnFocus(true),所以沒有必要手動設定;如果真的在佈局檔案中設定了android:textIsSelectable=”true”,那麼EditText就不能被編輯,失去了游標,如下圖:
    這裡寫圖片描述

    所以android:textIsSelectable=”true”一般是給TextView設定的。

首先我們看一下預設的選中模式(上面彈出操作提示框):
這裡寫圖片描述
那麼要想改變原有的東西呢?這裡有一個方法

setCustomSelectionActionModeCallback(new MyActionModeCallback(ActionMode.Callback callback));

通過ActionMode.Callback中的四個回撥方法進行操作:

//建立選單
        @Override
        public boolean onCreateActionMode
(ActionMode actionMode, Menu menu) { return true; } //這個相當於是選單建立好以後的操作 @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return true; } //選單中item的點選處理 @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return
true; } //選單銷燬操作 @Override public void onDestroyActionMode(ActionMode actionMode) { }

首先要去自定義一個選單佈局:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <item
        android:id="@+id/it_all"
        android:title="全選"
        android:icon="@drawable/all"
        />
    <item
        android:id="@+id/it_copy"
        android:title="複製"
        android:icon="@drawable/copy"
        />
    <item
        android:id="@+id/it_cut"
        android:title="剪下"
        android:icon="@drawable/cut"
        />
    <item
        android:id="@+id/it_paste"
        android:title="粘帖"
        />
</menu>

這裡的android:icon=“@drawable/xxx”設定了,但是不顯示。然後在onCreateActionMode方法中去初始化選單;

 MenuInflater menuInflater = actionMode.getMenuInflater();
            menuInflater.inflate(R.menu.menu,menu);
            return true;

選單建立好以後就是具體的操作了。

全選

Edittext有個selectAll()方法來實現全選;這個方法是Edittext獨有的,所以TextView是沒這個方法的。
這裡寫圖片描述

複製、剪下

複製和剪下的原理一樣,就是最後的處理稍有不同,所以我把他們放在了同一個方法中進行處理。

  /**
     *  統一處理複製和剪下的操作
     * @param mode 用來區別是複製還是剪下
     * @return
     */
    private String getSelectText(SelectMode mode) {
        //獲取剪下班管理者
        ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE);
        //獲取選中的起始位置
        int selectionStart = mTvSelect.getSelectionStart();
        int selectionEnd = mTvSelect.getSelectionEnd();
        Log.i(TAG,"selectionStart="+selectionStart+",selectionEnd="+selectionEnd);
        //擷取選中的文字
        String txt = mTvSelect.getText().toString();
        String substring = txt.substring(selectionStart, selectionEnd);
        Log.i(TAG,"substring="+substring);
        //將選中的文字放到剪下板
        cbs.setPrimaryClip(ClipData.newPlainText(null,substring));
        //如果是複製就不往下操作了
        if (mode==SelectMode.COPY)
            return txt;
        //把剪下後的資料替換""
        txt = txt.replace(substring, "");
        return txt;
    }

    /**
     * 用列舉來區分是複製還是剪下
     */
    public enum SelectMode{
        COPY,CUT;
    }

這裡我把相容低版本沒有做,API Level 11以前用的setText(),getText(),hasText()這三個方法做複製粘帖的操作(只限於對文字的操作);以後的API中廢棄了以前的三個方法,通過ClipData物件來操作文字、Uri和Intent,用ClipboardManager.setPrimaryClip(ClipData data),ClipboardManager.getPrimaryClip()和hasPrimaryClip()代替前面的三個方法了。這裡操作的就不是純文字,而是複雜的物件了。

ClipData 的三個靜態方法分別擔任不同的工作(ClipData物件中包含一個或多個ClipData.Item物件)

  • ClipData.newPlainText(“Label”, “Content”)建立普通字元型ClipData
  • ClipData.newRawUri(“Label”, Uri.parse(“https://www.baidu.com/“)) 建立URL型ClipData
  • ClipData.newIntent(“Label”, intent)建立Intent型ClipData

粘帖

                  //獲取剪下班管理者
                    ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE);
                    if (cbs.hasPrimaryClip()){
                        mTvSelect.setText(cbs.getPrimaryClip().getItemAt(0).getText());
                    }

基本操作就OK了,我把完整的Java程式碼貼一下。

/**
 * 描述:文字的選中模式的使用
 * 開發者:開發者的樂趣JRT
 * 建立時間:2017-3-12 12:29
 * CSDN地址:http://blog.csdn.net/Jiang_Rong_Tao/article
 * E-mail:[email protected]
 **/
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private EditText mTvSelect;
    private MainActivity mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext =this;
        init();
    }
    private void init() {
        mTvSelect = (EditText) findViewById(R.id.tv_select);
        mTvSelect.setCustomSelectionActionModeCallback(new MyActionModeCallback());
    }
    private class MyActionModeCallback implements ActionMode.Callback {
        private Menu mMenu;
        @Override
        public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
            MenuInflater menuInflater = actionMode.getMenuInflater();
            menuInflater.inflate(R.menu.menu,menu);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
           //選單建立完成以後獲取到其物件,便於後續操作
            this.mMenu=menu;
            return true;
        }

        @Override
        public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
            switch (menuItem.getItemId()){
                case R.id.it_all:
                    //全選
                    mTvSelect.selectAll();
                    Toast.makeText(mContext, "完成全選", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.it_copy:
                    String selectText = getSelectText(SelectMode.COPY);
                    //setText(selectText)是為了後面的this.mMenu.close()起作用
                    mTvSelect.setText(selectText);
                    Toast.makeText(mContext, "選中的內容已複製到剪下板", Toast.LENGTH_SHORT).show();
                    this.mMenu.close();
                    break;
                case R.id.it_cut:
                    //剪下
                    String txt = getSelectText(SelectMode.CUT);
                    mTvSelect.setText(txt);
                    Toast.makeText(mContext, "選中的內容已剪下到剪下板", Toast.LENGTH_SHORT).show();
                    this.mMenu.close();
                    break;

                case R.id.it_paste:
                    //獲取剪下班管理者
                    ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE);
                    if (cbs.hasPrimaryClip()){
                        mTvSelect.setText(cbs.getPrimaryClip().getItemAt(0).getText());
                    }
                    this.mMenu.close();
                    break;
            }
            return true;
        }

        @Override
        public void onDestroyActionMode(ActionMode actionMode) {

        }
    }

    /**
     *  統一處理複製和剪下的操作
     * @param mode 用來區別是複製還是剪下
     * @return
     */
    private String getSelectText(SelectMode mode) {
        //獲取剪下班管理者
        ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE);
        //獲取選中的起始位置
        int selectionStart = mTvSelect.getSelectionStart();
        int selectionEnd = mTvSelect.getSelectionEnd();
        Log.i(TAG,"selectionStart="+selectionStart+",selectionEnd="+selectionEnd);
        //擷取選中的文字
        String txt = mTvSelect.getText().toString();
        String substring = txt.substring(selectionStart, selectionEnd);
        Log.i(TAG,"substring="+substring);
        //將選中的文字放到剪下板
        cbs.setPrimaryClip(ClipData.newPlainText(null,substring));
        //如果是複製就不往下操作了
        if (mode==SelectMode.COPY)
            return txt;
        txt = txt.replace(substring, "");
        return txt;
    }

    /**
     * 用列舉來區分是複製還是剪下
     */
    public enum SelectMode{
        COPY,CUT;
    }
}

注意:這裡this.mMenu.close()有個細節,如果單純的呼叫close方法是不起作用的,必須EditText的文字有所變化

  • 如果不重新設定EditText的文字,則menu的close方法不管用
    選單不能關閉的效果
  • 重新設定文字後
    選單關閉的效果

總結

基本的操作就到此結束了,EditText的UI和選中後的游標也有點抽,這些都是可以自定義改變的,具體操作,自行Search。

github:原始碼下載

相關推薦

Android定義文字選中模式複製

為了方便操作,在PC端我們常用的Ctrl+A(全選)/Ctrl+C(複製)/Ctrl+X(剪下)/Ctrl+V(粘帖)提高了我們的辦公效率。然後在手機端怎麼實現呢?我花了一天的時間研究了一下。 首先說一下TextView的選中,要想選中TextV

【朝花夕拾】Android定義View篇之Canvas繪製文字教程

前言       前面的文章中在介紹Canvas的時候,提到過後續單獨講Canvas繪製文字,因為這一節內容比較細緻,內容很多。這裡先宣告一下,本文的內容的來源於騰訊課堂中“仍物線學堂”中課件,因為該課件對常用的繪製文字基本技巧做了比較詳細的講解

TabTopAutoTextSizeLayout【定義文字字號區域動態選項卡數據且可滑動

標題 unit near cnblogs 重新 auto target 類文件 fault 版權聲明:本文為HaiyuKing原創文章,轉載請註明出處! 前言 自定義頂部選項卡布局LinearLayout類,實現可滑動效果。【實際情況中建議使用RecyclerView】

android 定義文字字型

@SuppressLint("AppCompatCustomView") public class TypefaceTextView extends TextView { //字型檔案放在assets檔案中 // fongUrl是自定義字型分類的名稱 private static S

Android 定義橫向進度條可動態設定最大值

自定義橫向進度條       主佈局檔案中包 含          <LinearLayout android:id="@+id/linearlayout" android:layout_width="match_parent" androi

android定義文字後面帶清空按鈕

class MyEditText extends EditText { private final String TAG = "MyEditText"; private Drawable dRight; private Rect rBounds; // 構造器 public MyEditText(Conte

Android 定義view --圓形百分比進度條

注:本文由於是在學習過程中寫的,存在大量問題(overdraw onDraw new物件),請讀者們不要被誤導!!解決辦法見後面的部落格。 起因 最近公司專案有需求需要用到輕量級圖表如下

android 定義dialog的實現定義大小去除黑色邊框等

搜尋相關關鍵字網上一大堆實現,但是看完總覺得缺胳膊少腿,繞了不少彎路,終於弄好了自定義dialog。把自己整合的完整程式碼發上來。 要點: 1、設定自定義dialog的佈局檔案my_dialog.xml 2、設定一份自定義的樣式檔案styles_wx.xml,該檔案用於覆

Android定義view第一彈防小米計步

廢話不多說,先上效果圖: 右上腳的計步(有動畫效果) 從來不說廢話,上程式碼: 一.自定義View 程式碼 /** * 計步View * Created by DYJ on 2017/8/3. */ public class RunningV

簡單談談android定義相機的實現android.hardware.Camera

通常情況下,呼叫android系統相機基本上可以滿足拍照的需求,而自定義相機的需求一般來自於開發自己的相機應用,今天我們來簡單聊聊android自定義相機的實現,限於篇幅,我們上篇只討論android.hardware.Camera,下篇我會和大家一起討論一下a

Android定義視訊播放器

一、引言 在上文中,我們通過自定義控制面板的佈局,來實現自定義的播放控制,下面來對裡面的各個元件進行事件繫結。 @Override public void onClick(View v) { if ( v == btnVoice ) {

Android定義文字閃爍漸變色的跑馬燈

最近因為專案需要,一直都在尋找比較貼合專案主題的跑馬燈,但是寫的demo都是可以執行的,但是整合到專案中的時候就不起作用了,看了許多的資料,最後總結這都是執行緒的問題,後來各種搗騰,終於寫出了一個比較合適的跑馬燈,整合到專案中也是可以執行的,希望大神能多多指點 自定義一個控

Android 定義View--ProgressBar篇

1、概述 1.1 目的 : 在我們的日常開發中,有很多Android UI介面上有一些特殊或者特別的控制元件與介面,是Android自帶的控制元件所不能滿足的,需要我們自己定製一些適合的控制元件來完成。 1.2 Android自定義View步驟 : 自定

Android定義視訊播放器

一、引言 現在已經差不多完成了一個自定義的視訊播放器,還有一個讓視訊全屏播放的按鈕事件沒有繫結,下面會介紹。此外還要一個非常重要的功能就是,已經寫好了自定義的播放器,那麼就應該能被其他應用調起,來播放視訊,下面來完善這兩個功能。 二、全屏按鈕事件

android定義環形統計圖帶動畫

一、測試截圖 二、實現原理  package com.freedomanlib; import java.util.Timer; import java.util.TimerTask; import android.annotation.SuppressLint;

Android定義視訊播放器

一、引言 我們在開發Android多媒體應用時,有兩種方式來播放多媒體資源。第一種是使用隱式的Intent,來使用系統或者手機已經安裝的第三方播放器應用來播放音視訊,第二種是使用Android自帶的、我們自定義的播放器來播放,這種主要是採用Android提供的

android定義view之地圖

最近參加了一個比賽,要用到自己做一個自定義的小地圖,所以在網上查找了一些關於自定義view的有關資料,也瞭解了自定義控制元件的初步知識。 效果圖 第一階段我畫了一個自制的網格圖,點哪個網格就會哪個網格就會顯示。 工作環境圖 程式碼介紹

Android定義ActionBar背景顏色從原始碼分析

Android自定義ActionBar背景顏色 修改前後效果圖:   在style.xml里加一行程式碼搞定 <!-- Base application theme. --> <style name="AppTheme" parent="

Android 定義鍵盤 隨機鍵盤完全定製向上頂佈局按鈕進行隱藏

     之前上傳的另外一個自定義鍵盤,並沒有實現鍵盤彈出的時候,佈局向上自動調整。(網路上所有的自定義鍵盤都沒有新增自適應的功能,而且佈局沒這麼好看,上一個例子資源連結為:http://download.csdn.net/detail/omayyouhappy/91118

Android定義AutoCompleteTextView實現自動補Email

本篇主要實現了你可以自行控制從第一個字元開始進行聯想 public class AutoComplete extends AutoCompleteTextView { //輸入字元進行聯想,@163.com、@126.com、@qq.com、@sina.com、