آموزش کشیدن و رها کردن در اندروید
کشیدن و رها کردن در اندروید (Android Drag and Drop )
قالب کشیدن و رها کردن در اندروید این امکان را برای کاربران فراهم می کند که در layout فعلی، با استفاده از حالت کشیدن و رها کردن گرافیکی، داده را از یک View به View دیگر منتقل کنند. این قالب شامل سه مولفه اصلی زیر برای پشتیبانی از قابلیت کشیدن و رها کردن است.
کلاس رویداد کشیدن
شنودکنندگان عمل کشیدن
متدها و کلاس های کمکی
فرایند کشیدن و رها کردن
اساسا 4 مرحله یا وضعیت در فرایند کشیدن و رها کردن وجود دارد .
Started این رویداد زمانی اتفاق می افتد که شما شروع به کشیدن یک آیتم در صفحه می کنید و اپلیکیشن شما متد startDrag()را برای اعلام آغاز عملیات drag به سیستم، فراخوانی می کند. آرگومان های موجود در متد startDrag() داده هایی که باید drag شود، فرادادهی مربوط به این داده ها، و یک callback برای ترسیم مسیر drag را فراخوانی می کنند.
سیستم ابتدا با فراخوانی اپلیکیشن شما برای گرفتن مسیر drag به رویداد پاسخ می دهد، سپس مسیر drag را بر روی دستگاه نمایش می دهد.
پس از آن سیستم یک رویداد drag با نوع عمل ACTION_DRAG_STARTEDرا به شنود کننده رویداد ثبت شده برای تمام اشیا View در Layout فعلی می فرستد.
برای ادامه دریافت رویدادهای drag، از جمله یک رویداد امکان پذیرِ drop، شنود کننده باید مقدار trueرا برگرداند. اگر شنودکننده رویداد drag مقدار false را برگرداند، دیگر رویداد های drag عملیات فعلی را دریافت نمی کند، تا زمانیکه سیستم یک رویداد drag را با نوع عمل ACTION_DRAG_ENDED انتخاب کند.
Continuing کاربر به عمل drag ادامه می دهد. سیستم عمل ACTION_DRAG_ENTERED و به دنبال آن عمل ACTION_DRAG_LOCATION را به شنود کننده رویداد ثبت شده برای view ای که نقطه drag کردن از آن آغاز میشود، ارسال میکند. شنود کننده می تواند انتخاب کند که ظاهر اشیا view خود را در پاسخ به رویداد تغییر دهد یا می تواند با مشخص کردن view مربوطه، به رویداد واکنش نشان دهد.
شنود کننده رویداد drag یک عمل ACTION_DRAG_EXITED را بعد از اینکه کاربر مسیر drag را از محدوده View خارج کرد، دریافت می کند.
Dropped کاربر آیتم کشیده شده را رها می کند. سیستم به شنود کننده شی view یک رویداد drag را با نوع عمل ACTION_DROP می فرستد.
Ended درست پس از نوع عمل ACTION_DROP، سیستم برای نشان دادن پایان عملیات drag، یک رویداد drag را با نوع عمل ACTION_DRAG_ENDED می فرستد.
کلاس DragEvent
DragEventنشان دهنده رویدادی است که به وسیله سیستم در زمان های مختلف در طول عملیات drag و drop ارسال میشود. این کلاس دارای تعدادی ثابت و متد مهم است که در طول عملیات drag و drop مورد استفاده قرار می گیرند.
ثابت ها
در بخش زیر تمام ثابت های صحیحی که به عنوان بخشی از کلاس DragEvent موجود هستند لیست شده اند.
-
ACTION_DRAG_STARTED
سیگنال های مبنی بر آغاز عملیات drag و drop -
ACTION_DRAG_ENTERED
سیگنالی به یک View مبنی بر اینکه، نقطه drag کردن وارد محدوده view شده است. -
ACTION_DRAG_LOCATION
بعد از عمل ACTION_DRAG_ENTERED به یک view فرستاده می شود، اگر مسیر drag کردن هنوز در محدوده اشیا view باشد. -
ACTION_DRAG_EXITED
سیگنالی مبنی بر اینکه کاربر مسیر drag را به خارج از محدوده View منتقل کرده است. -
ACTION_DROP
سیگنالی که به یک view فرستاده میشود مبنی بر اینکه کاربر مسیر drag کردن را رها کرده است و نقطه drag در محدوده View قرار دارد. -
ACTION_DRAG_ENDED
سیگنالی به یک View مبنی بر اینکه عملیات drag و drop به پایان رسیده اند.
متدها
در بخش زیر مهمترین و پر استفاده ترین متدهای موجود در کلاس DragEvent ارائه شده اند.
-
int getAction()
مقدار avtion رویداد مربوطه را بررسی می کند. -
ClipData getClipData()
شی ClipData ارسال شده به سیستم را به عنوان بخشی از فراخوانی به startDrag() برمی گرداند. -
ClipDescription getClipDescription()
شی ClipDescription موجود در ClipData را برمی گرداند. -
boolean getResult()
نشانه ای از نتیجه عملیات drag و drop را برمی گرداند. -
float getX()
مختصات X نقطه drag کردن را می گیرد. -
float getY()
مختصات Y نقطه drag کردن را می گیرد. -
String toString()
نمایش رشته ای شی DragEvent را بر می گرداند.
گوش دادن به رویداد Drag
اگر شما بخواهید که هر کدام از View های شما در داخل یک Layout به رویداد drag پاسخ بدهد، آنگاه View شما متدهای callback، View.OnDragListenerیا onDragEvent(DragEvent)را پیاده سازی می کند. زمانی که سیستم متد یا شنود کننده را فراخوانی می کند، یک شی DragEvent که در بالا توصیف شد را به آنها بر می گرداند. شما می توانید هر دو مورد شنود کننده و متد callback را برای شی View داشته باشید. در این صورت سیستم ابتدا شنود کننده را فراخوانی می کند و سپس تا زمانی که شنود کننده مقدار صحیح را برگرداند، callback تعریف شده را فراخوانی می کند.
ترکیب متد nDragEvent(DragEvent)و View.OnDragListenerشبیه به ترکیبی از onTouchEvent()و View.OnTouchListenerبه کار رفته در مورد رویدادهای لمسی در نسخه های قدیمی اندروید است.
آغاز کردن یک رویداد Drag
شما کار را با ایجاد یک ClipDataو ClipData.Itemبرای داده های منتقل شده آغاز می کنید. این آیتم به عنوان بخشی از شی ClipData، فراداده ای را عرضه می کند که در شی ClipDescriptionدرون ClipData ذخیره میشود. برای عملیات drag و drop ای که شامل انتقال داده نیست، می توانید به جای شی واقعی از null استفاده کنید.
سپس شما می توانید یا View.DragShadowBuilderرا برای ایجاد یک مسیر drag کردن برای کشیدن View آغاز کنید و یا به سادگی از View.DragShadowBuilder(View)برای ایجاد مسیر پیش فرض drag کردن استفاده کنید که همان سایز آرگومان های View ارسالی به آن، به مرکزیت نقطه لمس کردن در مسیر drag است.
مثال
مثال زیر عملکرد یک عملیات ساده drag و drop را با استفاده از شنود کننده رویداد View.setOnLongClickListener() همراه با View.OnDragEventListener() نشان می دهد.
- از Eclipse IDE برای ایجاد یک اپلیکیشن اندرویدی استفاده کنید و آن را تحت پکیج com.example.dragndropdemo،DragNDropDemo بنامید. در حالیکه این پروژه را ایجاد می کنید برای استفاده از سطوح بالاتر API ها، از آخرین نسخه Target SDK و Compile With اطمینان حاصل کنید.
- فایل src/MainActivity.java را تغییر دهید و کدهایی را برای تعریف شنودکنندگان رویداد و همچنین متدهای call back مربوط به تصویر لوگوی به کار رفته در مثال، اضافه کنید.
- تصویر logo.png را در پوشه res/drawable-* کپی کنید. در صورتی که می خواهید تصاویر را برای دستگاه های مختلف به کار ببرید، می توانید از تصاویری با وضوح مختلف استفاده کنید.
- فایل صفحه بندی XML res/layout/activity_main.xml را برای تعریف view پیش فرض تصویر لوگو تغییر دهید.
- برای راه اندازی امولاتور اندروید اپلیکیشن را اجرا کنید و نتایج تغییرات اعمال شده در اپلیکیشن را بررسی کنید.
در بخش زیر محتوای تعییر یافته ی src/com.example.dragndropdemo/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;
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
بخش زیر محتوای فایل res/layout/activity_main.xmlاست.
<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/values/strings.xmlبرای تعریف دو ثابت جدید است.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application</string>
<string name="action_settings">Settings</string>
</resources>
بخش زیر محتوای فایل AndroidManifest.xmlاست
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.guidemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.guidemo.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>
اکنون می خواهیم اپلیکیشن DragNDropDemo رااجرا کنیم. من فرض میکنم که شما AVD خود را در زمان نصب محیط ایجاد کرده باشید. برای اجرای اپلیکیشن از Eclipse، یکی از فایل های فعالیت پروژهی خود را باز کنید و بر روی آیکن Run از نوار ابزار کلیک کنید. Eclipse، اپلیکیش را بر روی AVD شما نصب می کند و آن را آغاز می کند.
- نوشته شده توسط سعید نوشادی
- بازدید: 6165