Çoklu pencere modunda sürükleyip bırakma

Android 7.0 (API düzeyi 24) veya sonraki sürümleri çalıştıran cihazlar, kullanıcıların verileri sürükleyip bırakarak bir uygulamadan diğerine taşımasına olanak tanıyan çoklu pencere modunu destekler.

Verileri, işlemin başladığı yer olan kaynak uygulama sağlar. Verileri, işlemin sona erdiği hedef uygulama alır.

Kullanıcı içeriği sürüklemeye başladığında kaynak uygulama, kullanıcının verileri başka bir uygulamaya sürükleyebileceğini belirtmek için DRAG_FLAG_GLOBAL işaretini ayarlamalıdır.

Veriler uygulama sınırları arasında hareket ettiğinden, uygulamalar verilere erişimi bir içerik URI'si kullanarak paylaşır. Bunun için aşağıdakiler gereklidir:

  • Kaynak uygulama, kaynak uygulamanın hedef uygulamaya vermek istediği veriler için okuma veya yazma erişimine bağlı olarak DRAG_FLAG_GLOBAL_URI_READ ve DRAG_FLAG_GLOBAL_URI_WRITE işaretlerinden birini ya da ikisini birden ayarlamalıdır.
  • Hedef uygulama, kullanıcının uygulamaya sürüklediği verileri işlemeden önce hemen requestDragAndDropPermissions() çağrısı yapmalıdır. Hedef uygulamanın sürüklenen verilere artık erişmesi gerekmiyorsa requestDragAndDropPermissions() kaynağından döndürülen nesnede release() yöntemini çağırabilir. Aksi takdirde, içeren etkinlik kaldırıldığında izinler serbest bırakılır. Uygulamanız, bırakılan URI'ların işlenmesi için yeni bir Etkinlik başlatmayı içeriyorsa yeni Etkinliğe aynı izinleri vermeniz gerekir. Klip verilerini ve bir bayrağı ayarlamanız gerekir:

    Kotlin

    intent.setClipData(clipData)
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    

    Java

    intent.setClipData(clipData);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    

Aşağıdaki kod snippet'leri, sürüklenen verilere kullanıcı bırakma işlemi gerçekleştikten hemen sonra salt okuma erişiminin nasıl serbest bırakılacağını gösterir. Daha kapsamlı bir örnek için GitHub'da Sürükle ve Bırak örneğine bakın.

Kaynak etkinlik

Kotlin

// Drag a file stored in an images/ directory in internal storage.
val internalImagesDir = File(context.filesDir, "images")
val imageFile = File(internalImagesDir, imageFilename)
val uri = FileProvider.getUriForFile(context, contentAuthority, imageFile)

val listener = OnDragStartListener@{ view: View, _: DragStartHelper ->
    val clipData = ClipData(ClipDescription("Image Description",
                                            arrayOf("image/*")),
                            ClipData.Item(uri))
    // Must include DRAG_FLAG_GLOBAL to permit dragging data between apps.
    // This example provides read-only access to the data.
    val flags = View.DRAG_FLAG_GLOBAL or View.DRAG_FLAG_GLOBAL_URI_READ
    return@OnDragStartListener view.startDragAndDrop(clipData,
                                                     View.DragShadowBuilder(view),
                                                     null,
                                                     flags)
}

// Container where the image originally appears in the source app.
val srcImageView = findViewById<ImageView>(R.id.imageView)

// Detect and start the drag event.
DragStartHelper(srcImageView, listener).apply {
    attach()
}

Java

// Drag a file stored in an images/ directory in internal storage.
File internalImagesDir = new File(context.getFilesDir(), "images");
File imageFile = new File(internalImagesDir, imageFilename);
final Uri uri = FileProvider.getUriForFile(context, contentAuthority, imageFile);

// Container where the image originally appears in the source app.
ImageView srcImageView = findViewById(R.id.imageView);

// Enable the view to detect and start the drag event.
new DragStartHelper(srcImageView, (view, helper) -> {
    ClipData clipData = new ClipData(new ClipDescription("Image Description",
                                                          new String[] {"image/*"}),
                                     new ClipData.Item(uri));
    // Must include DRAG_FLAG_GLOBAL to permit dragging data between apps.
    // This example provides read-only access to the data.
    int flags = View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ;
    return view.startDragAndDrop(clipData,
                                 new View.DragShadowBuilder(view),
                                 null,
                                 flags);
}).attach();

Hedef etkinlik

Kotlin

// Container where the image is to be dropped in the target app.
val targetImageView = findViewById<ImageView>(R.id.imageView)

targetImageView.setOnDragListener { view, event ->

    when (event.action) {

        ACTION_DROP -> {
            val imageItem: ClipData.Item = event.clipData.getItemAt(0)
            val uri = imageItem.uri

            // Request permission to access the image data being dragged into
            // the target activity's ImageView element.
            val dropPermissions = requestDragAndDropPermissions(event)
            (view as ImageView).setImageURI(uri)

            // Release the permission immediately afterward because it's no
            // longer needed.
            dropPermissions.release()
            return@setOnDragListener true
        }

        // Implement logic for other DragEvent cases here.

        // An unknown action type is received.
        else -> {
            Log.e("DragDrop Example", "Unknown action type received by View.OnDragListener.")
            return@setOnDragListener false
        }

    }
}

Java

// Container where the image is to be dropped in the target app.
ImageView targetImageView = findViewById(R.id.imageView);

targetImageView.setOnDragListener( (view, event) -> {

    switch (event.getAction()) {

        case ACTION_DROP:
            ClipData.Item imageItem = event.getClipData().getItemAt(0);
            Uri uri = imageItem.getUri();

            // Request permission to access the image data being dragged into
            // the target activity's ImageView element.
            DragAndDropPermissions dropPermissions =
                requestDragAndDropPermissions(event);

            ((ImageView)view).setImageURI(uri);

            // Release the permission immediately afterward because it's no
            // longer needed.
            dropPermissions.release();

            return true;

        // Implement logic for other DragEvent cases here.

        // An unknown action type was received.
        default:
            Log.e("DragDrop Example","Unknown action type received by View.OnDragListener.");
            break;
    }

    return false;
});