テキストを触っていると時々選択されてコピーできるようなメニューが現れますがこれは Text Sellection です。これを実装してみましょう。
2021.1.1
Text Sellection
テキストを検索するためにテキストをコピーするときに使うのが Text Sellection です。検索するときには重宝しますが
ActionMode
ActionMode はユーザーが操作していることに関連したメニューを表示したりしてくれる仕組みです。ユーザーがそれにより何かを選択した場合はCallbackを使って取り出します。
このTest Sellectionでは、簡単な方法としては既存のActionMode.CallbackをActionMode.Callback2に拡張変更します。
Context Menu – Android Dvelopers
サンプルコード
setCustomSelectionActionModeCallback をカスタマイズすることもできますが、そのままオーバーライドして、コピーした文字列のみを取り出すように簡略化したものです。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
//package your.package.name; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView textView, textCopied; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.text_view); textCopied = findViewById(R.id.text_copied); // TextViewにセットするテキスト文をResourceから取り出す textView.setText(R.string.info_text); // Text Selection をenableにする textView.setTextIsSelectable(true); textView.setCustomSelectionActionModeCallback(new ActionMode.Callback2(){ @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case android.R.id.copy: int min = 0; int max = textView.getText().length(); if (textView.isFocused()) { final int selStart = textView.getSelectionStart(); final int selEnd = textView.getSelectionEnd(); min = Math.max(0, Math.min(selStart, selEnd)); max = Math.max(0, Math.max(selStart, selEnd)); } final CharSequence selectedText = textView.getText() .subSequence(min, max); String text = selectedText.toString(); textCopied.setText(text); // ActionModeの終了 mode.finish(); return true; case android.R.id.cut: return true; case android.R.id.paste: return true; default: break; } return false; } @Override public void onDestroyActionMode(ActionMode mode) { } }); } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="20dp" android:background="#dff" tools:context=".MainActivity"> <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#00f" android:textSize="20sp" /> <!-- 画像は無くても大丈夫です --> <ImageView android:src="@drawable/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/description"/> <TextView android:id="@+id/text_copied" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:textColor="#f00" android:textSize="20sp" /> </LinearLayout> |
コピーする長文テキストですが、コード上にStringで設定してもいいのですがリソースにしてみました。
strings.xml
1 2 3 4 5 6 7 |
<resources> <string name="app_name">YourAppName</string> <string name="info_text">"When users select text in your app, you can now display text selection actions such as Cut, Copy, and Paste in a floating toolbar."</string> <string name="description">Aisha</string> </resources> |
上段の文字列の任意の範囲を選択して、copyを選択すると、画像下に選択した文字列が赤で表示されます。
サンプル動画
これはあくまでAndroid 6.0(API 23)以降の機能です
References:
Text Selection
ActionMode
ActionMode.C
allback2