간소화된 드래그 앤 드롭을 위한 DropHelper

DropHelper 클래스는 드래그 앤 드롭 기능의 구현을 간소화합니다. Jetpack DragAndDrop 라이브러리의 구성원인 DropHelper는 API 수준 24까지 하위 호환성을 제공합니다.

DropHelper를 사용하면 드롭 타겟을 지정하고 드롭 타겟 강조표시를 맞춤설정하며 드롭된 데이터의 처리 방법을 정의할 수 있습니다.

드래그 소스 설정

시작하려면 드래그 소스 뷰와 OnDragStartListener를 사용하여 DragStartHelper를 만듭니다.

OnDragStartListener에서 onDragStart() 메서드를 재정의합니다. 이동할 데이터의 ClipData 객체와 ClipData.Item 객체를 만듭니다. ClipData의 일부로 ClipDataClipDescription 객체에 저장된 메타데이터를 제공합니다. 데이터 이동을 나타내지 않는 드래그 앤 드롭 작업의 경우 실제 객체 대신 null를 사용할 수 있습니다.

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);
    }
});

드롭 타겟 지정

사용자가 뷰 위에 그림자를 놓는 경우 데이터를 받아서 올바르게 응답하도록 뷰를 올바르게 구성해야 합니다.

DropHelper.configureView()는 오버로드된 정적 메서드로, 드롭 타겟을 지정할 수 있게 해줍니다. 매개변수에는 다음이 포함됩니다.

예를 들어 이미지를 허용하는 드롭 타겟을 만들려면 다음 메서드 호출 중 하나를 사용하세요.

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);

두 번째 호출에서는 드롭 타겟 구성 옵션을 생략합니다. 이 경우 드롭 타겟 강조표시 색상은 테마의 보조 (또는 강조) 색상으로 설정되고 강조표시 모서리 반경이 16dp로 설정되며 EditText 구성요소 목록은 비어 있습니다. 자세한 내용은 다음 섹션을 참고하세요.

드롭 타겟 구성

DropHelper.Options 내부 클래스를 사용하면 드롭 타겟을 구성할 수 있습니다. 클래스의 인스턴스를 DropHelper.configureView(Activity, View, String[], Options, OnReceiveContentListener) 메서드에 제공합니다. 자세한 내용은 이전 섹션을 참고하세요.

드롭 타겟 강조표시 맞춤설정

DropHelper는 드롭 타겟을 구성하여 사용자가 타겟 위로 콘텐츠를 드래그할 때 강조표시를 표시합니다. DropHelper는 기본 스타일을 제공하고 DropHelper.Options를 사용하면 강조표시 색상을 설정하고 강조표시 직사각형의 모서리 반경을 지정할 수 있습니다.

다음 예와 같이 DropHelper.Options.Builder 클래스를 사용하여 DropHelper.Options 인스턴스를 만들고 구성 옵션을 설정합니다.

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();

드롭 타겟에서 EditText 구성요소 처리

DropHelper는 타겟에 수정 가능한 텍스트 필드가 포함되어 있으면 드롭 타겟 내의 포커스도 제어합니다.

드롭 타겟은 단일 뷰 또는 뷰 계층 구조일 수 있습니다. 드롭 타겟 뷰 계층 구조에 하나 이상의 EditText 구성요소가 포함되어 있다면 구성요소 목록을 DropHelper.Options.Builder.addInnerEditTexts(EditText...)에 제공하여 드롭 타겟 강조표시 및 텍스트 데이터 처리가 올바르게 작동하도록 합니다.

DropHelper는 드롭 타겟 뷰 계층 구조 내의 EditText 구성요소가 드래그 상호작용 중에 포함 뷰에서 포커스를 도용하지 않도록 합니다.

또한 드래그 앤 드롭 ClipData에 텍스트와 URI 데이터가 포함되어 있다면 DropHelper는 드롭 타겟의 EditText 구성요소 중 하나를 선택하여 텍스트 데이터를 처리합니다. 선택은 다음 우선순위에 따라 이루어집니다.

  1. ClipData가 삭제되는 EditText입니다.
  2. 텍스트 커서 (캐럿)가 포함된 EditText입니다.
  3. DropHelper.Options.Builder.addInnerEditTexts(EditText...) 호출에 제공된 첫 번째 EditText입니다.

EditText를 기본 텍스트 데이터 핸들러로 설정하려면 EditTextDropHelper.Options.Builder.addInnerEditTexts(EditText...) 호출의 첫 번째 인수로 전달합니다. 예를 들어, 드롭 타겟이 이미지를 처리하지만 편집 가능한 텍스트 필드 T1, T2, T3을 포함하는 경우 T2를 다음과 같이 기본값으로 설정합니다.

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();

드롭 타겟의 데이터 처리

DropHelper.configureView() 메서드는 드래그 앤 드롭 ClipData를 처리하기 위해 만든 OnReceiveContentListener를 허용합니다. 드래그 앤 드롭 데이터는 ContentInfoCompat 객체의 리스너에 제공됩니다. 텍스트 데이터가 객체에 있습니다. 이미지와 같은 미디어는 URI로 표현됩니다.

OnReceiveContentListenerDropHelper.configureView()를 사용하여 다음 유형의 뷰를 구성할 때 드래그 앤 드롭 외의 사용자 상호작용(예: 복사 및 붙여넣기)으로 드롭 타겟에 제공된 데이터도 처리합니다.

  • 모든 뷰(사용자가 Android 12 이상을 실행하는 경우)
  • AppCompatEditText: 사용자가 Android 7.0 이하의 Android 버전을 실행하는 경우

MIME 유형, 권한, 콘텐츠 유효성 검사

DropHelper에 의한 MIME 유형 확인은 드래그 앤 드롭 데이터를 제공하는 앱에서 만든 드래그 앤 드롭 ClipDescription를 기반으로 합니다. ClipDescription의 유효성을 검사하여 MIME 유형이 올바르게 설정되었는지 확인합니다.

DropHelper는 드래그 앤 드롭 ClipData에 포함된 콘텐츠 URI의 모든 액세스 권한을 요청합니다. 자세한 내용은 DragAndDropPermissions를 참고하세요. 권한을 사용하면 드래그 앤 드롭 데이터를 처리할 때 콘텐츠 URI를 확인할 수 있습니다.

DropHelper는 드롭된 데이터의 URI를 결정할 때 콘텐츠 제공자가 반환한 데이터의 유효성을 검사하지 않습니다. null을 확인하고 결정된 데이터가 정확한지 확인합니다.