การลากและวาง — วิธีการทำงานของการลากและวางในแอปพลิเคชันมือถือ

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-27 เวลาอ่าน: 9 นาที

การลากและวาง — ท่าทางเชิงโต้ตอบสำหรับการลากวัตถุที่มองเห็นได้บนหน้าจอด้วยนิ้ว ท่าทางประกอบด้วยสามเฟส: การจับ (กดค้างหรือแตะ), การเคลื่อนย้าย (ขยับนิ้วพร้อมกับวัตถุ), และการปล่อย (วางในพื้นที่เป้าหมาย) ใช้สำหรับจัดลำดับองค์ประกอบใหม่ ย้ายไฟล์ระหว่างโฟลเดอร์ และจัดระเบียบอินเทอร์เฟซ (drag to reorder, drag to resize) บน iOS ใช้งานผ่าน UIDragInteraction, บน Android — ผ่าน DragEvent และ startDragAndDrop

ประเด็นสำคัญ

  • สามเฟส — การลากและวางประกอบด้วยการจับ การเคลื่อนย้าย และการปล่อยวัตถุ
  • UIDragInteraction — คลาสหลักของ iOS สำหรับเริ่มต้นและจัดการการลาก
  • startDragAndDrop — เมธอดของ Android View สำหรับเริ่มการลากหลังจากจับ
  • เงาลาก — เงาที่มองเห็นได้ของวัตถุที่ถูกลาก ซึ่งตามนิ้ว
  • เป้าหมายวาง — โซนวางที่ถูกไฮไลต์เมื่อวัตถุที่ถูกลากเลื่อนผ่าน

การลากและวางคืออะไร?

การลากและวาง (DnD) เป็นวิธีการจัดการองค์ประกอบอินเทอร์เฟซแบบกราฟิกที่ผู้ใช้จับวัตถุด้วยนิ้วหรือเมาส์ ย้ายไปยังตำแหน่งอื่น และปล่อย ในอินเทอร์เฟซมือถือ การลากและวางมักเริ่มต้นด้วยการกดค้าง — ผู้ใช้กดองค์ประกอบค้างไว้ 300–500 มิลลิวินาที หลังจากนั้นระบบจะเปลี่ยนอินเทอร์เฟซเป็นโหมดลาก และการเคลื่อนไหวของนิ้วจะย้ายวัตถุตามไป

ตามประวัติศาสตร์ การลากและวางเกิดขึ้นในอินเทอร์เฟซเดสก์ท็อป (Xerox Star, 1981; Macintosh, 1984) เพื่อเป็นทางเลือกแทนคำสั่งคัดลอก/วาง บนแพลตฟอร์มมือถือ การสนับสนุนอย่างเต็มรูปแบบปรากฏใน iOS 11 (2017) ด้วย UIDragInteraction และใน Android 7.0 (2016) ด้วยการลากและวางหลายหน้าต่าง ก่อนหน้านั้น การลากในแอปมือถือถูกนำไปใช้ด้วยโซลูชันที่กำหนดเองผ่านตัวจดจำท่าทาง

แนวคิดหลัก: เซสชันการลาก (drag session), รายการลาก (drag items), ตัวอย่างลาก (drag preview — การแสดงภาพของวัตถุ), เป้าหมายวาง (drop target), ข้อเสนอวาง (drop proposal — การกระทำเมื่อวาง: ย้าย, คัดลอก, เชื่อมโยง) ระบบจัดการเซสชันในระดับระบบปฏิบัติการ ทำให้สามารถลากวัตถุระหว่างแอปพลิเคชันต่างๆ ได้ (เช่น รูปภาพจากแกลเลอรีไปยังบันทึก)

เฟสของการลากและวาง

การลากและวาง แบ่งออกเป็นสามเฟสตามลำดับ เฟสที่ 1 — การจับ (เริ่มลาก): ผู้ใช้เริ่มท่าทาง (โดยปกติคือการกดค้าง), ระบบสร้างเซสชันการลาก, จับข้อมูลของวัตถุ และแสดงตัวอย่างการลาก — สำเนากึ่งโปร่งใสขององค์ประกอบที่ตามนิ้ว ในเฟสนี้ ระบบจะปฏิเสธท่าทางอื่นๆ (การเลื่อน, การเลือกข้อความ) จนกว่า DnD จะเสร็จสมบูรณ์

เฟสที่ 2 — การเคลื่อนย้าย (การเคลื่อนที่ลาก): นิ้วเคลื่อนที่บนหน้าจอ ตัวอย่างการลากตามจุดสัมผัส ระบบจะระบุเป้าหมายวางใต้นิ้วอย่างต่อเนื่องและส่งเหตุการณ์ drag-enter, drag-move และ drag-exit เป้าหมายวางสามารถตอบสนองทางภาพ: ไฮไลต์ ขยาย หรือแสดงเส้นแทรก เฟสนี้ใช้เวลา 0.5 ถึง 10+ วินาที ขึ้นอยู่กับความซับซ้อนของงาน

เฟสที่ 3 — การปล่อย (การวาง): นิ้วยกขึ้นจากหน้าจอ ระบบสิ้นสุดเซสชันการลากและเรียก callback การวางบนองค์ประกอบเป้าหมาย หากเป้าหมายวางปฏิเสธการวาง (เช่น ลากไฟล์ไปยังโฟลเดอร์ที่ไม่มีสิทธิ์เขียน) ตัวอย่างการลากจะเคลื่อนไหวกลับไปยังตำแหน่งเดิม (การเคลื่อนไหวยกเลิก) หากการวางได้รับการยอมรับ องค์ประกอบจะหายไปจากตำแหน่งเดิมและปรากฏที่เป้าหมาย

เฟสเหตุการณ์ iOSเหตุการณ์ Androidสถานะทางภาพ
การจับUIDragInteractionDelegate.dragSessionWillBeginView.OnLongClickListener → startDragAndDropตัวอย่างการลากปรากฏใต้นิ้ว
การเคลื่อนย้ายUIDropInteractionDelegate.dragSessionDidUpdateView.OnDragListener.onDrag (ACTION_DRAG_MOVED)ตัวอย่างเคลื่อนที่ เป้าหมายถูกไฮไลต์
การปล่อยUIDropInteractionDelegate.performDropView.OnDragListener.onDrag (ACTION_DROP)การเคลื่อนไหววางหรือกลับ

การลากข้ามแอป เป็นฟังก์ชันที่พร้อมใช้งานบนทั้งสองแพลตฟอร์ม iOS รองรับการลากและวางระหว่างแอปในโหมด Split View และ Slide Over (iPad) Android รองรับการลากระหว่างแอปในโหมด Split Screen ข้อมูลถูกถ่ายโอนผ่าน UIPasteConfiguration (iOS) หรือ ClipData (Android) นักพัฒนาระบุประเภทข้อมูลที่รองรับ (UTI สำหรับ iOS, MIME สำหรับ Android)

การลากและวางบน iOS: UIDragInteraction

UIDragInteraction เป็น API หลักของ iOS สำหรับการลาก ซึ่งเพิ่มใน iOS 11 หากต้องการเปิดใช้งานการลากจาก View ให้เพิ่ม UIDragInteraction พร้อม UIDragInteractionDelegate ตัวแทนกำหนดว่าองค์ประกอบใดบ้างที่ลากได้ ลักษณะที่ปรากฏและพฤติกรรมขององค์ประกอบเหล่านั้น หากต้องการรับองค์ประกอบ ให้ใช้ UIDropInteraction พร้อม UIDropInteractionDelegate ซึ่งกำหนดว่า View สามารถยอมรับการวางได้หรือไม่และจะประมวลผลข้อมูลอย่างไร

swift
// UIDragInteraction — การลากองค์ประกอบจากคอลเล็กชัน
class DragViewController: UIViewController, UIDragInteractionDelegate {

    @IBOutlet var dragSourceView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        let dragInteraction = UIDragInteraction(delegate: self)
        dragSourceView.addInteraction(dragInteraction)
    }

    func dragInteraction(_ interaction: UIDragInteraction,
                          itemsForBeginning session: UIDragSession) -> [UIDragItem] {

        guard let data = Data(contentsOf: selectedFileURL) else { return [] }

        let itemProvider = NSItemProvider(object: data as NSData)
        let dragItem = UIDragItem(itemProvider: itemProvider)

        // ตัวอย่างการลาก — สำเนาที่ลดขนาดขององค์ประกอบ
        dragItem.previewProvider = {
            let previewView = UIImageView(image: thumbnailImage)
            previewView.alpha = 0.8
            return UIDragPreview(view: previewView)
        }
        return [dragItem]
    }
}

UIDropInteractionDelegate เป็นอินเทอร์เฟซสะท้อนสำหรับรับการวาง เมธอด canHandle(_:) ตรวจสอบว่าประเภทข้อมูลรองรับหรือไม่ sessionDidUpdate(_:) อัปเดตสถานะทางภาพ (ไฮไลต์, เส้นแทรก) performDrop(_:) ดำเนินการประมวลผลข้อมูลขั้นสุดท้าย iOS เรียก UIDropProposal โดยอัตโนมัติพร้อมประเภทการดำเนินการ: .move, .copy หรือ .forbidden ประเภทการดำเนินการส่งผลต่อการแสดงทางภาพ (ไอคอน + ที่มุมของตัวอย่างสำหรับการคัดลอก, เครื่องหมายห้ามสำหรับ forbidden)

การลากและวางบน Android: startDragAndDrop

View.startDragAndDrop() เป็นเมธอด Android SDK สำหรับเริ่มการลาก ซึ่งพร้อมใช้งานตั้งแต่ API 24 (Android 7.0) ถูกเรียกหลังจากจับองค์ประกอบ (โดยปกติใน onLongClick) พารามิเตอร์: ClipData (ข้อมูล), DragShadowBuilder (เงาที่มองเห็น), Object myLocalState (สถานะภายใน), flags DragShadowBuilder สร้าง Bitmap ที่ตามนิ้ว ระบบจัดการการเคลื่อนไหวและเหตุการณ์สัมผัสโดยอัตโนมัติระหว่างการลาก

kotlin
// การลากและวางขององค์ประกอบ RecyclerView พร้อมการจัดลำดับใหม่
class ReorderAdapter(private val items: MutableList<String>) :
    RecyclerView.Adapter<ReorderAdapter.ViewHolder>() {

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.itemView.setOnLongClickListener {
            // การสร้าง ClipData สำหรับการถ่ายโอนข้อมูล
            val clipData = ClipData.newPlainText("item", items[position])

            // DragShadowBuilder ที่กำหนดเองพร้อมตัวอย่างที่ลดขนาด
            val shadowBuilder = object : View.DragShadowBuilder(holder.itemView) {
                override fun onProvideShadowMetrics(shadowSize: Point, shadowTouchPoint: Point) {
                    shadowSize.set(itemView.width, itemView.height / 2)
                }
            }

            holder.itemView.startDragAndDrop(clipData, shadowBuilder, position, 0)
            true
        }
    }
}

การรับการวาง บน Android ถูกนำไปใช้ผ่าน View.setOnDragListener() ตัวฟังรับเหตุการณ์ ACTION_DRAG_STARTED, ACTION_DRAG_ENTERED, ACTION_DRAG_LOCATION, ACTION_DRAG_EXITED, ACTION_DROP และ ACTION_DRAG_ENDED ในเหตุการณ์ ACTION_DROP ข้อมูลจะถูกแยกจาก ClipData และดำเนินการตามเป้าหมาย สำหรับ RecyclerView ที่มีการจัดลำดับใหม่ แนะนำให้ใช้ ItemTouchHelper.SimpleCallback — กลไกในตัวที่จัดการการกดค้างสำหรับการจับ การเคลื่อนไหว และเมธอดอรรถประโยชน์ onMove/onSwiped โดยอัตโนมัติ

กรณีการใช้งานการลากและวาง

การจัดลำดับรายการใหม่ (drag to reorder) เป็นสถานการณ์ DnD ที่พบบ่อยที่สุด: ผู้ใช้ลากรายการในรายการเพื่อเปลี่ยนลำดับ ตัวอย่าง: จัดเรียงรายชื่อในรายการโปรดใหม่, จัดเรียงงานในตัวติดตาม (Trello, Todoist), จัดลำดับเพลงในเพลย์ลิสต์ใหม่ (Spotify, Apple Music) ถูกนำไปใช้ผ่าน ItemTouchHelper บน Android หรือ UILongPressGestureRecognizer พร้อมการจัดเรียงเซลล์ใหม่บน iOS

ตัวจัดการไฟล์ — การลากและวางสำหรับคัดลอกและย้ายไฟล์ระหว่างโฟลเดอร์ iOS Files App, Android Files by Google, Dropbox — ทั้งหมดรองรับ DnD การลากไฟล์ไปยังโฟลเดอร์จะย้ายเข้าไปข้างใน (move) การลากขณะกด Option/Ctrl ค้างจะคัดลอก (copy) เป้าหมายวางจะถูกไฮไลต์ทางภาพเมื่อเลื่อนผ่าน แสดงขอบเขตของโฟลเดอร์

บอร์ด Kanban — Trello, Jira, Notion ใช้การลากและวางเพื่อย้ายการ์ดระหว่างคอลัมน์ (To Do → In Progress → Done) เมื่อลาก การ์ดจะแยกจากคอลัมน์ต้นทาง ตามนิ้ว และเมื่อข้ามขอบเขตของอีกคอลัมน์หนึ่ง จะแทรกด้วยการเคลื่อนไหว iOS 11+ รองรับ UIDragPreview พร้อมเอฟเฟกต์พารัลแลกซ์ โดยที่ตัวอย่างจะเอียงเล็กน้อยจากจุดสัมผัส สร้างความลึก

ส่วน Springboard (iOS) — การลากไอคอนแอปบนหน้าจอหลักของ iOS การกดไอคอนค้างจะเปิดใช้งานโหมด “สั่น” (ไอคอนสั่น) หลังจากนั้นผู้ใช้สามารถย้ายไอคอนระหว่างหน้าและสร้างโฟลเดอร์ได้ นี่เป็นหนึ่งในรูปแบบ UX DnD ที่ซับซ้อนที่สุด เนื่องจากต้องจัดการการลาก การเคลื่อนไหวสั่น และการจัดกลุ่มเป็นโฟลเดอร์พร้อมกัน

คำแนะนำ UX สำหรับการลากและวาง

การตอบกลับทางภาพ มีความสำคัญอย่างยิ่งสำหรับการลากและวาง วัตถุที่ถูกลากควรเปลี่ยนแปลง: หดลง (iOS: สเกล 0.8–0.9), กลายเป็นกึ่งโปร่งใส (alpha 0.7–0.8), และยกขึ้นเหนืออินเทอร์เฟซด้วยเงา (shadow offset) เป้าหมายวางควรตอบสนองทางภาพเมื่อเลื่อนผ่าน: ไฮไลต์ ขยาย หรือแสดงขอบ หากไม่มีสัญญาณเหล่านี้ ผู้ใช้จะไม่ทราบว่าสามารถวางวัตถุได้ที่ไหน

การเคลื่อนไหวกลับ (ยกเลิกการลาก) — หากผู้ใช้ปล่อยองค์ประกอบนอกโซนวางหรือบนโซนที่ไม่ถูกต้อง วัตถุควรเคลื่อนไหวกลับไปยังตำแหน่งเดิม iOS UIDragInteractionDelegate มี dragInteraction(_:sessionDidMove:) สำหรับการติดตาม และ dragInteraction(_:session:willEndWith:) สำหรับการเคลื่อนไหวกลับ Android View.setOnDragListener ได้รับ ACTION_DRAG_ENDED ซึ่งสามารถเริ่มการเคลื่อนไหวกลับผ่าน ValueAnimator หรือ ObjectAnimator

คำแนะนำiOSAndroid
การจับด้วยท่าทางกดค้าง (ค่าเริ่มต้น)OnLongClickListener
ตัวอย่างลากUIDragItem.previewProviderDragShadowBuilder
การตอบกลับแบบสัมผัสUIImpactFeedbackGeneratorHapticFeedbackConstants.LONG_PRESS
การเคลื่อนไหวกลับUIDragPreviewTargetViewPropertyAnimator
ข้อเสนอวางUIDropProposal (.move/.copy)ACTION_DROP + ธง
DnD ข้ามแอปiOS 11+ Split View (iPad)Android 7.0+ Split Screen

การเข้าถึง: ผู้ใช้ที่มีข้อจำกัดด้านการเคลื่อนไหวอาจไม่สามารถทำท่าทางลากได้ ให้ทางเลือกผ่านปุ่ม “ย้ายขึ้น/ลง” สำหรับรายการ และเมนูบริบท “ย้ายไปยังโฟลเดอร์” สำหรับไฟล์ iOS VoiceOver รองรับการดำเนินการโรเตอร์ “ลาก” สำหรับการย้ายองค์ประกอบ Android TalkBack ให้การดำเนินการที่กำหนดเองผ่าน AccessibilityNodeInfo.addAction() Nike Run Club และ Apple Health ใช้ DnD เพื่อจัดลำดับเมตริกบนแดชบอร์ดใหม่ — ด้วยการเข้าถึงผ่านปุ่มมาตรฐาน

คำถามที่พบบ่อย

ใช้ท่าทางใดในการเริ่มต้นการลากและวาง?

ท่าทางมาตรฐานสำหรับเริ่ม การลากและวาง คือการกดค้าง 300–500 มิลลิวินาที iOS ใช้กลไก UIDragInteraction ในตัวที่แปลงการแตะแบบต่อเนื่องเป็นการจับโดยอัตโนมัติ Android ต้องการการเรียก startDragAndDrop() อย่างชัดเจนใน callback OnLongClickListener ในบางกรณี (เช่น เกม) DnD สามารถเริ่มด้วยการแตะธรรมดาโดยไม่มีความล่าช้า

สามารถลากวัตถุระหว่างแอปพลิเคชันต่างๆ ได้หรือไม่?

ได้ การลากและวางข้ามแอป รองรับบน iOS 11+ (iPad) และ Android 7.0+ บน iPad การลากทำงานในโหมด Split View และ Slide Over — ผู้ใช้สามารถนำข้อความจาก Safari และวางในบันทึกได้ บน Android DnD ระหว่างแอปทำงานใน Split Screen ข้อมูลถูกถ่ายโอนผ่าน UIPasteConfiguration (iOS) หรือ ClipData (Android) พร้อมประเภทที่รองรับที่ระบุ (UTI, MIME)

จะป้องกันข้อขัดแย้งระหว่างการลากและวางกับการเลื่อนได้อย่างไร?

ข้อขัดแย้ง DnD และการเลื่อน ได้รับการแก้ไขผ่านการหน่วงเวลาการจับ หากผู้ใช้เริ่มขยับนิ้วก่อนที่การหมดเวลากดค้าง (500 มิลลิวินาที) จะสิ้นสุด ท่าทางจะถูกตีความว่าเป็นการเลื่อนมากกว่าการลากและวาง บน iOS UIDragInteraction จัดการข้อขัดแย้งนี้โดยอัตโนมัติผ่าน cancelsTouchesInView บน Android ItemTouchHelper ใช้เกณฑ์ — หากการเคลื่อนไหวเกินเกณฑ์ TouchSlop การกดค้างจะถูกยกเลิกเพื่อให้การเลื่อน優先

ข้อมูลใดที่สามารถถ่ายโอนเมื่อลาก?

การลากและวาง รองรับข้อมูลทุกประเภท: ข้อความ, รูปภาพ, ไฟล์, URL, วัตถุที่กำหนดเอง iOS ใช้ NSItemProvider พร้อมประเภท UTI (public.text, public.image, public.file-url) Android ใช้ ClipData พร้อมประเภท MIME (text/plain, image/png, application/octet-stream) สำหรับข้อมูลที่กำหนดเอง จะสร้าง ClipData.Item พร้อม Intent สำหรับ DnD ข้ามแอป ข้อมูลจะถูกบรรจุในรูปแบบสากล: ข้อความธรรมดา, HTML, RTF, UIImage/PNG

จะเคลื่อนไหวการกลับขององค์ประกอบเมื่อยกเลิกการลากและวางได้อย่างไร?

บน iOS การเคลื่อนไหวกลับถูกจัดการผ่าน UIDragPreviewTarget — ตำแหน่งสุดท้ายที่ตัวอย่างเคลื่อนไหวกลับไป บน Android ใช้ ViewPropertyAnimator พร้อม translateX/translateY เพื่อนำองค์ประกอบกลับไปยังตำแหน่งเดิม ระยะเวลาการเคลื่อนไหวคือ 200–300 มิลลิวินาทีพร้อมเส้นโค้ง easing (EaseOut) UIKit เพิ่ม UIDragPreview พร้อมเอฟเฟกต์พารัลแลกซ์โดยอัตโนมัติ ซึ่งกลับมาอย่างนุ่มนวลเมื่อท่าทางถูกยกเลิก

สรุป

  • การลากและวาง — วิธีการลากวัตถุสามเฟส: จับ, เคลื่อนย้าย, ปล่อย
  • การเริ่มต้น — โดยปกติผ่านการกดค้าง (300–500 มิลลิวินาที) เพื่อแยกความแตกต่างจากการเลื่อน
  • API iOS — UIDragInteraction (แหล่ง) + UIDropInteraction (ตัวรับ)
  • API Android — View.startDragAndDrop() (แหล่ง) + View.setOnDragListener (ตัวรับ)
  • ItemTouchHelper — โซลูชัน Android พร้อมใช้สำหรับการจัดลำดับใหม่ใน RecyclerView
  • ตัวอย่างลาก — เงาที่มองเห็นของวัตถุตามนิ้วด้วยความกึ่งโปร่งใส
  • การเคลื่อนไหวกลับ — จำเป็นเมื่อวางนอกโซนที่ถูกต้องเพื่อ UX ที่ชัดเจน

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม