Використання Drag-and-drop між різними Activity в Android 7 Nougat

У цій статті я хочу розповісти про нову можливість перетягувати дані між різними Activity в режимі спільного відображення, яка з'явилася з виходом Android 7 Nougat. Раніше перетягувати дані можна було тільки в рамках однієї Activity.

Опис технології і розбір прикладу
Для передачі даних при перетягуванні використовуються класи ClipData і DragEvent. В додатку, в якому ініціюється операція перетягування, дані упаковуються з допомогою ClipData. ClipData являє собою складний тип, що містить у собі один або кілька примірників переданих даних. ClipData використовується для розміщення даних у буфері обміну. Для перетягування доступні наступні типи даних:

— MIMETYPE_TEXT_HTML: необхідний для передачі HTML тексту;
— MIMETYPE_TEXT_INTENT: необхідний для передачі интента;
— MIMETYPE_TEXT_PLAIN: необхідний для передачі простого тексту;
— MIMETYPE_TEXT_URILIST: необхідний для передачі URL.
У додатку приймачі на відповідному елементі інтерфейсу встановлюється слухач перетягування, який приймає події DragEvent.

Давайте розглянемо приклад використання функції перетягування. У прикладі представлені два додатки: инициализатор (DragNDropExample) і приймач перетягування (DragNDropReceiver).

Для того, щоб додаток відображалося в багатовіконному режимі необхідно встановити в AndroidManifest в секції Application або Activity наступний параметр:

<activity
...
android:resizeableActivity="true"
...
</activity>


У додатку DragNDropExample реалізовано перетягування зображення і тексту. Файл зображення зберігається в папці Downloads. При перетягуванні зображення іншому процесу передається URI файлу зображення. Ініціалізація перетягування відбувається по довгому натисненню на відповідні елементи.

image
Встановлюємо слухач довгого натискання.

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

Нижче наведені скріншоти екрану в процесі перетягування
У процесі перетягування зображення:

image
Після перетягування тексту та зображення:

image

Висновок

Можливість перетягувати інформацію між різними процесами дозволяє прискорити обмін даними між додатками, зробити його більш зручним і наочним для користувача.

Посилання

  • 1. Посилання на офіційну документацію Google Drad-n-Drop
  • 2. Посилання на офіційну документацію Google про Multi-Window Support
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.