Kéo và thả đơn giản hơn với DropHelper

Lớp DropHelper giúp đơn giản hoá việc triển khai các tính 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 tính năng kéo nguồn

Để bắt đầu, hãy tạo DragStartHelper bằng thao tác kéo khung hiển thị nguồn và OnDragStartListener.

Trong OnDragStartListener, hãy ghi đè phương thức onDragStart(). Tạo một đối tượng ClipData và đối tượng ClipData.Item cho dữ liệu đang được di chuyển. Là một phần của ClipData, siêu dữ liệu cung cấp được lưu trữ trong đối tượng ClipDescription trong ClipData. Đối với thao tác kéo và thả không đại diện cho việc di chuyển dữ liệu, bạn nê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 mục tiêu thả

Khi người dùng thả bóng đổ trên một khung hiển thị, khung hiển thị đó cần được định cấu hình đúng cách để 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ả. Các tham số của lớp này 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 đánh dấu 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 các thành phần 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ả

Lớp DropHelper.Options 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 phương thức DropHelper.configureView(Activity, View, String[], Options, OnReceiveContentListener). Xem phần trước để biết thêm thông tin.

Tuỳ chỉnh tính năng đánh dấu 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 vùng nổi bật và chỉ định bán kính góc của hình chữ nhật được làm nổi bật.

Sử dụng lớp DropHelper.Options.Builder để tạo một thực thể 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 các 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 hệ phân cấp khung hiển thị mục tiêu thả chứa một hoặc nhiều thành phần EditText, hãy cung cấp danh sách các thành phần cho DropHelper.Options.Builder.addInnerEditTexts(EditText...) để đảm bảo rằng việc đánh dấu mục tiêu thả và xử lý dữ liệu văn bản hoạt động đúng cách.

DropHelper ngăn các thành phần EditText trong hệ phân cấp khung hiển thị mục tiêu thả đánh cắp tiêu điểm từ khung hiển thị vùng chứa trong các hoạt động tương tác kéo.

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

  1. EditTextClipData bị bỏ qua.
  2. EditText chứa con trỏ văn bản (con nháy).
  3. EditText đầu tiên được cung cấp cho lệnh 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 một 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 đố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 biểu thị bằng URI.

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

  • 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 xuống Android 7.0.

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 ClipDescription kéo và thả, 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 bạn thiết lập loại MIME chính xác.

DropHelper yêu cầu tất cả quyền truy cập cho các URI nội dung có trong ClipData kéo và thả. Để biết thêm thông tin, hãy xem DragAndDropPermissions. Các quyền này cho phép bạn phân giải URI nội dung khi xử lý dữ liệu kéo và thả.

DropHelper không xác thực dữ liệu do trình cung cấp nội dung trả về khi phân giải các 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.