今天來學學如何使用Clipboard

其實也就是俗稱的“剪貼簿”啦!(`・ω・´)+

調閱官方網站的資料的話

官網甚至直接命名Copy and Paste

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

要搜尋關鍵字的話,搜尋

  • android Copy and Paste
  • android clipboard
  • android 剪貼簿
  • android 文字複製

...等等,基本上就是秀出很多你想知道的資訊了(•ө•)♡

另外,雖然一般而言手機廠商在出廠時其實都會有內建剪貼簿

不過今天想做的事就是針對像是ListView、RecyclerView內部的資料做複製與貼上

那以下就是今天的範例:

Gif_20200201131814364_by_gifguru

以及GitHub:

https://github.com/thumbb13555/ClipboardExample/tree/master


1.功能需求設置介面

1-1功能需求

歸納一下今天想要完成的功能

  1. 建立一個ListView,再將欲複製之字元串放在裡面
  2. 長點擊ListView元件即可複製
  3. 長點擊EditText即可直接將剛才複製的元件貼上去

1-2設置介面

因為這次要設置的東西不多,因此直接貼上來了

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="120dp"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <EditText
            android:id="@+id/editText_in"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:inputType="textPersonName" />

        <Button
            android:id="@+id/button_clear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="清除文字" />
    </LinearLayout>

    <ListView
        android:id="@+id/listview_TextBox"
        android:layout_width="0dp"
        android:layout_height="300dp"
        android:layout_marginTop="24dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

樹狀圖長這樣

截圖 2020-02-01 下午2.39.46

1-3加入震動權限

我刻意讓APP在完成複製或貼上時會讓手機有一個小震動(・∀・)

關於震動的使用方法超簡單,兩行的事兒,沒事兒沒事兒(´υ`)

但是還是得加入震動權限

請點擊AndroidManifest.xml

截圖 2020-02-01 下午2.45.26

並在<manifest>標籤外部加入震動權限

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jetec.clipboardexample">
    <uses-permission android:name="android.permission.VIBRATE" />
<!--震動權限-->

    <application ...

截圖 2020-02-01 下午2.47.28

2.功能撰寫

接著撰寫功能的部分

因為程式不多,直接上程式吧

public class MainActivity extends AppCompatActivity {

    ArrayList<String> arrayList = new ArrayList<>();
    ListView listView;
    ClipboardManager clipboard = null;//複製貼上
    ClipData clipData = null;//複製貼上

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

        Button clear= findViewById(R.id.button_clear);
        EditText editText = findViewById(R.id.editText_in);
        listView = findViewById(R.id.listview_TextBox);
/**=========================================設置複製素材庫↓=========================================*/
        for (int i=0;i<4;i++){
            arrayList.add("複製素材"+i);
        }
        ArrayAdapter adapter
                = new ArrayAdapter(this,android.R.layout.simple_list_item_1,arrayList);
        listView.setAdapter(adapter);
/**=========================================設置複製素材庫↑=========================================*/

        //ListView素材庫長點擊處理
        listView.setOnItemLongClickListener((parent, view, position, id)->{
            Vibrator myVibrator = (Vibrator) getApplication()//取得震動
                    .getSystemService(Service.VIBRATOR_SERVICE);
            myVibrator.vibrate(50);
            clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
            clipData = ClipData.newPlainText(null,arrayList.get(position));
            clipboard.setPrimaryClip(clipData);
            Toast.makeText(this, "已複製: " + arrayList.get(position)
                    , Toast.LENGTH_SHORT).show();

            return false;
        });

        //EditText長點擊處理
        editText.setOnLongClickListener((v -> {
            Vibrator myVibrator = (Vibrator) getApplication()//取得震動
                    .getSystemService(Service.VIBRATOR_SERVICE);
            myVibrator.vibrate(50);

            try {//如果未複製任何字就施行貼上,會導致程式閃退
                ClipData word = clipboard.getPrimaryClip();
                ClipData.Item item = word.getItemAt(0);
                String text = item.getText().toString();
                editText.setText(editText.getText().toString()+text);
                Toast.makeText(this, "已貼上: " + text, Toast.LENGTH_SHORT).show();
            }catch (Exception e){
                Toast.makeText(this, "未複製任何字串", Toast.LENGTH_SHORT).show();
            }
            return true;
        }));

        clear.setOnClickListener(v -> {editText.setText("");});//清除Edittext內字串

    }//EndOnCreate

}

 

幾個顏色部分講解

  1. 淺紅是onCreate範圍,沒什麼意義
  2. 綠色是全域變數
  3. 紫色是使用震動

然後再來詳細看一下複製與貼上的程式碼

複製:

clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipData = ClipData.newPlainText(null,arrayList.get(position));
clipboard.setPrimaryClip(clipData);

clipboard的部分是我有在全域變數中(綠色)宣告過的ClipboardManager

以及存放clipData的變數以樣是在全域變數中(綠色)宣告過的ClipData

最後再細看第二行

clipData = ClipData.newPlainText(null,arrayList.get(position));

的部分,紅字的部分是用來存放字串的;官網有寫如果想存放位址(URI)或Intent

可以向官網這個示範

https://developer.android.com/guide/topics/text/copy-paste?hl=zh_cn#Copying

Text官網示範:

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

URL官網示範:

// 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);

最後解釋一下,在我的示範中,前面那個是null

clipData = ClipData.newPlainText(null,arrayList.get(position));

那這又是什麼?其實這個就有點接近索引標籤

假設A區域複製的東西只能貼在A區域內容

那你的索引就把它設置為A區域的代號

這樣就可以實現在特定區域貼上特定區域的複製內容了(´・з・)

貼上:

ClipData word = clipboard.getPrimaryClip();
ClipData.Item item = word.getItemAt(0);
String text = item.getText().toString();

邏輯事先取得剪貼簿內的陣列(他存在ClipBoard內)

然後以ClipData.Item儲存取得的內容

最後在將它轉型為字串String釋出

請注意這整取出方法跟取陣列特定值的原理是一致的

因此若取出值是空,那就會閃退回報空值指針異常

要特別注意了(・ω・)b

最後將取得到的字放入EditText內,按下執行,就能得出想要的效果囉(・ωー)~☆

Gif_20200201131814364_by_gifguru


結語

講個笑話,其實大部分的使用者直接用手機內建的就好(´・_・`)

不過值得開心的是,按照我的這個方法其實他的剪貼簿可以與手機內建的共用

因此某些程度上來說,只要撰寫ListView的點擊事件基本上就萬事大吉了XD

那麼今天的範例到此,希望對你有幫助

喜歡我的文章可以將我的部落格網頁加入瀏覽器的標籤頁哦!掰逼!

arrow
arrow

    碼農日常 發表在 痞客邦 留言(2) 人氣()