Kéo và thả đơn giản hơn nhờ DropHelper

Lớp DropHelper đơn giản hoá triển khai chức năng kéo và thả. Là một phần của thư viện Jetpack DragAndDrop, DropHelper hỗ trợ tương thích ngược đến cấp API 24.

Hãy dùng DropHelper để chỉ định các mục tiêu thả, tuỳ chỉnh việc làm nổi bật mục mục tiêu thả và xác định cách xử lý dữ liệu được thả.

Đặt nguồn kéo

Để bắt đầu, hãy tạo DragStartHelper với chế độ xem nguồn khi kéo và OnDragStartListener.

Tại OnDragStartListener, phương thức ghi đè onDragStart(). Tạo đối tượng ClipData và đối tượng ClipData.Item cho dữ liệu đang được di chuyển. Trong ClipData, cung cấp siêu dữ liệu được lưu trữ trong đối tượng ClipDescription bên trong ClipData. Đối với thao tác kéo và thả không biểu thị di chuyển dữ liệu, bạn có thể muốn sử dụng null thay vì một đối tượng thực tế.

Kotlin

DragStartHelper(draggableView)
    { view: View, _: DragStartHelper ->
        val item = ClipData.Item(view.tag as? CharSequence)
        val dragData = ClipData(
            view.tag as? CharSequence,
            arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN),
            item
        )
        view.startDragAndDrop(
            dragData,
            View.DragShadowBuilder(view),
            null,
            0
        )
    }.attach()

Java

new DragStartHelper(draggableView, new DragStartHelper.OnDragStartListener() {
    @Override
    public void onDragStart(View view, DragStartHelper helper) {
        CharSequence tag = (CharSequence) view.getTag();
        ClipData.Item item = new ClipData.Item(tag);
        ClipData dragData = new ClipData(
          tag, new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}, item);
        view.startDragAndDrop(
          dragData, new View.DragShadowBuilder(view), null, 0);
    }
});

Chỉ định các mục tiêu thả

Khi người dùng thả bóng đổ trên một khung hiển thị, bạn cần định cấu hình khung hiển thị đó để chấp nhận dữ liệu và phản hồi chính xác.

DropHelper.configureView() là một phương thức tĩnh, nạp chồng cho phép bạn chỉ định các mục tiêu thả. tham số bao gồm:

Ví dụ: để tạo mục tiêu thả chấp nhận hình ảnh, hãy sử dụng một trong các lệnh gọi phương thức sau:

Kotlin

configureView(
    myActivity,
    targetView,
    arrayOf("image/*"),
    options,
    onReceiveContentListener)

// or

configureView(
    myActivity,
    targetView,
    arrayOf("image/*"),
    onReceiveContentListener)

Java

DropHelper.configureView(
    myActivity,
    targetView,
    new String[] {"image/*"},
    options,
    onReceiveContentlistener);

// or

DropHelper.configureView(
    myActivity,
    targetView,
    new String[] {"image/*"},
    onReceiveContentlistener);

Lệnh gọi thứ hai bỏ qua các tuỳ chọn cấu hình mục tiêu thả, trong trường hợp đó màu làm nổi bật của mục tiêu thả được đặt thành màu phụ (hoặc màu nhấn) của giao diện, bán kính góc đánh dấu được đặt thành 16 dp và danh sách EditText trống. Hãy xem phần sau để biết thông tin chi tiết.

Định cấu hình mục tiêu thả

DropHelper.Options lớp bên trong cho phép bạn định cấu hình các mục tiêu thả. Cung cấp một thực thể của lớp cho DropHelper.configureView(Activity, View, String[], Options, OnReceiveContentListener) . Hãy xem phần trước để biết thêm thông tin.

Tuỳ chỉnh tính năng làm nổi bật mục tiêu thả

DropHelper định cấu hình các mục tiêu thả để hiển thị vùng nổi bật khi người dùng kéo nội dung lên trên mục tiêu thả. DropHelper cung cấp kiểu mặc định, và DropHelper.Options cho phép bạn đặt màu của phần đánh dấu và chỉ định bán kính góc của hình chữ nhật được đánh dấu.

Sử dụng DropHelper.Options.Builder để tạo một phiên bản DropHelper.Options và đặt các tuỳ chọn cấu hình, như trong ví dụ sau:

Kotlin

val options: DropHelper.Options = DropHelper.Options.Builder()
                                      .setHighlightColor(getColor(R.color.purple_300))
                                      .setHighlightCornerRadiusPx(resources.getDimensionPixelSize(R.dimen.drop_target_corner_radius))
                                      .build()

Java

DropHelper.Options options = new DropHelper.Options.Builder()
                                     .setHighlightColor(getColor(R.color.purple_300))
                                     .setHighlightCornerRadiusPx(getResources().getDimensionPixelSize(R.dimen.drop_target_corner_radius))
                                     .build();

Xử lý các thành phần EditText trong mục tiêu thả

DropHelper cũng kiểm soát tiêu điểm trong mục tiêu thả khi mục tiêu chứa trường văn bản có thể chỉnh sửa.

Mục tiêu thả có thể là một thành phần hiển thị hoặc hệ phân cấp thành phần hiển thị. Nếu khung hiển thị mục tiêu thả hệ phân cấp chứa một hoặc nhiều EditText thành phần, cung cấp danh sách các thành phần để DropHelper.Options.Builder.addInnerEditTexts(EditText...) để đảm bảo rằng việc làm nổi bật mục tiêu thả và xử lý dữ liệu văn bản hoạt động chính xác.

DropHelper ngăn chặn các thành phần EditText trong khung hiển thị mục tiêu thả hệ thống phân cấp sao cho không đánh cắp tiêu điểm khỏi khung hiển thị vùng chứa trong các tương tác kéo.

Ngoài ra, nếu thao tác kéo và thả ClipData bao gồm dữ liệu văn bản và URI, DropHelper sẽ chọn một trong EditText thành phần trong mục tiêu thả để xử lý dữ liệu văn bản. Lựa chọn dựa trên thứ tự ưu tiên sau:

  1. EditText nơi ClipData được thả.
  2. EditText chứa con trỏ văn bản (con nháy).
  3. EditText đầu tiên được cung cấp cho cuộc gọi đến DropHelper.Options.Builder.addInnerEditTexts(EditText...)

Để đặt EditText làm trình xử lý dữ liệu văn bản mặc định, hãy truyền EditText làm đối số đầu tiên của lệnh gọi tới DropHelper.Options.Builder.addInnerEditTexts(EditText...). Ví dụ: nếu mục tiêu thả của bạn xử lý hình ảnh nhưng chứa các trường văn bản có thể chỉnh sửa T1, T2T3, hãy đặt T2 làm mặc định như sau:

Kotlin

val options: DropHelper.Options = DropHelper.Options.Builder()
                                      .addInnerEditTexts(T2, T1, T3)
                                      .build()

Java

DropHelper.Options options = new DropHelper.Options.Builder()
                                     .addInnerEditTexts(T2, T1, T3)
                                     .build();

Xử lý dữ liệu trong các mục tiêu thả

Phương thức DropHelper.configureView() chấp nhận OnReceiveContentListener mà bạn tạo để xử lý ClipData kéo và thả. Dữ liệu kéo và thả được cung cấp cho trình nghe trong một Đối tượng ContentInfoCompat. Dữ liệu văn bản đã có trong đối tượng. Nội dung nghe nhìn, chẳng hạn như hình ảnh, được thể hiện bằng URI.

OnReceiveContentListener cũng xử lý dữ liệu được cung cấp cho mục tiêu thả bằng cách các tương tác của người dùng khác ngoài thao tác kéo và thả (chẳng hạn như sao chép và dán – khi DropHelper.configureView() được dùng để định cấu hình các đoạn mã sau loại lượt xem:

  • Tất cả khung hiển thị, nếu người dùng đang chạy Android 12 trở lên.
  • AppCompatEditText! nếu người dùng đang chạy phiên bản Android từ Android 7.0 trở xuống.

Loại MIME, quyền và xác thực nội dung

Việc kiểm tra loại MIME của DropHelper dựa trên thao tác kéo và thả ClipDescription, tức là do ứng dụng cung cấp dữ liệu kéo và thả tạo ra. Xác thực ClipDescription để đảm bảo loại MIME được thiết lập chính xác.

DropHelper yêu cầu tất cả các quyền truy cập đối với các URI nội dung có trong kéo và thả ClipData. Để biết thêm thông tin, hãy xem DragAndDropPermissions. Chiến lược phát hành đĩa đơn cho phép bạn phân giải các URI nội dung khi xử lý thao tác kéo và thả .

DropHelper không xác thực dữ liệu do nhà cung cấp nội dung trả về khi phân giải URI trong dữ liệu được thả. Kiểm tra giá trị rỗng và xác minh tính chính xác của mọi dữ liệu đã phân giải.