چهارچوب drag و drop اندروید به کاربران شما اجازه می دهد که با استفاده از یک حرکت گرافیکی درگ و دراپ؛ داده های مورد نظرشان را از یک View به View دیگر در صفحه بندی فعلی منتقل کنند. (درگ کردن به معنای انتخاب یک آیتم روی صفحه دستگاه و حرکت آن به یک نقطه ی دیگر می باشد؛ دراپ نیز به معنای رها کردن آیتم در آن نقطه مورد نظر است).
درگ و دراپ کردن view به نماهای دیگر یا نماهای گروهی به شکل API 11 پشتیبانی شده است. این چارچوب برای پشتیبانی از عملکرد درگ و دراپ، شامل سه مؤلفه ی بسیار مهم زیر می باشد:
- درگ کردن کلاس رویدادها
- درگ کردن مخاطبین
- کلاس ها و متد های کمک کننده
فرآیند Drag/Drop
اساساً چهار مرحله یا حالت در فرآیند درگ و دراپ وجود دارد.
- شروع – این رویداد هنگامی رخ می دهد که شروع به درگ کردن یک آیتم در یک صفحه بندی می نمایید، اپلیکیشن شما متد startDrag() را فراخوانی می کند تا به سیستم بگوید که درگ کردن را شروع کند. آرگومان های درون متد startDrag() داده هایی را که می توان درگ نمود، فراهم می آورد. همچنین متادیتا برای این داده ها و نیز کال بک برای ترسیم سایه درگ را فراهم می کند.
این سیستم ابتدا با تماس با استفاده از کال بک به اپلیکیشن شما پاسخ می دهد تا سایه درگ کردن دریافت شود. سپس سیستم سایه درگ کردن را روی دستگاه نمایش می دهد.
در مرحله بعد ، سیستم یک رویداد درگ با نوع عمل ACTION_DRAG_STARTED را برای مخاطبین رویداد درگ ثبت شده برای همه اشیاء View در صفحه بندی فعلی، ارسال می کند.
برای ادامه دادن به دریافت رویدادهای درگ؛ از جمله رویداد دراپ احتمالی، یک رویداد مخاطب رویداد درگ باید true را بازگرداند؛ اما اگر مخاطب رویداد درگ؛ false را برگرداند؛ سپس رویدادهای درگ برای عملکرد فعلی را دریافت نمی کند؛ تا زمانی که سیستم یک رویداد درگ با نوع فعالیت ACTION_DRAG_ENDED را اراسال نماید.
- ادامه فرآیند- کاربر درگ کردن را ادامه می دهد. سیستم فعالیت ACTION_DRAG_ENTERD و به دنبال آن ACTION_DARG_LOCATION را به مخاطب ثبت شده برای رویداد درگ ارسال می کند تا View که در آن درگ نقطه درگ کردن وارد می شود؛ مشخص نماید. مخاطب ممکن است تصمیم بگیرد که ظاهر شیء View را در پاسخ به رویداد تغییر بدهد، همچنین می تواند با برجسته کردن View آن واکنش نشان بدهد.
بعد از آن که کاربر سایه درگ را به خارج از کادر محدوده View منتقل کرد؛ مخاطب رویداد درگ، یک عمل ACTION_DRAG_EXITD را دریافت می کند.
- دراپ شدن- کاربر آیتم درگ شده را درون کادر محدوده ی View رها می کند. سیستم به مخاطب شیء View یک رویداد درگ با نوع عمل ACTION_DROP ارسال می کند.
- پایان- دقیقاً بعد از نوع عمل ACTION_DROP سیستم یک رویداد درگ را با نوع عمل ACTION_DRAG_ENDED ارسال می کند تا نشان بدهد که عملیات درگ کردن تمام شده است.
کلاس DragEvent
در واقع DragEvent نشان دهنده رویدادی است که توسط سیستم در زمان های متفاوت در طول یک عملیات درگ و دراپ ارسال می شود. این کلاس، تعدادی ثابت و متدهای مهم وجود دارد که در طول فرآیند Drag/Drop استفاده می کنیم.
ثابت ها
در ادامه تمام اعداد صحیح ثابتی که به عنوان بخشی از کلاس DragEvent در دسترس هستند؛ آورده شده است:
ردیف | توضیح |
۱ | ACTION_DRAG_STARTED علامت هایی که آغاز عملیات درگ و دراپ را اطلاع رسانی می کنند. |
۲ | ACTION_DRAG_ENTERED سیگنال هایی که به یک View ارسال می شود و نشان دهنده این امر است که نقطه درگ به کادر محدوده ی View وارد شده است. |
۳ | ACTION_DRAG_LOCATION بعد از ACTION_DRAG_ENTERED ؛ اگر سایه درگ هنوز درون کادر محدوده ی شیء Viewباشد؛ این نوع عمل به View ارسال می شود |
۴ | ACTION_DRAG_EXITED سیگنال هایی که نشان می دهد کاربر سایه درگ را به خارج از محدوده کادر View منتقل کرده است. |
۵ | ACTION_DROP سیگنال هایی که نشان می هد کاربر سایه درگ را رها کرده است و نقطه درگ درون محدوده کادر View می باشد. |
۶ | ACTION_DRAG_ENDED سیگنال هایی که به View نشان می دهد که عملکرد دراگ و دراپ به پایان رسیده است. |
متدها
در ادامه چندتا از مهم ترین متدهایی که مکرراً استفاده شده اند؛ به عنوان بخشی از کلاس DragEvent آورده شده است.
ردیف | ثابت ها و توضیح آنها |
۱ |
Int getAction() مقدار action این رویداد را بررسی می کند. |
۲ |
ClipData getClipData() ClipData را باز می گرداند که شیء به عنوان بخشی از فراخوانی ()startDrag ارسال می کند. |
۳ |
clipDescription getClipDescription() شیء ClipDescription را باز می گرداند که در ClipData موجود است. |
۴ |
Boolean getResult() به عنوان نشان دهنده ی نتایج عملیات درگ و دراپ برگردانده می شود. |
۵ |
Float getX() مختصات X نقطه درگ را دریافت می کند. |
۶ |
Float getY() مختصات Y نقطه درگ را دریافت می کند. |
۷ |
String to String() نمایش رشته ای از این شیء DragEvent را باز می گرداند. |
مخاطب رویداد Drag
اگر می خواهید هر یک از Viewهای تان درون یک صفحه بندی به رویداد درگ کردن پاسخ دهد؛ آنگاه view شما یاView.OnDragListener را پیاده سازی می کند یا متدکال بک (onDragEvent (DragEvent را تنظیم می کند. زمانی که سیستم متد یا مخاطب را فراخوانی می کند؛ یک شیء DragEvent را که در بالا توضیح داده شد؛ به آنها منتقل می کند. شمامی توانید برای شیء view هم یک متد کال بک و هم یک مخاطب را داشته باشید. در این صورت؛ البته سیستم ابتدا؛ مخاطب را فراخوانی می کند و سپس تا زمانی که مخاطب، عبارت true را باز می گرداند، کال بک تعریف شده را فراخوانی می نماید.
ترکیب متد (onDragEvent(DragEvent و onDragListener مشابه با ترکیب ()on TouchEvent و View.OnTouchListener است که در مورد رویدادهای touch (لمس صفحه) در نسخه های قدیمی اندروید به کار رفته است.
آغاز رویداد درگ کردن
شما با ایجاد یک ClipData و ClipData.Item برای داده هایی که حرکت داده می شوند؛ آغاز می کنید. به عنوان بخشی از شیء ClipData ، ابرداده ای را تأمین کرده است که در شیء ClipDescription درون ClipData ذخیره شده است. برای یک عملکرد درگ و دراپ که نشان دهنده حرکت داده ها نیست؛ شما ممکن است بخواهید به جای یک شیء واقعی از null استفاده کنید.
سپس شما می تواند برای ایجاد یک سایه درگ برای درگ کردن view ، View.DragShadowBuilder را توسعه بدهید یا این که به سادگی می توانید از View.DragShadowBuilder(View برای ایجاد سایه درگ پیش فرض استفاده کنید که اندازه آن مشابه شناسه View می باشد که به آن منتقل شده است و همراه با نقطه لمسی است که در مرکز سایه درگ قرار گرفته است.
مثال
مثال زیر نشان دهنده عملکرد یک درگ و دراپ ساده با استفاده از
View.setOnLongClickListener()؛View.setOnTouchListener() ؛ View.setOnDragListener()
می باشد.
مرحله | توضیح |
۱ | شما از IDE استودیو اندروید برای ایجاد اپلیکیشن اندروید استفاده می کنید و آن را تحت بسته ی com.example.saira_000myapplication به صورت My Application نام گذاری کنید. |
۲ | فایل src/MainActivity.java را اصلاح کرده و کد لازم برای تعریف مخاطبین رویداد را اضافه نمایید؛ همچنین یک متد کال بک برای تصویر لوگو در مثال باید اضافه کند. |
۳ | تصویر abc.png را در فولدرهای res/drawable کپی کنید. در مواردی که می خواهید تصاویر را برای دستگاه های متفاوت آماده کنید؛ می توانید از تصاویری با رزولوشن متفاوت استفاده کنید. |
۴ | فایل XML صفحه بندی res/layout/activity_main.xml را اصلاح کنید تا view پیشفرض تصاویر logo را تعریف نمایید. |
۵ | اپلیکیشن را اجرا کنید تا شبیه ساز اندروید راه اندازی شود و تأیید نمایید که نتایج تغییرات در اپلیکیشن انجام شده است. |
در ادامه محتوای فایل activity اصلاح شده src/MainActivity.java. را مشاهده می کنید. این فایل می تواند شامل هر یک از متدهای اساسی طول عمر باشد.
package com.example.saira_000.myapplication;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class MainActivity extends Activity {
ImageView img;
String msg;
private android.widget.RelativeLayout.LayoutParams layoutParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img=(ImageView)findViewById(R.id.imageView);
img.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
ClipData dragData = new ClipData(v.getTag().toString(),mimeTypes, item);
View.DragShadowBuilder myShadow = new View.DragShadowBuilder(img);
v.startDrag(dragData,myShadow,null,0);
return true;
}
});
img.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch(event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
layoutParams = (RelativeLayout.LayoutParams)v.getLayoutParams();
Log.d(msg, “Action is DragEvent.ACTION_DRAG_STARTED”);
// Do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.d(msg, “Action is DragEvent.ACTION_DRAG_ENTERED”);
int x_cord = (int) event.getX();
int y_cord = (int) event.getY();
break;
case DragEvent.ACTION_DRAG_EXITED :
Log.d(msg, “Action is DragEvent.ACTION_DRAG_EXITED”);
x_cord = (int) event.getX();
y_cord = (int) event.getY();
layoutParams.leftMargin = x_cord;
layoutParams.topMargin = y_cord;
v.setLayoutParams(layoutParams);
break;
case DragEvent.ACTION_DRAG_LOCATION :
Log.d(msg, “Action is DragEvent.ACTION_DRAG_LOCATION”);
x_cord = (int) event.getX();
y_cord = (int) event.getY();
break;
case DragEvent.ACTION_DRAG_ENDED :
Log.d(msg, “Action is DragEvent.ACTION_DRAG_ENDED”);
// Do nothing
break;
case DragEvent.ACTION_DROP:
Log.d(msg, “ACTION_DROP event”);
// Do nothing
break;
default: break;
}
return true;
}
});
img.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText(“”, “”);
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(img);
img.startDrag(data, shadowBuilder, img, 0);
img.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
});
}
}
در ادامه محتوای فایل res/layout/activity_main.xml را مشاهده می کنید:
در کد زیر، abc نشان دهنده لوگوی tutorialspint.com می باشد.
<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:paddingLeft=”@dimen/activity_horizontal_margin”
android:paddingRight=”@dimen/activity_horizontal_margin”
android:paddingTop=”@dimen/activity_vertical_margin”
android:paddingBottom=”@dimen/activity_vertical_margin”
tools:context=”.MainActivity”>
<TextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”Drag and Drop Example”
android:id=”@+id/textView”
android:layout_alignParentTop=”true”
android:layout_centerHorizontal=”true”
android:textSize=”30dp” />
<TextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”Tutorials Point”
android:id=”@+id/textView2″
android:layout_below=”@+id/textView”
android:layout_centerHorizontal=”true”
android:textSize=”30dp”
android:textColor=”#ff14be3c” />>
<ImageView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:id=”@+id/imageView”
android:src=”@drawable/abc”
android:layout_below=”@+id/textView2″
android:layout_alignRight=”@+id/textView2″
android:layout_alignEnd=”@+id/textView2″
android:layout_alignLeft=”@+id/textView2″
android:layout_alignStart=”@+id/textView2″ />
</RelativeLayout>
در ادامه می توانید محتوای res/value/strings.xml. را مشاهده کنید که برای تعریف ثابت های جدید به کار می رود:
<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<string name=”app_name”>My Application</string>
</resources>
در ادامه محتوای پیش فرض AndroidManifest.xml را مشاهده می کنید:
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.example.saira_000.myapplication” >
<application
android:allowBackup=”true”
android:icon=”@drawable/ic_launcher”
android:label=”@string/app_name”
android:theme=”@style/AppTheme” >
<activity
android:name=”.MainActivity”
android:label=”@string/app_name” >
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
</application>
</manifest>
بیاید اجرای برنامه ی My Application شما را امتحان کنیم. فرض می کنیم که شما در حین انجام تنظیمات محیط، AVD خود را ساخته اید. برای اجرای برنامه از استودیو اندروید، یکی از فایل های activity پروژه تان را باز کنید و روی آیکون اجرا کلیک کنید که در نوار ابزار قرار گرفته است. استودیو اندروید برنامه شما را روی AVD نصب می کند و اگر همه چیز در مورد تنظیمات و برنامه ی شما خوب پیش برود؛ اجرای برنامه آغاز می شود؛ به این ترتیب پنجره شبیه ساز زیر نمایش داده می شود.
اکنون روی لوگوی نمایش داده شده TutorialsPoint برای مدتی طولانی کلیک کنید؛ به این صورت خواهید دید تصویر لوگو کمی بعد از این که کلیک را به مدت ۱ ثانیه روی آن نگه داشتید؛ از جای خود حرکت می کند؛ اکنون زمان آن رسیده است که درگ کردن تصویر را آغاز کنید. شما می توانید آن را حول صفحه نمایش جابه جا کرده و در یک موقعیت جدید؛ آن را دراپ کنید.