lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Seret dan Lepas

Dengan kerangka kerja seret/lepas Android, Anda bisa memungkinkan pengguna memindah data dari satu Tampilan ke Tampilan lain dalam layout saat ini dengan menggunakan isyarat grafis seret dan lepas. Kerangka kerja ini berisi kelas kejadian seret, listener penyeretan, serta kelas dan metode helper.

Walaupun kerangka kerja ini terutama didesain untuk perpindahan data, Anda bisa menggunakannya untuk aksi UI lainnya. Misalnya, Anda bisa membuat aplikasi yang mencampur warna bila pengguna menyeret sebuah ikon warna di atas ikon lain. Akan tetapi, bagian selebihnya dari topik ini menjelaskan kerangka kerja dalam artian perpindahan data.

Ringkasan

Operasi seret dan lepas dimulai bila pengguna membuat semacam isyarat yang Anda kenal sebagai pertanda untuk mulai menyeret data. Sebagai respons, aplikasi Anda akan memberi tahu sistem bahwa penyeretan sedang dimulai. Panggilan sistem akan kembali ke aplikasi Anda untuk mengambil representasi data yang sedang diseret. Saat jari pengguna menggerakkan representasi ("bayangan penyeretan") di atas layout saat ini, sistem akan mengirim kejadian seret objek event listener penyeretan dan metode callback kejadian seret bersama objek View di layout. Setelah pengguna melepas bayangan penyeretan, sistem akan mengakhiri operasi seret.

Anda membuat objek event listener penyeretan ("listener") dari kelas yang mengimplementasikan View.OnDragListener. Anda menyetel objek event listener penyeretan untuk Tampilan dengan metode setOnDragListener() objek Tampilan. Setiap objek Tampilan juga memiliki metode callback onDragEvent(). Keduanya dijelaskan lebih detail di bagian Event listener penyeretan dan metode callback.

Catatan: Demi kemudahan, bagian-bagian berikut merujuk ke rutin yang menerima kejadian seret sebagai "event listener penyeretan", walaupun sebenarnya berupa metode callback.

Saat memulai penyeretan, Anda menyertakan data yang akan dipindah dan metadata yang menjelaskan data ini sebagai bagian dari panggilan ke sistem. Selama penyeretan, sistem akan mengirim kejadian seret ke event listener penyeretan atau metode callback setiap Tampilan dalam layout. Listener atau metode callback bisa menggunakan metadata tersebut untuk memutuskan apakah ingin menerima data tersebut bila dilepaskan. Jika pengguna melepaskan data di atas objek Tampilan, dan listener atau metode callback objek Tampilan itu sebelumnya telah memberi tahu sistem bahwa ia ingin menerima pelepasan itu, maka sistem akan mengirim data tersebut ke listener atau metode callback di kejadian seret.

Aplikasi Anda akan memberi tahu sistem untuk memulai penyeretan dengan memanggil metode startDrag(). Hal ini akan memberi tahu sistem untuk mulai mengirim kejadian seret. Metode ini juga mengirim data yang sedang Anda seret.

Anda bisa memanggil startDrag() untuk Tampilan yang dilampirkan dalam layout saat ini. Sistem hanya menggunakan objek Tampilan untuk mendapatkan akses ke setelan global di layout Anda.

Setelah aplikasi Anda memanggil startDrag(), bagian selebihnya dari proses ini akan menggunakan kejadian yang dikirim sistem ke objek Tampilan dalam layout saat ini.

Proses seret/lepas

Pada dasarnya ada empat langkah atau status dalam proses seret dan lepas:

Dimulai
Sebagai respons terhadap isyarat pengguna untuk memulai penyeretan, aplikasi Anda akan memanggil startDrag() untuk memberi tahu sistem agar memulai penyeretan. Argumen startDrag() menyediakan data yang akan diseret, metadata untuk data ini, dan callback untuk menggambar bayangan penyeretan.

Sistem terlebih dahulu akan merespons dengan memanggil kembali ke aplikasi untuk mendapatkan bayangan penyeretan. Sistem kemudian menampilkan bayangan penyeretan pada perangkat.

Berikutnya, sistem akan mengirim kejadian seret dengan tipe aksi ACTION_DRAG_STARTED ke event listener penyeretan untuk semua objek Tampilan dalam layout saat ini. Untuk melanjutkan penerimaan kejadian seret, termasuk kemungkinan kejadian lepas, event listener penyeretan harus mengembalikan true. Ini akan mendaftarkan listener pada sistem. Hanya listener terdaftar yang melanjutkan untuk menerima kejadian seret. Pada poin ini, listener juga bisa mengubah penampilan objek Tampilan untuk menunjukkan bahwa listener bisa menerima kejadian lepas.

Jika event listener penyeretan mengembalikan false, maka ia tidak akan menerima kejadian seret untuk operasi saat ini hingga sistem mengirim kejadian seret bersama tipe aksi ACTION_DRAG_ENDED. Dengan mengirim false, listener memberi tahu sistem bahwa ia tidak tertarik dengan operasi seret dan tidak ingin menerima data yang diseret.

Melanjutkan
Pengguna melanjutkan penyeretan. Saat bayangan penyeretan berpotongan dengan kotak pembatas objek Tampilan sistem akan mengirim satu atau beberapa kejadian seret ke event listener penyeretan objek Tampilan (jika telah didaftarkan untuk menerima kejadian). Listener dapat memilih apakah akan mengubah penampilan objek Tampilannya sebagai respons terhadap kejadian. Misalnya, jika kejadian menunjukkan bahwa bayangan penyeretan telah memasuki kotak pembatas Tampilan (tipe aksi ACTION_DRAG_ENTERED), listener bisa bereaksi dengan menyoroti Tampilannya.
Dilepaskan
Pengguna melepaskan bayangan penyeretan dalam kotak pembatas Tampilan yang bisa menerima data. Sistem akan mengirimi listener objek Tampilan sebuah kejadian seret dengan tipe aksi ACTION_DROP. Kejadian seret berisi data yang telah diteruskan ke sistem dalam panggilan ke startDrag() yang telah memulai operasi. Listener diharapkan untuk mengembalikan boolean true ke sistem jika kode untuk menerima pelepasan tersebut berhasil.

Perhatikan, langkah ini hanya terjadi jika pengguna melepaskan bayangan penyeretan dalam kotak pembatas Tampilan yang listener-nya telah didaftarkan untuk menerima kejadian seret. Jika pengguna melepaskan bayangan penyeretan dalam situasi lain, maka tidak ada kejadian seret ACTION_DROP yang dikirim.

Diakhiri
Setelah pengguna melepaskan bayangan penyeretan, dan setelah sistem mengirim (jika perlu) kejadian seret bersama tipe aksi ACTION_DROP, sistem akan mengirim kejadian seret bersama tipe aksi ACTION_DRAG_ENDED untuk menunjukkan bahwa operasi seret telah selesai. Ini telah selesai tidak peduli di mana pengguna melepaskan bayangan penyeretan. Kejadian dikirim ke setiap listener yang telah didaftarkan untuk menerima kejadian seret, sekalipun listener menerima kejadian ACTION_DROP.

Masing-masing dari keempat langkah ini dijelaskan lebih detail di bagian Mendesain Operasi Seret dan Lepas.

Event listener penyeretan dan metode callback

Sebuah Tampilan menerima kejadian seret bersama event listener penyeretan yang mengimplementasikan View.OnDragListener atau bersama metode callback onDragEvent(DragEvent). Bila sistem memanggil metode atau listener, sistem akan meneruskan objek DragEvent ke sana.

Mungkin Anda akan menggunakan listener dalam banyak kasus. Bila mendesain UI, Anda biasanya tidak menjadikan kelas-kelas Tampilan sebagai subkelas, namun menggunakan metode callback akan memaksa Anda untuk melakukan hal ini agar dapat mengganti metode. Sebagai perbandingan, Anda bisa mengimplementasikan satu kelas listener kemudian menggunakannya bersama sejumlah objek Tampilan yang berbeda. Anda juga bisa mengimplementasikannya sebagai kelas inline anonim. Untuk menyetel listener objek Tampilan, panggil setOnDragListener().

Anda bisa memiliki listener maupun metode callback untuk objek Tampilan. Jika ini terjadi, sistem akan memanggil listener terlebih dahulu. Sistem tidak memanggil metode callback kecuali jika listener mengembalikan false.

Kombinasi metode onDragEvent(DragEvent) dan View.OnDragListener analog dengan kombinasi onTouchEvent() dan View.OnTouchListener yang digunakan bersama kejadian sentuh.

Kejadian seret

Sistem akan mengirim kejadian seret dalam bentuk objek DragEvent. Objek berisi tipe aksi yang memberi tahu listener apa yang terjadi dalam proses seret/lepaskan. Objek berisi data lainnya, bergantung pada tipe aksi.

Untuk mendapatkan tipe aksi, listener memanggil getAction(). Ada enam kemungkinan nilai, yang didefinisikan oleh konstanta dalam kelas DragEvent. Semua ini dicantumkan dalam tabel 1.

Objek DragEvent juga berisi data yang disediakan aplikasi Anda ke sistem dalam panggilan ke startDrag(). Sebagian data hanya berlaku untuk tipe aksi tertentu. Data yang berlaku untuk setiap tipe aksi dirangkum dalam tabel 2. Juga dijelaskan secara detail bersama kejadian yang valid untuk data tersebut di bagian Mendesain Operasi Seret dan Lepas.

Tabel 1. Tipe aksi DragEvent

Nilai getAction() Arti
ACTION_DRAG_STARTED Sebuah event listener penyeretan objek Tampilan menerima tipe aksi kejadian ini tepat setelah aplikasi memanggil startDrag() dan mendapatkan bayangan penyeretan.
ACTION_DRAG_ENTERED Sebuah event listener penyeretan objek Tampilan menerima tipe aksi kejadian ini bila bayangan penyeretan baru saja memasuki kotak pembatas Tampilan. Ini adalah tipe aksi kejadian pertama yang diterima listener bila bayangan penyeretan memasuki kotak pembatas. Jika listener ingin melanjutkan penerimaan kejadian seret untuk operasi ini, ia harus mengembalikan boolean true ke sistem.
ACTION_DRAG_LOCATION Sebuah event listener penyeretan objek Tampilan menerima tipe aksi kejadian ini setelah ia menerima kejadian ACTION_DRAG_ENTERED saat jendela penyeretan masih dalam kotak pembatas Tampilan.
ACTION_DRAG_EXITED Sebuah event listener penyeretan objek Tampilan menerima tipe aksi kejadian ini setelah ia menerima ACTION_DRAG_ENTERED dan setidaknya satu kejadian ACTION_DRAG_LOCATION, dan setelah pengguna memindah jendela penyeretan ke luar kotak pembatas Tampilan.
ACTION_DROP Sebuah event listener penyeretan objek Tampilan menerima tipe aksi kejadian ini bila pengguna melepaskan jendela penyeretan di atas objek Tampilan. Tipe aksi ini hanya dikirim ke listener objek Tampilan jika listener mengembalikan boolean true sebagai respons terhadap kejadian seret ACTION_DRAG_STARTED. Tipe aksi ini tidak dikirim jika pengguna melepaskan bayangan penyeretan pada Tampilan yang listener-nya tidak terdaftar, atau jika pengguna melepaskan bayangan penyeretan pada sesuatu yang bukan menjadi bagian layout saat ini.

Listener diharapkan untuk mengembalikan boolean true jika berhasil memproses pelepasan. Jika tidak maka ia harus mengembalikan false.

ACTION_DRAG_ENDED Sebuah event listener penyeretan objek Tampilan menerima tipe aksi kejadian ini bila sistem mengakhiri operasi seret. Tipe aksi ini tidak harus didahului oleh kejadian ACTION_DROP. Jika sistem mengirim sebuah ACTION_DROP, menerima tipe aksi ACTION_DRAG_ENDED tidak akan menyiratkan bahwa operasi pelepasan berhasil. Listener harus memanggil getResult() untuk mendapatkan nilai yang telah dikembalikan sebagai respons terhadap ACTION_DROP. Jika sebuah kejadian ACTION_DROP belum dikirim, maka getResult() akan mengembalikan false.

Tabel 2. Data DragEvent yang valid oleh tipe aksi

Nilai getAction() Nilai getClipDescription() Nilai getLocalState() Nilai getX() Nilai getY() Nilai getClipData() Nilai getResult()
ACTION_DRAG_STARTED X X X      
ACTION_DRAG_ENTERED X X X X    
ACTION_DRAG_LOCATION X X X X    
ACTION_DRAG_EXITED X X        
ACTION_DROP X X X X X  
ACTION_DRAG_ENDED X X       X

Metode getAction(), describeContents(), writeToParcel(), dan toString() selalu mengembalikan data yang valid.

Jika sebuah metode tidak berisi data yang valid untuk tipe aksi tertentu, ia akan mengembalikan null atau 0, bergantung pada tipe hasilnya.

Bayangan penyeretan

Selama operasi seret dan lepas, sistem akan menampilkan gambar yang diseret pengguna. Untuk perpindahan data, gambar ini mewakili data yang sedang diseret. Untuk operasi lainnya, gambar ini mewakili sebagian aspek operasi seret.

Gambar ini disebut bayangan penyeretan. Anda membuatnya dengan beberapa metode yang dideklarasikan untuk objek View.DragShadowBuilder, kemudian meneruskannya ke sistem bila Anda mulai menyeret menggunakan startDrag(). Sebagai bagian dari responsnya terhadap startDrag(), sistem memanggil metode callback yang Anda definisikan dalam View.DragShadowBuilder untuk memperoleh bayangan penyeretan.

Kelas View.DragShadowBuilder memiliki dua konstruktor:

View.DragShadowBuilder(View)
Konstruktor ini menerima semua objek View aplikasi. Konstruktor menyimpan objek Tampilan dalam objek View.DragShadowBuilder, jadi selama callback Anda bisa mengaksesnya saat Anda membangun bayangan penyeretan. Ia tidak harus dikaitkan dengan Tampilan (jika ada) yang dipilih pengguna untuk memulai operasi penyeretan.

Jika Anda menggunakan proses ini konstruktor, Anda tidak harus memperluas View.DragShadowBuilder atau mengganti metodenya. Secara default, Anda akan mendapatkan bayangan penyeretan yang sama penampilannya dengan Tampilan yang Anda teruskan sebagai argumen, dipusatkan di bawah lokasi pengguna menyentuh layar.

View.DragShadowBuilder()
Jika Anda menggunakan konstruktor ini, tidak ada objek Tampilan yang tersedia dalam objek View.DragShadowBuilder (bidang ini disetel ke null). Jika Anda menggunakan konstruktor ini, dan tidak memperluas View.DragShadowBuilder atau mengganti metodenya, Anda akan mendapatkan bayangan penyeretan yang tak terlihat. Sistem tidak memberikan kesalahan.

Kelas View.DragShadowBuilder memiliki dua metode:

onProvideShadowMetrics()
Sistem akan segera memanggil metode ini setelah Anda memanggil startDrag(). Gunakan ini untuk mengirim dimensi dan titik sentuh bayangan penyeretan ke sistem. Metode ini memiliki dua argumen:
dimensions
Objek Point. Lebar bayangan penyeretan ada di x dan tingginya ada di y.
touch_point
Objek Point. Titik sentuh adalah lokasi dalam bayangan penyeretan yang harus berada di bawah jari pengguna selama penyeretan. Posisi X ada di x dan posisi Y ada di y
onDrawShadow()
Begitu selesai memanggil onProvideShadowMetrics() sistem akan memanggil onDrawShadow() untuk mendapatkan bayangan penyeretan itu sendiri. Metode ini memiliki argumen tunggal, sebuah objek Canvas yang dibangun sistem dari parameter yang Anda sediakan dalam onProvideShadowMetrics() Gunakan ini untuk menggambar bayangan penyeretan dalam objek Canvas yang disediakan.

Untuk meningkatkan kinerja, Anda harus mempertahankan ukuran bayangan penyeretan agar tetap kecil. Untuk item tunggal, Anda mungkin perlu menggunakan ikon. Untuk multi-pilihan, Anda mungkin perlu menggunakan beberapa ikon dalam satu tumpukan daripada beberapa gambar penuh yang tersebar di seluruh layar.

Mendesain Operasi Seret dan Lepas

Bagian ini menunjukkan langkah-demi-langkah bagaimana memulai penyeretan, cara merespons kejadian selama penyeretan, cara merespons kejadian lepas, dan cara mengakhiri operasi seret dan lepas.

Memulai penyeretan

Pengguna memulai penyeretan dengan isyarat menyeret, biasanya dengan menekan lama, pada objek Tampilan. Sebagai respons, Anda harus melakukan yang berikut ini:

  1. Bila perlu, buat ClipData dan ClipData.Item untuk data yang sedang dipindahkan. Sebagai bagian dari objek ClipData, pasok metadata yang disimpan di objek ClipDescription dalam ClipData. Untuk operasi seret dan lepas yang tidak mewakili perpindahan data, Anda mungkin perlu menggunakan null sebagai ganti objek sesungguhnya.

    Misalnya, cuplikan kode ini menunjukkan cara merespons penekanan lama pada ImageView dengan membuat objek ClipData berisi tag atau label ImageView. Setelah cuplikan ini, cuplikan berikutnya menunjukkan cara mengganti metode dalam View.DragShadowBuilder:

    // Create a string for the ImageView label
    private static final String IMAGEVIEW_TAG = "icon bitmap"
    
    // Creates a new ImageView
    ImageView imageView = new ImageView(this);
    
    // Sets the bitmap for the ImageView from an icon bit map (defined elsewhere)
    imageView.setImageBitmap(mIconBitmap);
    
    // Sets the tag
    imageView.setTag(IMAGEVIEW_TAG);
    
        ...
    
    // Sets a long click listener for the ImageView using an anonymous listener object that
    // implements the OnLongClickListener interface
    imageView.setOnLongClickListener(new View.OnLongClickListener() {
    
        // Defines the one method for the interface, which is called when the View is long-clicked
        public boolean onLongClick(View v) {
    
        // Create a new ClipData.
        // This is done in two steps to provide clarity. The convenience method
        // ClipData.newPlainText() can create a plain text ClipData in one step.
    
        // Create a new ClipData.Item from the ImageView object's tag
        ClipData.Item item = new ClipData.Item(v.getTag());
    
        // Create a new ClipData using the tag as a label, the plain text MIME type, and
        // the already-created item. This will create a new ClipDescription object within the
        // ClipData, and set its MIME type entry to "text/plain"
        ClipData dragData = new ClipData(v.getTag(),ClipData.MIMETYPE_TEXT_PLAIN,item);
    
        // Instantiates the drag shadow builder.
        View.DragShadowBuilder myShadow = new MyDragShadowBuilder(imageView);
    
        // Starts the drag
    
                v.startDrag(dragData,  // the data to be dragged
                            myShadow,  // the drag shadow builder
                            null,      // no need to use local data
                            0          // flags (not currently used, set to 0)
                );
    
        }
    }
    
  2. Cuplikan kode berikut ini mendefinisikan myDragShadowBuilder Cuplikan ini membuat bayangan penyeretan untuk menyeret TextView sebagai persegi panjang abu-abu kecil:
        private static class MyDragShadowBuilder extends View.DragShadowBuilder {
    
        // The drag shadow image, defined as a drawable thing
        private static Drawable shadow;
    
            // Defines the constructor for myDragShadowBuilder
            public MyDragShadowBuilder(View v) {
    
                // Stores the View parameter passed to myDragShadowBuilder.
                super(v);
    
                // Creates a draggable image that will fill the Canvas provided by the system.
                shadow = new ColorDrawable(Color.LTGRAY);
            }
    
            // Defines a callback that sends the drag shadow dimensions and touch point back to the
            // system.
            @Override
            public void onProvideShadowMetrics (Point size, Point touch) {
                // Defines local variables
                private int width, height;
    
                // Sets the width of the shadow to half the width of the original View
                width = getView().getWidth() / 2;
    
                // Sets the height of the shadow to half the height of the original View
                height = getView().getHeight() / 2;
    
                // The drag shadow is a ColorDrawable. This sets its dimensions to be the same as the
                // Canvas that the system will provide. As a result, the drag shadow will fill the
                // Canvas.
                shadow.setBounds(0, 0, width, height);
    
                // Sets the size parameter's width and height values. These get back to the system
                // through the size parameter.
                size.set(width, height);
    
                // Sets the touch point's position to be in the middle of the drag shadow
                touch.set(width / 2, height / 2);
            }
    
            // Defines a callback that draws the drag shadow in a Canvas that the system constructs
            // from the dimensions passed in onProvideShadowMetrics().
            @Override
            public void onDrawShadow(Canvas canvas) {
    
                // Draws the ColorDrawable in the Canvas passed in from the system.
                shadow.draw(canvas);
            }
        }
    

    Catatan: Ingatlah bahwa Anda tidak harus memperluas View.DragShadowBuilder. Konstruktor View.DragShadowBuilder(View) akan membuat bayangan penyeretan default yang sama ukurannya dengan argumen Tampilan yang diteruskan kepadanya, dengan titik sentuh yang berpusat dalam bayangan penyeretan.

Merespons awal penyeretan

Selama operasi penyeretan, sistem akan menugaskan kejadian seret ke event listener penyeretan objek Tampilan dalam layout saat ini. Listener akan beraksi dengan memanggil getAction() untuk mendapatkan tipe aksi. Pada awal penyeretan, metode ini akan mengembalikan ACTION_DRAG_STARTED.

Sebagai respons terhadap kejadian dengan tipe aksi ACTION_DRAG_STARTED, listener harus melakukan yang berikut ini:

  1. Panggil getClipDescription() untuk mendapatkan ClipDescription. Gunakan metode tipe MIME di ClipDescription untuk melihat apakah listener bisa menerima data yang sedang diseret.

    Jika operasi seret dan lepas tidak mewakili perpindahan data, hal ini mungkin tidak diperlukan.

  2. Jika listener bisa merima pelepasan, ia akan mengembalikan true. Ini akan memberi tahu sistem untuk melanjutkan mengirim kejadian seret ke listener. Jika tidak bisa menerima pelepasan, ia akan mengembalikan false, dan sistem akan menghentikan pengiriman kejadian seret hingga sistem mengirim ACTION_DRAG_ENDED.

Perhatikan, untuk kejadian ACTION_DRAG_STARTED, metode DragEvent berikut ini tidak valid: getClipData(), getX(), getY(), dan getResult().

Menangani kejadian selama penyeretan

Selama penyeretan, listener yang mengembalikan true sebagai respons terhadap kejadian seret ACTION_DRAG_STARTED akan terus menerima kejadian seret. Tipe kejadian seret yang diterima listener selama penyeretan bergantung pada lokasi bayangan penyeretan dan visibilitas Tampilan listener.

Selama penyeretan, listener terutama akan menggunakan kejadian seret untuk memutuskan apakah akan mengubah penampilan Tampilannya.

Selama penyeretan, getAction() mengembalikan salah satu dari tiga nilai:

Listener tidak perlu bereaksi pada salah satu tipe aksi ini. Jika listener mengembalikan sebuah nilai ke sistem, nilai itu akan diabaikan. Inilah beberapa panduan untuk merespons setiap tipe aksi ini:

  • Sebagai respons terhadap ACTION_DRAG_ENTERED atau ACTION_DRAG_LOCATION, listener bisa mengubah penampilan Tampilan untuk menunjukkan bahwa ia sedang menerima pelepasan.
  • Sebuah kejadian dengan tipe aksi ACTION_DRAG_LOCATION berisi data yang valid untuk getX() dan getY(), yang menyangkut lokasi titik sentuh. Listener mungkin perlu menggunakan informasi ini untuk mengubah penampilan bagian itu pada Tampilan yaitu pada titik sentuh. Listener juga bisa menggunakan informasi ini untuk menentukan posisi persis untuk tempat pengguna akan melepaskan bayangan penyeretan.
  • Sebagai respons terhadap ACTION_DRAG_EXITED, listener akan menyetel ulang perubahan penampilan yang diterapkannya sebagai respons terhadap ACTION_DRAG_ENTERED atau ACTION_DRAG_LOCATION. Ini menunjukkan pada pengguna bahwa Tampilan tersebut tidak lagi menjadi target pelepasan yang segera terjadi.

Merespons pelepasan

Bila pengguna melepaskan bayangan penyeretan pada Tampilan dalam aplikasi, dan Tampilan itu sebelumnya telah melaporkan bahwa ia bisa menerima materi yang sedang diseret, sistem akan menugaskan kejadian seret ke Tampilan itu bersama tipe aksi ACTION_DROP. Listener akan melakukan yang berikut ini:

  1. Memanggil getClipData() untuk mendapatkan objek ClipData yang semula disediakan dalam panggilan ke startDrag() dan menyimpannya. Jika operasi seret dan lepas tidak mewakili perpindahan data, hal ini mungkin tidak diperlukan.
  2. Mengembalikan boolean true untuk menunjukkan bahwa pelepasan telah berhasil diproses, atau boolean false jika tidak berhasil. Nilai yang dikembalikan menjadi nilai yang dikembalikan oleh getResult() untuk kejadian ACTION_DRAG_ENDED.

    Perhatikan, jika sistem tidak mengirim kejadian ACTION_DROP, nilai getResult() untuk kejadian ACTION_DRAG_ENDED adalah false.

Untuk kejadian ACTION_DROP, getX() dan getY() akan mengembalikan posisi X dan Y dari titik penyeretan pada saat pelepasan, dengan menggunakan sistem koordinat Tampilan yang menerima pelepasan.

Sistem tidak memungkinkan pengguna melepaskan bayangan penyeretan pada Tampilan yang listener-nya tidak menerima kejadian seret. Sistem juga akan memungkinkan pengguna melepaskan bayangan penyeretan pada daerah kosong di UI aplikasi, atau pada area di luar aplikasi Anda. Di semua kasus ini, sistem tidak mengirim kejadian bersama tipe aksi ACTION_DROP, walaupun ia mengirim kejadian ACTION_DRAG_ENDED.

Merespons akhir penyeretan

Begitu pengguna melepaskan bayangan penyeretan, sistem akan mengirim kejadian seret ke semua event listener penyeretan dalam aplikasi Anda, bersama tipe aksi ACTION_DRAG_ENDED. Ini menunjukkan bahwa operasi penyeretan telah selesai.

Setiap listener akan melakukan yang berikut ini:

  1. Jika listener mengubah penampilan objek Tampilannya selama operasi, ia akan menyetel ulang Tampilan ke penampilan default-nya. Ini adalah petunjuk visual kepada pengguna bahwa operasi telah selesai.
  2. Listener secara opsional bisa memanggil getResult() untuk mengetahui selengkapnya tentang operasi tersebut. Jika listener mengembalikan true sebagai respons terhadap kejadian tipe aksi ACTION_DROP, maka getResult() akan mengembalikan boolean true. Di semua kasus lainnya, getResult() akan mengembalikan boolean false, termasuk bila sistem tidak mengirim kejadian ACTION_DROP.
  3. Listener akan mengembalikan boolean true ke sistem.

Merespons kejadian seret: sebuah contoh

Semua kejadian seret mula-mula diterima oleh metode atau listener kejadian seret. Cuplikan kode berikut adalah contoh sederhana dari reaksi terhadap kejadian seret di listener:

// Creates a new drag event listener
mDragListen = new myDragEventListener();

View imageView = new ImageView(this);

// Sets the drag event listener for the View
imageView.setOnDragListener(mDragListen);

...

protected class myDragEventListener implements View.OnDragListener {

    // This is the method that the system calls when it dispatches a drag event to the
    // listener.
    public boolean onDrag(View v, DragEvent event) {

        // Defines a variable to store the action type for the incoming event
        final int action = event.getAction();

        // Handles each of the expected events
        switch(action) {

            case DragEvent.ACTION_DRAG_STARTED:

                // Determines if this View can accept the dragged data
                if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {

                    // As an example of what your application might do,
                    // applies a blue color tint to the View to indicate that it can accept
                    // data.
                    v.setColorFilter(Color.BLUE);

                    // Invalidate the view to force a redraw in the new tint
                    v.invalidate();

                    // returns true to indicate that the View can accept the dragged data.
                    return true;

                }

                // Returns false. During the current drag and drop operation, this View will
                // not receive events again until ACTION_DRAG_ENDED is sent.
                return false;

            case DragEvent.ACTION_DRAG_ENTERED:

                // Applies a green tint to the View. Return true; the return value is ignored.

                v.setColorFilter(Color.GREEN);

                // Invalidate the view to force a redraw in the new tint
                v.invalidate();

                return true;

            case DragEvent.ACTION_DRAG_LOCATION:

                // Ignore the event
                return true;

            case DragEvent.ACTION_DRAG_EXITED:

                // Re-sets the color tint to blue. Returns true; the return value is ignored.
                v.setColorFilter(Color.BLUE);

                // Invalidate the view to force a redraw in the new tint
                v.invalidate();

                return true;

            case DragEvent.ACTION_DROP:

                // Gets the item containing the dragged data
                ClipData.Item item = event.getClipData().getItemAt(0);

                // Gets the text data from the item.
                dragData = item.getText();

                // Displays a message containing the dragged data.
                Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG);

                // Turns off any color tints
                v.clearColorFilter();

                // Invalidates the view to force a redraw
                v.invalidate();

                // Returns true. DragEvent.getResult() will return true.
                return true;

            case DragEvent.ACTION_DRAG_ENDED:

                // Turns off any color tinting
                v.clearColorFilter();

                // Invalidates the view to force a redraw
                v.invalidate();

                // Does a getResult(), and displays what happened.
                if (event.getResult()) {
                    Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG);

                } else {
                    Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG);

                }

                // returns true; the value is ignored.
                return true;

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

        return false;
    }
};