ড্র্যাগ স্টার্ট ট্রিগার করতে পারে এমন ইভেন্টগুলিতে সাড়া দিয়ে এবং প্রতিক্রিয়া এবং ড্রপ ইভেন্টগুলি গ্রহণ করে আপনি আপনার ড্র্যাগ-এন্ড-ড্রপ প্রক্রিয়াটি ভিউয়ে প্রয়োগ করতে পারেন।
একটি টান শুরু করুন
ব্যবহারকারী একটি অঙ্গভঙ্গি দিয়ে একটি টেনে আনতে শুরু করে, সাধারণত স্পর্শ করে বা ক্লিক করে এবং ধরে রাখার মাধ্যমে তারা টেনে আনতে চায়।
একটি View
এটি পরিচালনা করতে, সরানো ডেটার জন্য একটি ClipData
অবজেক্ট এবং ClipData.Item
অবজেক্ট তৈরি করুন। ClipData
এর অংশ হিসেবে, ClipData
মধ্যে একটি ClipDescription
অবজেক্টে সংরক্ষিত মেটাডেটা সরবরাহ করুন। একটি ড্র্যাগ-এন্ড-ড্রপ অপারেশনের জন্য যা ডেটা আন্দোলনের প্রতিনিধিত্ব করে না, আপনি একটি প্রকৃত বস্তুর পরিবর্তে null
ব্যবহার করতে চাইতে পারেন।
উদাহরণস্বরূপ, এই কোড স্নিপেটটি দেখায় কিভাবে একটি ImageView
এ একটি স্পর্শ এবং ধরে রাখার অঙ্গভঙ্গিতে প্রতিক্রিয়া জানাতে হয় একটি ClipData
অবজেক্ট তৈরি করে যাতে একটি ImageView
এর ট্যাগ (বা লেবেল) থাকে:
কোটলিন
// Create a string for the ImageView label. val IMAGEVIEW_TAG = "icon bitmap" ... val imageView = ImageView(context).apply { // Set the bitmap for the ImageView from an icon bitmap defined elsewhere. setImageBitmap(iconBitmap) tag = IMAGEVIEW_TAG setOnLongClickListener { 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. val item = ClipData.Item(v.tag as? CharSequence) // Create a new ClipData using the tag as a label, the plain text // MIME type, and the already-created item. This creates a new // ClipDescription object within the ClipData and sets its MIME type // to "text/plain". val dragData = ClipData( v.tag as? CharSequence, arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN), item) // Instantiate the drag shadow builder. We use this imageView object // to create the default builder. val myShadow = View.DragShadowBuilder(view: this) // Start the drag. v.startDragAndDrop(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. ) // Indicate that the long-click is handled. true } }
জাভা
// Create a string for the ImageView label. private static final String IMAGEVIEW_TAG = "icon bitmap"; ... // Create a new ImageView. ImageView imageView = new ImageView(context); // Set the bitmap for the ImageView from an icon bitmap defined elsewhere. imageView.setImageBitmap(iconBitmap); // Set the tag. imageView.setTag(IMAGEVIEW_TAG); // Set a long-click listener for the ImageView using an anonymous listener // object that implements the OnLongClickListener interface. imageView.setOnLongClickListener( 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((CharSequence) v.getTag()); // Create a new ClipData using the tag as a label, the plain text MIME type, // and the already-created item. This creates a new ClipDescription object // within the ClipData and sets its MIME type to "text/plain". ClipData dragData = new ClipData( (CharSequence) v.getTag(), new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN }, item); // Instantiate the drag shadow builder. We use this imageView object // to create the default builder. View.DragShadowBuilder myShadow = new View.DragShadowBuilder(imageView); // Start the drag. v.startDragAndDrop(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. ); // Indicate that the long-click is handled. return true; });
ড্র্যাগ শুরুতে সাড়া দিন
ড্র্যাগ অপারেশন চলাকালীন, সিস্টেম বর্তমান লেআউটে View
অবজেক্টের ড্র্যাগ ইভেন্ট শ্রোতাদের কাছে ড্র্যাগ ইভেন্টগুলি প্রেরণ করে। শ্রোতারা অ্যাকশনের ধরন পেতে DragEvent.getAction()
কল করে প্রতিক্রিয়া জানায়। একটি টেনে আনার শুরুতে, এই পদ্ধতিটি ACTION_DRAG_STARTED
প্রদান করে।
অ্যাকশন টাইপ ACTION_DRAG_STARTED
সহ একটি ইভেন্টের প্রতিক্রিয়া হিসাবে, একজন ড্র্যাগ ইভেন্ট শ্রোতাকে নিম্নলিখিতগুলি করতে হবে:
DragEvent.getClipDescription()
কে কল করুন এবং শ্রোতা টেনে আনা ডেটা গ্রহণ করতে পারে কিনা তা দেখতে ফেরতClipDescription
এ MIME টাইপ পদ্ধতি ব্যবহার করুন।যদি ড্র্যাগ-এন্ড-ড্রপ অপারেশন ডেটা চলাচলের প্রতিনিধিত্ব না করে তবে এটি অপ্রয়োজনীয় হতে পারে।
যদি ড্র্যাগ ইভেন্ট শ্রোতা একটি ড্রপ গ্রহণ করতে পারে, তবে শ্রোতাকে ড্র্যাগ ইভেন্টগুলি পাঠানো চালিয়ে যেতে সিস্টেমকে বলার জন্য এটি অবশ্যই
true
হতে হবে। যদি শ্রোতা একটি ড্রপ গ্রহণ করতে না পারে, শ্রোতাকে অবশ্যইfalse
ফেরত দিতে হবে, এবং সিস্টেমটি ড্র্যাগ-এন্ড-ড্রপ অপারেশন শেষ করতেACTION_DRAG_ENDED
না পাঠানো পর্যন্ত শ্রোতার কাছে ড্র্যাগ ইভেন্টগুলি পাঠানো বন্ধ করে।
একটি ACTION_DRAG_STARTED
ইভেন্টের জন্য, নিম্নলিখিত DragEvent
পদ্ধতিগুলি বৈধ নয়: getClipData()
, getX()
, getY()
, এবং getResult()
৷
টানার সময় ইভেন্টগুলি পরিচালনা করুন
ড্র্যাগ অ্যাকশন চলাকালীন, ড্র্যাগ ইভেন্ট শ্রোতারা যা ACTION_DRAG_STARTED
ড্র্যাগ ইভেন্টের প্রতিক্রিয়া হিসাবে true
ফিরে আসে ড্র্যাগ ইভেন্টগুলি পেতে থাকে। ড্র্যাগের সময় একজন শ্রোতা যে ধরনের ড্র্যাগ ইভেন্টগুলি গ্রহণ করে তা নির্ভর করে ড্র্যাগ শ্যাডোর অবস্থান এবং শ্রোতার View
দৃশ্যমানতার উপর। শ্রোতারা তাদের View
চেহারা পরিবর্তন করতে হবে কিনা তা নির্ধারণ করতে প্রাথমিকভাবে ড্র্যাগ ইভেন্টগুলি ব্যবহার করে৷
ড্র্যাগ অ্যাকশন চলাকালীন, DragEvent.getAction()
তিনটি মানের একটি প্রদান করে:
-
ACTION_DRAG_ENTERED
: শ্রোতা এই ইভেন্ট অ্যাকশন টাইপটি পায় যখন স্পর্শ পয়েন্ট—ব্যবহারকারীর আঙুল বা মাউসের নীচে স্ক্রিনের বিন্দু—শ্রোতারView
বাউন্ডিং বাক্সে প্রবেশ করে। -
ACTION_DRAG_LOCATION
: একবার শ্রোতা একটিACTION_DRAG_ENTERED
ইভেন্ট গ্রহণ করলে, এটি একটিACTION_DRAG_EXITED
ইভেন্ট না পাওয়া পর্যন্ত প্রতিবার টাচ পয়েন্ট সরে যাওয়ার সময় এটি একটি নতুনACTION_DRAG_LOCATION
ইভেন্ট পায়।getX()
এবংgetY()
পদ্ধতি স্পর্শ বিন্দুর X এবং Y স্থানাঙ্ক ফিরিয়ে দেয়। -
ACTION_DRAG_EXITED
: এই ইভেন্ট অ্যাকশন টাইপটি এমন একজন শ্রোতার কাছে পাঠানো হয় যেটি আগেACTION_DRAG_ENTERED
পেয়েছে। ইভেন্টটি পাঠানো হয় যখন ড্র্যাগ শ্যাডো টাচ পয়েন্ট শ্রোতারView
এর বাউন্ডিং বাক্সের মধ্যে থেকে বাউন্ডিং বাক্সের বাইরে চলে যায়।
ড্র্যাগ ইভেন্ট শ্রোতাকে এই ধরনের কোনো অ্যাকশনে প্রতিক্রিয়া জানাতে হবে না। যদি শ্রোতা সিস্টেমে একটি মান ফেরত দেয় তবে এটি উপেক্ষা করা হয়।
এই ধরনের প্রতিটি কর্মের প্রতিক্রিয়া করার জন্য এখানে কিছু নির্দেশিকা রয়েছে:
-
ACTION_DRAG_ENTERED
বাACTION_DRAG_LOCATION
এর প্রতিক্রিয়ায়, শ্রোতাView
চেহারা পরিবর্তন করতে পারে নির্দেশ করতে পারে যে দৃশ্যটি একটি সম্ভাব্য ড্রপ লক্ষ্য। - অ্যাকশন টাইপ
ACTION_DRAG_LOCATION
সহ একটি ইভেন্টে টাচ পয়েন্টের অবস্থানের সাথে সম্পর্কিতgetX()
এবংgetY()
এর জন্য বৈধ ডেটা রয়েছে৷ শ্রোতা স্পর্শ পয়েন্টেView
চেহারা পরিবর্তন করতে বা ব্যবহারকারীর বিষয়বস্তুটি কোথায় ফেলতে পারে তা সঠিক অবস্থান নির্ধারণ করতে এই তথ্যটি ব্যবহার করতে পারে। -
ACTION_DRAG_EXITED
এর প্রতিক্রিয়া হিসাবে, শ্রোতাকে অবশ্যইACTION_DRAG_ENTERED
বাACTION_DRAG_LOCATION
প্রতিক্রিয়া হিসাবে প্রযোজ্য যে কোনও চেহারা পরিবর্তনগুলি পুনরায় সেট করতে হবে। এটি ব্যবহারকারীকে নির্দেশ করে যেView
আর একটি আসন্ন ড্রপ লক্ষ্য নয়।
একটি ড্রপ সাড়া
যখন ব্যবহারকারী একটি View
উপর ড্র্যাগ শ্যাডো প্রকাশ করে, এবং View
পূর্বে রিপোর্ট করে যে এটি টেনে আনা বিষয়বস্তু গ্রহণ করতে পারে, তখন সিস্টেম অ্যাকশন টাইপ ACTION_DROP
সহ View
একটি ড্র্যাগ ইভেন্ট প্রেরণ করে।
ড্র্যাগ ইভেন্ট শ্রোতাকে নিম্নলিখিতগুলি করতে হবে:
startDragAndDrop()
কলে সরবরাহ করাClipData
অবজেক্ট পেতেgetClipData()
কল করুন এবং ডেটা প্রক্রিয়া করুন। যদি ড্র্যাগ-এন্ড-ড্রপ অপারেশন ডেটা চলাচলের প্রতিনিধিত্ব না করে তবে এটি অপ্রয়োজনীয়।ড্রপটি সফলভাবে প্রসেস করা হয়েছে তা বোঝাতে
true
ট্রু রিটার্ন করুন, অথবা যদি না হয় তাহলেfalse
। প্রত্যাবর্তিত মানটিACTION_DRAG_ENDED
ইভেন্টের জন্যgetResult()
দ্বারা প্রত্যাবর্তিত মান হয়ে যায়। যদি সিস্টেমটি একটিACTION_DROP
ইভেন্ট না পাঠায়, তাহলে একটিACTION_DRAG_ENDED
ইভেন্টের জন্যgetResult()
দ্বারা ফেরত দেওয়া মানটিfalse
।
একটি ACTION_DROP
ইভেন্টের জন্য, getX()
এবং getY()
View
স্থানাঙ্ক সিস্টেম ব্যবহার করে যা ড্রপ গ্রহণ করে ড্রপের মুহূর্তে স্পর্শ বিন্দুর X এবং Y অবস্থান ফেরত দিতে।
ব্যবহারকারী এমন একটি View
উপর ড্র্যাগ শ্যাডো প্রকাশ করতে সক্ষম হয় যার ড্র্যাগ ইভেন্ট শ্রোতারা ড্র্যাগ ইভেন্টগুলি, আপনার অ্যাপের UI এর খালি অঞ্চলগুলি বা এমনকি আপনার অ্যাপ্লিকেশনের বাইরের অঞ্চলগুলিও পাচ্ছেন না, Android ACTION_DROP
অ্যাকশন টাইপ সহ একটি ইভেন্ট পাঠাবে না এবং শুধুমাত্র একটি ACTION_DRAG_ENDED
ইভেন্ট পাঠাবে৷
একটি টেনে শেষ প্রতিক্রিয়া
ব্যবহারকারী ড্র্যাগ শ্যাডো প্রকাশ করার সাথে সাথেই, সিস্টেমটি আপনার অ্যাপ্লিকেশনের সমস্ত ড্র্যাগ ইভেন্ট শ্রোতাদের কাছে ACTION_DRAG_ENDED
একটি অ্যাকশন টাইপের একটি ড্র্যাগ ইভেন্ট পাঠায়৷ এটি নির্দেশ করে যে ড্র্যাগ অপারেশন শেষ হয়েছে৷
প্রতিটি ড্র্যাগ ইভেন্ট শ্রোতাকে অবশ্যই নিম্নলিখিতগুলি করতে হবে:
- যদি শ্রোতা অপারেশন চলাকালীন তার চেহারা পরিবর্তন করে, তবে এটি ব্যবহারকারীকে একটি ভিজ্যুয়াল ইঙ্গিত হিসাবে তার ডিফল্ট চেহারাতে পুনরায় সেট করা উচিত যে অপারেশনটি শেষ হয়েছে।
- শ্রোতা ঐচ্ছিকভাবে অপারেশন সম্পর্কে আরও জানতে
getResult()
কল করতে পারেন। যদি একজন শ্রোতাACTION_DROP
ধরনের অ্যাকশনের একটি ইভেন্টের প্রতিক্রিয়া হিসাবেtrue
ফেরত দেয়, তাহলেgetResult()
বুলিয়ানtrue
প্রদান করে। অন্য সব ক্ষেত্রে,getResult()
বুলিয়ানfalse
প্রদান করে, যখন সিস্টেমACTION_DROP
ইভেন্ট পাঠায় না। - ড্রপ অপারেশনের সফল সমাপ্তি নির্দেশ করার জন্য, শ্রোতাকে সিস্টেমে বুলিয়ান
true
ফেরত দেওয়া উচিত।false
প্রত্যাবর্তন না করার মাধ্যমে, একটি ভিজ্যুয়াল কিউ ড্রপ শ্যাডোটি তার উত্সে ফিরে আসছে তা ব্যবহারকারীকে পরামর্শ দিতে পারে যে অপারেশনটি ব্যর্থ হয়েছে৷
ড্র্যাগ ইভেন্টগুলির প্রতিক্রিয়া: একটি উদাহরণ
সমস্ত ড্র্যাগ ইভেন্ট আপনার ড্র্যাগ ইভেন্ট পদ্ধতি বা শ্রোতা দ্বারা গৃহীত হয়। নিম্নলিখিত কোড স্নিপেটটি ড্র্যাগ ইভেন্টগুলিতে প্রতিক্রিয়া জানানোর একটি উদাহরণ:
কোটলিন
val imageView = ImageView(this) // Set the drag event listener for the View. imageView.setOnDragListener { v, e -> // Handle each of the expected events. when (e.action) { DragEvent.ACTION_DRAG_STARTED -> { // Determine whether this View can accept the dragged data. if (e.clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { // As an example, apply a blue color tint to the View to // indicate that it can accept data. (v as? ImageView)?.setColorFilter(Color.BLUE) // Invalidate the view to force a redraw in the new tint. v.invalidate() // Return true to indicate that the View can accept the dragged // data. true } else { // Return false to indicate that, during the current drag and // drop operation, this View doesn't receive events again until // ACTION_DRAG_ENDED is sent. false } } DragEvent.ACTION_DRAG_ENTERED -> { // Apply a green tint to the View. (v as? ImageView)?.setColorFilter(Color.GREEN) // Invalidate the view to force a redraw in the new tint. v.invalidate() // Return true. The value is ignored. true } DragEvent.ACTION_DRAG_LOCATION -> // Ignore the event. true DragEvent.ACTION_DRAG_EXITED -> { // Reset the color tint to blue. (v as? ImageView)?.setColorFilter(Color.BLUE) // Invalidate the view to force a redraw in the new tint. v.invalidate() // Return true. The value is ignored. true } DragEvent.ACTION_DROP -> { // Get the item containing the dragged data. val item: ClipData.Item = e.clipData.getItemAt(0) // Get the text data from the item. val dragData = item.text // Display a message containing the dragged data. Toast.makeText(this, "Dragged data is $dragData", Toast.LENGTH_LONG).show() // Turn off color tints. (v as? ImageView)?.clearColorFilter() // Invalidate the view to force a redraw. v.invalidate() // Return true. DragEvent.getResult() returns true. true } DragEvent.ACTION_DRAG_ENDED -> { // Turn off color tinting. (v as? ImageView)?.clearColorFilter() // Invalidate the view to force a redraw. v.invalidate() // Do a getResult() and display what happens. when(e.result) { true -> Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG) else -> Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG) }.show() // Return true. The value is ignored. true } else -> { // An unknown action type is received. Log.e("DragDrop Example", "Unknown action type received by View.OnDragListener.") false } } }
জাভা
View imageView = new ImageView(this); // Set the drag event listener for the View. imageView.setOnDragListener( (v, e) -> { // Handle each of the expected events. switch(e.getAction()) { case DragEvent.ACTION_DRAG_STARTED: // Determine whether this View can accept the dragged data. if (e.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { // As an example, apply a blue color tint to the View to // indicate that it can accept data. ((ImageView)v).setColorFilter(Color.BLUE); // Invalidate the view to force a redraw in the new tint. v.invalidate(); // Return true to indicate that the View can accept the dragged // data. return true; } // Return false to indicate that, during the current drag-and-drop // operation, this View doesn't receive events again until // ACTION_DRAG_ENDED is sent. return false; case DragEvent.ACTION_DRAG_ENTERED: // Apply a green tint to the View. ((ImageView)v).setColorFilter(Color.GREEN); // Invalidate the view to force a redraw in the new tint. v.invalidate(); // Return true. The value is ignored. return true; case DragEvent.ACTION_DRAG_LOCATION: // Ignore the event. return true; case DragEvent.ACTION_DRAG_EXITED: // Reset the color tint to blue. ((ImageView)v).setColorFilter(Color.BLUE); // Invalidate the view to force a redraw in the new tint. v.invalidate(); // Return true. The value is ignored. return true; case DragEvent.ACTION_DROP: // Get the item containing the dragged data. ClipData.Item item = e.getClipData().getItemAt(0); // Get the text data from the item. CharSequence dragData = item.getText(); // Display a message containing the dragged data. Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG).show(); // Turn off color tints. ((ImageView)v).clearColorFilter(); // Invalidate the view to force a redraw. v.invalidate(); // Return true. DragEvent.getResult() returns true. return true; case DragEvent.ACTION_DRAG_ENDED: // Turn off color tinting. ((ImageView)v).clearColorFilter(); // Invalidate the view to force a redraw. v.invalidate(); // Do a getResult() and displays what happens. if (e.getResult()) { Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG).show(); } else { Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG).show(); } // Return true. The value is ignored. return true; // An unknown action type is received. default: Log.e("DragDrop Example","Unknown action type received by View.OnDragListener."); break; } return false; });
একটি ড্র্যাগ শ্যাডো কাস্টমাইজ করুন
আপনি View.DragShadowBuilder
এ পদ্ধতিগুলি ওভাররাইড করে একটি কাস্টমাইজড myDragShadowBuilder
সংজ্ঞায়িত করতে পারেন। নিম্নলিখিত কোড স্নিপেট একটি TextView
এর জন্য একটি ছোট, আয়তক্ষেত্রাকার, ধূসর ড্র্যাগ শ্যাডো তৈরি করে:
কোটলিন
private class MyDragShadowBuilder(view: View) : View.DragShadowBuilder(view) { private val shadow = ColorDrawable(Color.LTGRAY) // Define a callback that sends the drag shadow dimensions and touch point // back to the system. override fun onProvideShadowMetrics(size: Point, touch: Point) { // Set the width of the shadow to half the width of the original // View. val width: Int = view.width / 2 // Set the height of the shadow to half the height of the original // View. val height: Int = view.height / 2 // The drag shadow is a ColorDrawable. Set its dimensions to // be the same as the Canvas that the system provides. As a result, // the drag shadow fills the Canvas. shadow.setBounds(0, 0, width, height) // Set the size parameter's width and height values. These get back // to the system through the size parameter. size.set(width, height) // Set the touch point's position to be in the middle of the drag // shadow. touch.set(width / 2, height / 2) } // Define a callback that draws the drag shadow in a Canvas that the system // constructs from the dimensions passed to onProvideShadowMetrics(). override fun onDrawShadow(canvas: Canvas) { // Draw the ColorDrawable on the Canvas passed in from the system. shadow.draw(canvas) } }
জাভা
private static class MyDragShadowBuilder extends View.DragShadowBuilder { // The drag shadow image, defined as a drawable object. private static Drawable shadow; // Constructor. public MyDragShadowBuilder(View view) { // Store the View parameter. super(view); // Create a draggable image that fills the Canvas provided by the // system. shadow = new ColorDrawable(Color.LTGRAY); } // Define a callback that sends the drag shadow dimensions and touch point // back to the system. @Override public void onProvideShadowMetrics (Point size, Point touch) { // Define local variables. int width, height; // Set the width of the shadow to half the width of the original // View. width = getView().getWidth() / 2; // Set the height of the shadow to half the height of the original // View. height = getView().getHeight() / 2; // The drag shadow is a ColorDrawable. Set its dimensions to // be the same as the Canvas that the system provides. As a result, // the drag shadow fills the Canvas. shadow.setBounds(0, 0, width, height); // Set the size parameter's width and height values. These get back // to the system through the size parameter. size.set(width, height); // Set the touch point's position to be in the middle of the drag // shadow. touch.set(width / 2, height / 2); } // Define a callback that draws the drag shadow in a Canvas that the system // constructs from the dimensions passed to onProvideShadowMetrics(). @Override public void onDrawShadow(Canvas canvas) { // Draw the ColorDrawable on the Canvas passed in from the system. shadow.draw(canvas); } }