Android - ลากและวาง
เฟรมเวิร์กการลาก / วางของ Android ช่วยให้ผู้ใช้ของคุณสามารถย้ายข้อมูลจากมุมมองหนึ่งไปยังอีกมุมมองหนึ่งในเค้าโครงปัจจุบันโดยใช้ท่าทางลากและวางแบบกราฟิก ณAPI 11 รองรับการลากและวางมุมมองไปยังมุมมองหรือกลุ่มมุมมองอื่น ๆ เฟรมเวิร์กประกอบด้วยองค์ประกอบที่สำคัญสามประการต่อไปนี้เพื่อรองรับฟังก์ชันการลากและวาง
Drag event class.
Drag listeners.
Helper methods and classes.
กระบวนการลาก / วาง
โดยทั่วไปมีสี่ขั้นตอนหรือสถานะในกระบวนการลากและวาง -
Started - เหตุการณ์นี้เกิดขึ้นเมื่อคุณเริ่มลากรายการในเค้าโครงแอปพลิเคชันของคุณเรียกใช้เมธอด startDrag ()เพื่อบอกให้ระบบเริ่มการลาก อาร์กิวเมนต์ภายในเมธอด startDrag () ให้ข้อมูลที่จะลากข้อมูลเมตาสำหรับข้อมูลนี้และการเรียกกลับสำหรับการวาดเงาลาก
ระบบจะตอบกลับก่อนโดยโทรกลับไปที่แอปพลิเคชันของคุณเพื่อรับเงาลาก จากนั้นจะแสดงเงาลากบนอุปกรณ์
จากนั้นระบบจะส่งเหตุการณ์ลากที่มีประเภทการดำเนินการACTION_DRAG_STARTEDไปยังผู้ฟังเหตุการณ์การลากที่ลงทะเบียนสำหรับวัตถุ View ทั้งหมดในเค้าโครงปัจจุบัน
หากต้องการรับเหตุการณ์ลากต่อไปรวมถึงเหตุการณ์การดร็อปที่เป็นไปได้ผู้ฟังเหตุการณ์ลากจะต้องส่งคืน trueหาก Listener เหตุการณ์ลากส่งคืนเป็นเท็จจะไม่ได้รับเหตุการณ์การลากสำหรับการดำเนินการปัจจุบันจนกว่าระบบจะส่งเหตุการณ์ลากที่มีประเภทการดำเนินการ ACTION_DRAG_ENDED
Continuing- ผู้ใช้ลากต่อไป ระบบส่งการดำเนินการ ACTION_DRAG_ENTERED ตามด้วยการดำเนินการ ACTION_DRAG_LOCATION ไปยังผู้ฟังเหตุการณ์การลากที่ลงทะเบียนไว้สำหรับมุมมองที่จุดลากเข้า ผู้ฟังอาจเลือกที่จะปรับเปลี่ยนลักษณะที่ปรากฏของวัตถุ View เพื่อตอบสนองต่อเหตุการณ์หรือสามารถตอบสนองโดยการเน้นมุมมอง
ผู้ฟังเหตุการณ์การลากได้รับการดำเนินการ ACTION_DRAG_EXITED หลังจากที่ผู้ใช้ย้ายเงาลากออกนอกกรอบขอบเขตของมุมมอง
Dropped- ผู้ใช้ปล่อยรายการที่ลากภายในกรอบขอบเขตของ View ระบบจะส่งเหตุการณ์การลากให้ผู้ฟังของวัตถุดูด้วยประเภทการดำเนินการ ACTION_DROP
Ended - หลังจากประเภทการดำเนินการ ACTION_DROP ระบบจะส่งเหตุการณ์ลากที่มีประเภทการดำเนินการ ACTION_DRAG_ENDED เพื่อระบุว่าการดำเนินการลากสิ้นสุดลงแล้ว
คลาส DragEvent
DragEventหมายถึงเหตุการณ์ที่ระบบส่งออกในช่วงเวลาต่างๆระหว่างการดำเนินการลากและวาง คลาสนี้มีค่าคงที่และวิธีการสำคัญเพียงไม่กี่อย่างที่เราใช้ในระหว่างกระบวนการลาก / วาง
ค่าคงที่
ต่อไปนี้เป็นค่าคงที่จำนวนเต็มทั้งหมดที่มีอยู่ในคลาส DragEvent
ซีเนียร์ | ค่าคงที่และคำอธิบาย |
---|---|
1 |
ACTION_DRAG_STARTED ส่งสัญญาณการเริ่มต้นการลากและวาง |
2 |
ACTION_DRAG_ENTERED ส่งสัญญาณไปยังมุมมองว่าจุดลากได้เข้าสู่กล่องขอบเขตของมุมมอง |
3 | ACTION_DRAG_LOCATION ส่งไปยังมุมมองหลังจาก ACTION_DRAG_ENTERED หากเงาของการลากยังคงอยู่ในกรอบขอบเขตของวัตถุดู |
4 | ACTION_DRAG_EXITED สัญญาณว่าผู้ใช้ย้ายเงาลากออกนอกกรอบขอบเขตของมุมมอง |
5 | ACTION_DROP ส่งสัญญาณไปยังมุมมองที่ผู้ใช้ปล่อยเงาลากและจุดลากอยู่ภายในกรอบขอบเขตของมุมมอง |
6 |
ACTION_DRAG_ENDED สัญญาณไปยังมุมมองว่าการดำเนินการลากและวางได้ข้อสรุปแล้ว |
วิธีการ
ต่อไปนี้เป็นวิธีการที่สำคัญและใช้บ่อยที่สุดซึ่งเป็นส่วนหนึ่งของคลาส DragEvent
ซีเนียร์ | ค่าคงที่และคำอธิบาย |
---|---|
1 | int getAction() ตรวจสอบมูลค่าการกระทำของเหตุการณ์นี้ .. |
2 | ClipData getClipData() ส่งคืนอ็อบเจ็กต์ ClipData ที่ส่งไปยังระบบโดยเป็นส่วนหนึ่งของการเรียกใช้ startDrag () |
3 |
ClipDescription getClipDescription() ส่งคืนอ็อบเจ็กต์ ClipDescription ที่มีอยู่ใน ClipData |
4 |
boolean getResult() ส่งคืนการบ่งชี้ผลลัพธ์ของการดำเนินการลากและวาง |
5 |
float getX() รับพิกัด X ของจุดลาก |
6 | float getY() รับพิกัด Y ของจุดลาก |
7 | String toString() ส่งกลับการแสดงสตริงของวัตถุ DragEvent นี้ |
การรับฟังเหตุการณ์ลาก
หากคุณต้องการมุมมองใด ๆ ของคุณภายใน Layout ควรตอบสนองเหตุการณ์ Drag จากนั้นมุมมองของคุณก็จะดำเนินการ View.OnDragListener หรือตั้งค่า onDragEvent(DragEvent)วิธีการโทรกลับ เมื่อระบบเรียกใช้เมธอดหรือ Listener ระบบจะส่งผ่านอ็อบเจกต์ DragEvent ที่อธิบายข้างต้นไปให้พวกเขา คุณสามารถมีทั้ง Listener และวิธีการโทรกลับสำหรับ View object หากสิ่งนี้เกิดขึ้นระบบจะเรียกผู้ฟังก่อนจากนั้นจึงกำหนดการเรียกกลับตราบเท่าที่ผู้ฟังส่งคืนค่าจริง
การรวมกันของเมธอด onDragEvent (DragEvent)และView OnDragListenerนั้นคล้ายคลึงกับการรวมกันของonTouchEvent() และ View.OnTouchListener ใช้กับเหตุการณ์การสัมผัสใน Android เวอร์ชันเก่า
การเริ่มต้นเหตุการณ์การลาก
คุณเริ่มต้นด้วยการสร้างไฟล์ ClipData และ ClipData.Itemสำหรับข้อมูลที่ถูกย้าย ในฐานะที่เป็นส่วนหนึ่งของวัตถุClipDataให้จัดหาข้อมูลเมตาที่เก็บไว้ในไฟล์ClipDescriptionวัตถุภายใน ClipData สำหรับการดำเนินการลากและวางที่ไม่ได้แสดงถึงการเคลื่อนย้ายข้อมูลคุณอาจต้องการใช้null แทนที่จะเป็นวัตถุจริง
ถัดไปคุณสามารถขยายส่วนขยายได้ View.DragShadowBuilderเพื่อสร้างเงาลากสำหรับลากมุมมองหรือเพียงแค่คุณสามารถใช้View.DragShadowBuilder (View)เพื่อสร้างเงาลากเริ่มต้นที่มีขนาดเดียวกับอาร์กิวเมนต์ View ที่ส่งไปให้โดยจุดสัมผัสที่อยู่ตรงกลางของเงาลาก
ตัวอย่าง
ตัวอย่างต่อไปนี้แสดงการทำงานของการลากและวางแบบธรรมดาโดยใช้ View.setOnLongClickListener(), View.setOnTouchListener()และ View.OnDragEventListener().
ขั้นตอน | คำอธิบาย |
---|---|
1 | คุณจะใช้ Android สตูดิโอ IDE ในการสร้างแอพลิเคชัน Android และชื่อเป็นแอพลิเคชันของฉันภายใต้แพคเกจcom.example.saira_000.myapplication |
2 | แก้ไขไฟล์src / MainActivity.javaและเพิ่มโค้ดเพื่อกำหนดตัวฟังเหตุการณ์ตลอดจนวิธีการเรียกกลับสำหรับรูปภาพโลโก้ที่ใช้ในตัวอย่าง |
3 | คัดลอกรูปภาพ abc.png ในโฟลเดอร์res / drawable- * คุณสามารถใช้รูปภาพที่มีความละเอียดแตกต่างกันได้ในกรณีที่คุณต้องการจัดเตรียมให้กับอุปกรณ์ต่างๆ |
4 | แก้ไขไฟล์ XML เค้าโครงres / layout / activity_main.xmlเพื่อกำหนดมุมมองเริ่มต้นของภาพโลโก้ |
5 | เรียกใช้แอปพลิเคชันเพื่อเปิดโปรแกรมจำลอง Android และตรวจสอบผลลัพธ์ของการเปลี่ยนแปลงที่ทำในแอปพลิเคชัน |
ต่อไปนี้เป็นเนื้อหาของไฟล์กิจกรรมหลักที่แก้ไข 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 ระบุโลโก้ของ tutorialspoint.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/values/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ในขณะที่ทำการตั้งค่าสภาพแวดล้อม ในการเรียกใช้แอปจาก Android Studio ให้เปิดไฟล์กิจกรรมของโครงการแล้วคลิก
ตอนนี้ให้คลิกยาวที่โลโก้ TutorialsPoint ที่แสดงและคุณจะเห็นว่าภาพโลโก้นั้นเคลื่อนไหวเล็กน้อยหลังจากคลิกจากตำแหน่งนาน 1 วินาทีซึ่งเป็นเวลาที่คุณควรเริ่มลากภาพ คุณสามารถลากไปรอบ ๆ หน้าจอและวางในตำแหน่งใหม่