Các phần sau đây giải thích một số khái niệm chính về quy trình kéo và thả.
Quy trình kéo và thả
Có 4 bước hoặc trạng thái trong quá trình kéo và thả: đã bắt đầu, tiếp tục, bỏ qua và kết thúc.
- Started (Đã khởi động)
Để phản hồi cử chỉ kéo của người dùng, ứng dụng của bạn sẽ gọi
startDragAndDrop()
để yêu cầu hệ thống bắt đầu thao tác kéo và thả. Chiến lược phát hành đĩa đơn các đối số của phương thức cung cấp những nội dung sau:- Dữ liệu cần kéo.
- Lệnh gọi lại để vẽ bóng khi kéo
- Siêu dữ liệu mô tả dữ liệu đã kéo
- Hệ thống sẽ phản hồi bằng cách gọi lại ứng dụng của bạn để yêu cầu kéo bóng. Sau đó, hệ thống sẽ hiển thị bóng khi kéo trên thiết bị.
- Tiếp theo, hệ thống sẽ gửi một sự kiện kéo kèm theo loại thao tác
ACTION_DRAG_STARTED
đến sự kiện kéo trình nghe của tất cả đối tượngView
trong bố cục hiện tại. Người nhận tiếp tục nhận được các sự kiện kéo—bao gồm cả khả năng thả sự kiện – trình nghe sự kiện kéo phải trả vềtrue
. Thanh ghi này trình nghe cùng với hệ thống. Chỉ những người nghe đã đăng ký mới tiếp tục nhận các sự kiện kéo. Tại thời điểm này, người nghe cũng có thể thay đổi của đối tượngView
đích thả để cho thấy rằng thành phần hiển thị này có thể chấp nhận sự kiện thả. - Nếu trình nghe sự kiện kéo trả về
false
, thì trình nghe sự kiện kéo này sẽ không nhận được thao tác kéo các sự kiện cho thao tác hiện tại cho đến khi hệ thống gửi sự kiện kéo với loại hành độngACTION_DRAG_ENDED
. Khi trả vềfalse
, trình nghe sẽ cho hệ thống biết rằng ứng dụng không quan tâm trong thao tác kéo và thả và không muốn chấp nhận dữ liệu đã kéo.
- Đang tiếp tục
- Người dùng tiếp tục kéo. Khi bóng khi kéo giao với
hộp giới hạn của mục tiêu thả, hệ thống sẽ gửi một hoặc nhiều sự kiện kéo đến
trình nghe sự kiện kéo của mục tiêu. Trình nghe có thể thay đổi giao diện của
mục tiêu thả
View
để phản hồi sự kiện. Ví dụ: nếu sự kiện cho biết bóng khi kéo đi vào hộp giới hạn của hộp thả loại hành động mục tiêuACTION_DRAG_ENTERED
— trình nghe có thể phản ứng bằng cách làm nổi bậtView
. - Thả
- Người dùng thả bóng khi kéo trong hộp giới hạn của hộp thả
. Hệ thống gửi một sự kiện kéo kèm theo thao tác cho trình nghe của mục tiêu thả
loại
ACTION_DROP
. Đối tượng sự kiện kéo chứa dữ liệu truyền đến hệ thống trong gọi đếnstartDragAndDrop()
để bắt đầu thao tác. Trình nghe là dự kiến sẽ trả về giá trị booleantrue
cho hệ thống nếu trình nghe thành công xử lý dữ liệu được thả. : Bước này chỉ xảy ra nếu người dùng thả bóng khi kéo trong hộp giới hạn củaView
có trình nghe được đăng ký để nhận các sự kiện kéo (mục tiêu thả). Nếu người dùng thả bóng khi kéo trong bất kỳ không có sự kiện kéoACTION_DROP
nào được gửi. - Đã kết thúc
Sau khi người dùng thả bóng khi kéo và sau khi hệ thống gửi
một sự kiện kéo bằng loại thao tác
ACTION_DROP
, nếu cần, hệ thống sẽ gửi một sự kiện kéo có loại thao tácACTION_DRAG_ENDED
để cho biết rằng thao tác kéo và thả đã kết thúc. Thực hiện việc này bất kể người dùng đang ở đâu thả bóng khi kéo. Sự kiện này sẽ được gửi đến mọi trình nghe đã đăng ký nhận các sự kiện kéo, ngay cả khi trình nghe cũng nhận được Sự kiệnACTION_DROP
.
Mỗi bước trong số này được mô tả chi tiết hơn trong phần có tên là Thao tác kéo và thả.
Sự kiện kéo
Hệ thống sẽ gửi một sự kiện kéo ở dạng đối tượng DragEvent
. Sự kiện này
chứa loại thao tác mô tả những gì sẽ diễn ra trong thao tác kéo và thả
của chúng tôi. Tuỳ thuộc vào loại thao tác mà đối tượng cũng có thể chứa dữ liệu khác.
Trình nghe sự kiện kéo sẽ nhận đối tượng DragEvent
. Để biết loại thao tác, trình nghe gọi DragEvent.getAction()
.
Có 6 giá trị có thể được xác định bằng các hằng số trong lớp DragEvent
,
được mô tả trong bảng 1:
Loại thao tác | Ý nghĩa |
---|---|
ACTION_DRAG_STARTED |
Ứng dụng gọi startDragAndDrop() và nhận
bóng khi kéo. Nếu trình nghe muốn tiếp tục nhận các sự kiện kéo
cho thao tác này, nó phải trả về giá trị boolean true cho
hệ thống.
|
ACTION_DRAG_ENTERED |
Bóng khi kéo đi vào hộp giới hạn của
View . Đây là loại thao tác sự kiện đầu tiên mà trình nghe
nhận được khi bóng khi kéo đi vào hộp giới hạn.
|
ACTION_DRAG_LOCATION |
Sau một
ACTION_DRAG_ENTERED sự kiện, bóng khi kéo vẫn là
trong hộp giới hạn của trình nghe sự kiện kéo
View
|
ACTION_DRAG_EXITED |
Đang theo dõi ACTION_DRAG_ENTERED và ít nhất một
Sự kiện ACTION_DRAG_LOCATION , bóng khi kéo sẽ di chuyển
bên ngoài hộp giới hạn của trình nghe sự kiện kéo
View .
|
ACTION_DROP |
Bóng khi kéo thả ra trên trình nghe sự kiện kéo
View . Loại thao tác này được gửi đến View
trình nghe của đối tượng chỉ khi trình nghe trả về boolean
true để phản hồi
Sự kiện kéo ACTION_DRAG_STARTED . Loại hành động này không
được gửi nếu người dùng thả bóng khi kéo trên View
có trình nghe chưa được đăng ký hoặc nếu người dùng thả thao tác kéo
đổ bóng lên bất kỳ mục nào không thuộc bố cục hiện tại.
Trình nghe sẽ trả về giá trị boolean |
ACTION_DRAG_ENDED |
Hệ thống đang kết thúc thao tác kéo và thả. Loại hành động này
không nhất thiết phải đứng sau sự kiện ACTION_DROP . Nếu
hệ thống sẽ gửi một ACTION_DROP , nhận
Loại hành động ACTION_DRAG_ENDED không ngụ ý rằng
thả thành công. Trình nghe phải gọi
getResult() ,
như minh hoạ trong bảng 2 để nhận giá trị
được trả về nhằm phản hồi ACTION_DROP . Nếu một
ACTION_DROP sự kiện chưa được gửi, sau đó
getResult() trả về false .
|
Đối tượng DragEvent
cũng chứa dữ liệu và siêu dữ liệu mà ứng dụng của bạn
cung cấp cho hệ thống trong lệnh gọi đến startDragAndDrop()
. Một số dữ liệu là
chỉ hợp lệ đối với một số loại hành động nhất định như được tóm tắt trong bảng 2. Để biết thêm
thông tin về các sự kiện và dữ liệu liên quan, hãy xem phần có tên là A
thao tác kéo và thả.
Giá trị getAction() |
Giá trị getClipDescription() |
Giá trị getLocalState() |
Giá trị getX() |
Giá trị getY() |
Giá trị getClipData() |
Giá trị getResult() |
---|---|---|---|---|---|---|
ACTION_DRAG_STARTED |
✓ | ✓ | ||||
ACTION_DRAG_ENTERED |
✓ | ✓ | ||||
ACTION_DRAG_LOCATION |
✓ | ✓ | ✓ | ✓ | ||
ACTION_DRAG_EXITED |
✓ | ✓ | ||||
ACTION_DROP |
✓ | ✓ | ✓ | ✓ | ✓ | |
ACTION_DRAG_ENDED |
✓ | ✓ |
Các phương thức DragEvent
getAction()
,
describeContents()
!
writeToParcel()
thân mến!
và toString()
luôn
sẽ trả về dữ liệu hợp lệ.
Nếu không chứa dữ liệu hợp lệ cho một loại thao tác cụ thể thì phương thức đó sẽ trả về
null
hoặc 0, tuỳ thuộc vào loại kết quả.
Bóng khi kéo
Trong suốt thao tác kéo và thả, hệ thống sẽ hiển thị hình ảnh mà người dùng kéo. Đối với di chuyển dữ liệu, hình ảnh này đại diện cho dữ liệu đang được kéo. Đối với các thao tác khác, hình ảnh đại diện cho một số chương trình thành phần của thao tác kéo.
Hình ảnh này được gọi là bóng khi kéo. Bạn tạo ứng dụng bằng các phương thức mà bạn khai báo
một
View.DragShadowBuilder
. Bạn truyền trình tạo đến hệ thống khi bắt đầu kéo và thả
bằng startDragAndDrop()
. Để phản hồi lại
startDragAndDrop()
, hệ thống sẽ gọi các phương thức gọi lại mà bạn xác định trong
View.DragShadowBuilder
để lấy bóng khi kéo.
Lớp View.DragShadowBuilder
có hai hàm khởi tạo (constructor):
View.DragShadowBuilder(View)
Hàm khởi tạo này chấp nhận mọi đối tượng
View
của ứng dụng. Hàm khởi tạo lưu trữ đối tượngView
trong đối tượngView.DragShadowBuilder
, vì vậy, các lệnh gọi lại có thể truy cập vào đối tượng đó để tạo bóng khi kéo. Chế độ xem không nhất thiết phải làView
mà người dùng chọn để bắt đầu thao tác kéo.Nếu sử dụng hàm khởi tạo này, bạn không cần phải mở rộng
View.DragShadowBuilder
hoặc ghi đè phương thức của hàm khởi tạo. Theo mặc định, bạn sẽ chọn thao tác kéo bóng có cùng hình thức vớiView
mà bạn truyền dưới dạng đối số, chính giữa bên dưới vị trí người dùng chạm vào màn hình.View.DragShadowBuilder()
Nếu bạn sử dụng hàm khởi tạo này, sẽ không có đối tượng
View
nào trong Đối tượngView.DragShadowBuilder
. Trường này được đặt thànhnull
. Bạn phải mở rộngView.DragShadowBuilder
rồi ghi đè các phương thức của đối tượng đó, nếu không, bạn sẽ nhận được bóng khi kéo vô hình. Hệ thống không báo lỗi.
Lớp View.DragShadowBuilder
có 2 phương thức để tạo ra thao tác kéo
bóng:
onProvideShadowMetrics()
Hệ thống sẽ gọi phương thức này ngay sau khi bạn gọi
startDragAndDrop()
. Sử dụng phương thức để gửi kích thước và điểm chạm của bóng khi kéo đến hệ thống. Phương thức có hai tham số:outShadowSize
:Point
. Chiều rộng của bóng khi kéo làx
và chiều cao của nó tương ứng vớiy
.outShadowTouchPoint
: đối tượngPoint
. Điểm tiếp xúc là vị trí trong bóng khi kéo phải ở dưới ngón tay của người dùng trong khi kéo. Vị trí X của tín hiệu tương ứng vớix
và vị trí Y rơi vàoy
.onDrawShadow()
Ngay sau khi gọi
onProvideShadowMetrics()
, hệ thống sẽ gọionDrawShadow()
để tạo bóng khi kéo. Phương thức này có một đối số, một đối tượngCanvas
hệ thống xây dựng từ các tham số mà bạn cung cấp trongonProvideShadowMetrics()
. Phương thức này sẽ vẽ bóng khi kéo trênCanvas
.
Để cải thiện hiệu suất, hãy giữ kích thước của bóng khi kéo nhỏ. Cho một người độc thân bạn nên sử dụng biểu tượng. Để chọn nhiều mục, bạn có thể muốn sử dụng các biểu tượng trong một ngăn xếp thay vì hình ảnh toàn bộ trải rộng trên màn hình.
Trình nghe sự kiện kéo và phương thức gọi lại
View
nhận các sự kiện kéo bằng trình nghe sự kiện kéo để triển khai
View.OnDragListener
hoặc bằng phương thức gọi lại onDragEvent()
của khung hiển thị. Thời gian
hệ thống gọi phương thức hoặc trình nghe, nó cung cấp một
Đối số DragEvent
.
Trong hầu hết trường hợp, bạn nên sử dụng trình nghe thay vì phương thức gọi lại. Khi thiết kế giao diện người dùng, bạn thường không phân lớp các lớp View
, nhưng khi sử dụng phương thức gọi lại, bạn sẽ phải tạo các lớp con để ghi đè phương thức. Khi so sánh, bạn có thể triển khai một lớp trình nghe rồi sử dụng lớp đó với nhiều đối tượng View
riêng biệt. Bạn cũng có thể triển khai lớp này dưới dạng một lớp cùng dòng ẩn danh
hoặc biểu thức lambda. Để thiết lập trình nghe cho đối tượng View
, hãy gọi
setOnDragListener()
Thay vào đó, bạn có thể thay đổi cách triển khai mặc định của onDragEvent()
mà không cần ghi đè phương thức. Đặt một
OnReceiveContentListener
trên một khung hiển thị; để biết thêm chi tiết, hãy xem
setOnReceiveContentListener()
.
Sau đó, phương thức onDragEvent()
sẽ thực hiện những thao tác sau theo mặc định:
- Trả về giá trị true để phản hồi lệnh gọi đến
startDragAndDrop()
. Cuộc gọi
performReceiveContent()
nếu dữ liệu kéo và thả được thả vào khung hiển thị. Dữ liệu được chuyển đến làm đối tượngContentInfo
. Chiến lược phát hành đĩa đơn sẽ gọiOnReceiveContentListener
.Trả về true nếu dữ liệu kéo và thả được thả vào khung hiển thị và
OnReceiveContentListener
sử dụng bất kỳ nội dung nào.
Xác định OnReceiveContentListener
để xử lý dữ liệu dành riêng cho
. Để có khả năng tương thích ngược xuống đến API cấp 24, hãy sử dụng phiên bản Jetpack
OnReceiveContentListener
.
Bạn có thể có một trình nghe sự kiện kéo và phương thức gọi lại cho đối tượng View
trong
trong trường hợp này, hệ thống sẽ gọi trình nghe trước tiên. Hệ thống không gọi hàm
trừ phi trình nghe trả về false
.
Tổ hợp phương thức onDragEvent()
và View.OnDragListener
là
tương tự như sự kết hợp của
onTouchEvent()
và View.OnTouchListener
được dùng với các sự kiện chạm.