技術の説明とケーススタディ
ドラッグアンドドロップ中のデータ転送には、ClipDataクラスとDragEventクラスが使用されます。 ドラッグアンドドロップ操作が初期化されるアプリケーションでは、データはClipDataを使用してパックされます。 ClipDataは、送信データの1つ以上のインスタンスを含む複合型です。 ClipDataは、クリップボードにデータを配置するために使用されます。 ドラッグアンドドロップには次のデータタイプを使用できます。
-MIMETYPE_TEXT_HTML:HTMLテキストの送信に必要。
-MIMETYPE_TEXT_INTENT:インテントを送信するために必要です。
-MIMETYPE_TEXT_PLAIN:プレーンテキストの送信に必要。
-MIMETYPE_TEXT_URILIST:URLを渡すために必要です。
レシーバーアプリケーションでは、ドラッグアンドドロップリスナーが対応するインターフェイス要素にインストールされ、DragEventイベントを受け取ります。
ドラッグアンドドロップ機能の使用例を見てみましょう。 この例には、初期化子(DragNDropExample)とドラッグレシーバー(DragNDropReceiver)の2つのアプリケーションが示されています。
アプリケーションをマルチウィンドウモードで表示するには、AndroidManifestの[アプリケーションまたはアクティビティ]セクションで次のパラメーターを設定する必要があります。
<activity … android:resizeableActivity="true" … </activity>
DragNDropExampleアプリケーションは、画像とテキストのドラッグアンドドロップを実装します。 イメージファイルは、ダウンロードフォルダーに保存されます。 画像を別のプロセスにドラッグすると、画像ファイルのURIが渡されます。 ドラッグアンドドロップの初期化は、対応する要素を長押しすることで行われます。
長押しのリスナーを設定します。
imageView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { File downloadFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); String[] filNames = downloadFolder.list();
別のプロセスに転送するためのファイルURIを取得します。 Androidの新しいバージョンでは、マルチメディアフォルダーにあるファイルにアクセスするには、FileProviderを使用する必要があります。
Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", new File(downloadFolder, filNames[0]));
ClipDataオブジェクトを作成し、それにURIをパックします。 ClipDataオブジェクトの作成時に、パックデータのタイプが示されます。 タイプMIMETYPE_TEXT_URILISTは、uriがパッケージ化されていることを示します。
ClipData.Item item = new ClipData.Item(uri); ClipData clip = new ClipData("text", new String[]{ ClipDescription.MIMETYPE_TEXT_URILIST}, item);
ClipDataオブジェクト、dragShadowBuilderオブジェクトを渡し、適切なフラグを設定して、ドラッグアンドドロップを初期化します。 View.DRAG_FLAG_GLOBALフラグを使用すると、操作間でドラッグアンドドロップできます。 View.DRAG_FLAG_GLOBAL_URI_READフラグとView.DRAG_FLAG_GLOBAL_URI_WRITEフラグは、それぞれURIの読み取りと書き込みを許可します。 DragShadowBuilderは、ドラッグ時に影を作成するために使用されます。 この例では、影はインターフェイス要素そのものです。
View.DragShadowBuilder dragShadowBuilder = new View.DragShadowBuilder(view); imageView.startDragAndDrop(clip, dragShadowBuilder, null, View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ | View.DRAG_FLAG_GLOBAL_URI_WRITE); return true; } });
同様に、すべてがテキストのドラッグアンドドロップに発生します。
textView = (TextView) findViewById(R.id.text_view); textView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { ClipData.Item item = new ClipData.Item(textView.getText()); ClipData clip = new ClipData("text", new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN}, item); View.DragShadowBuilder dragShadowBuilder = new View.DragShadowBuilder(view); textView.startDragAndDrop(clip, dragShadowBuilder, null, View.DRAG_FLAG_GLOBAL); return true; } });
受信側アプリケーションには、OnDragListenerリスナーがインストールされます。
imageView.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) {
リスナーは、特定のドラッグアンドドロップイベントのアクションを設定します。 この例では、次のイベントに対してアクションが設定されます。
-ACTION_DRAG_STARTED:ドラッグアンドドロップが開始されました。
-ACTION_DROP:ユーザーはドラッグされたアイテムをリリースしました。
switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: Toast toast = Toast.makeText(getApplicationContext(), R.string.drop_started, Toast.LENGTH_SHORT); toast.show(); imageView.setBackgroundResource(R.color.grey_200); break; case DragEvent.ACTION_DROP: requestDragAndDropPermissions(event); ClipData.Item item = event.getClipData().getItemAt(0);
画像をImageViewのみに挿入し、それに応じてTextViewのテキストをチェックする必要があります。 このコードセクションでは、ドラッグされているデータのタイプがチェックされ、必要なデータと比較されます。
if (event.getClipDescription().getMimeType(0).equals(MIMETYPE_TEXT_URILIST)) { Uri uri = item.getUri(); imageView.setImageURI(uri); } } return true; } });
テキストをドラッグアンドドロップする場合、すべてが同じように行われます。
textView.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: Toast toast = Toast.makeText(getApplicationContext(), R.string.drop_started, Toast.LENGTH_SHORT); toast.show(); break; case DragEvent.ACTION_DROP: requestDragAndDropPermissions(event); ClipData.Item item = event.getClipData().getItemAt(0); if (event.getClipDescription().getMimeType(0).equals(MIMETYPE_TEXT_PLAIN)) { CharSequence text = item.getText(); textView.setText(text); } } return true; } });
以下は、ドラッグアンドドロップ中の画面のスクリーンショットです
画像をドラッグする過程で:
テキストと画像をドラッグした後:
おわりに
異なるプロセス間で情報をドラッグする機能により、アプリケーション間のデータ交換を高速化でき、ユーザーにとってより便利で視覚的になります。
参照資料
- 1. Googleの公式Drad-n-Dropドキュメントへのリンク
- 2. マルチウィンドウサポートに関するGoogleの公式ドキュメントへのリンク