基本的なコンセプト

以下のセクションでは、ドラッグ&ドロップ プロセスの主なコンセプトについて説明します。

ドラッグ&ドロップのプロセス

ドラッグ&ドロップのプロセスには 4 つのステップ(状態)があります。開始済み、 継続、ドロップ、終了です

開始

ユーザーのドラッグ操作に応答して、アプリは startDragAndDrop(): ドラッグ&ドロップ オペレーションを開始するようシステムに指示します。「 メソッドの引数には、次のものがあります。

  • ドラッグするデータ。
  • ドラッグ シャドウを描画するためのコールバック
  • ドラッグしたデータを説明するメタデータ
  • システムは、アプリケーションにコールバックしてドラッグを取得することで応答します。 できます。それにより、デバイスにドラッグ シャドウが表示されます。
  • 次に、システムからアクション タイプを含むドラッグ イベントが送信されます。 ドラッグ イベントに追加する ACTION_DRAG_STARTED 現在のレイアウトに含まれるすべての View オブジェクトのリスナー。宛先 ドラッグ イベントを引き続き受信する(ドロップの可能性を含む) event - ドラッグ イベント リスナーが true を返す必要があります。これにより、 リクエストできます。登録済みのリスナーのみが、 ドラッグ イベントを受信できます。この時点で、リスナーは ドロップ ターゲット View オブジェクトの外観。ビューが 受け取れます。
  • ドラッグ イベント リスナーが false を返した場合は、ドラッグを受信しません。 システムからドラッグ イベントが送信されるまで、現在のオペレーションの アクション タイプ ACTION_DRAG_ENDEDfalse を返すことにより、リスナーは関心がないことをシステムに伝えます。 ドラッグ&ドロップ オペレーションで機能し、ドラッグされたデータを受け入れたくない場合。
ドラッグ中
ユーザーがドラッグを続けています。ドラッグ シャドウが境界線と交差すると、 ドラッグ イベントがドロップ ターゲットの境界ボックスに追加されると、 ターゲットのドラッグ イベント リスナー。リスナーによって、メッセージの外観が イベントに応答してドロップ ターゲット View。たとえば、イベントが ドラッグ シャドウがドロップの境界ボックスに入ることを示します target - アクション タイプ ACTION_DRAG_ENTERED - リスナーは View をハイライト表示してリアクションできます。
ドロップ
ユーザーがドロップの境界ボックス内でドラッグ シャドウを放す あります。システムがドロップ ターゲットのリスナーにアクション付きのドラッグ イベントを送信する タイプ ACTION_DROP。 ドラッグ イベント オブジェクトには、 オペレーションを開始する startDragAndDrop() を呼び出します。リスナーは リスナーが正常に終了すると、ブール値 true がシステムに返されます。 ドロップされたデータを処理します。 : このステップは、ユーザーがドラッグ シャドウを ドラッグ イベントを受信するようにリスナーが登録されている View の境界ボックス (ドロップ ターゲット)。ユーザーがドラッグ シャドウを ACTION_DROP ドラッグ イベントは送信されません。
終了

ユーザーがドラッグ シャドウを離した後、システムが

アクション タイプ ACTION_DROP のドラッグ イベントを出力します。必要に応じて、システムが アクション タイプ ACTION_DRAG_ENDED のドラッグ イベントを送信し、 終了です。これはユーザーがどこで ドラッグ シャドウを解放します。イベントは、指定されたすべての 登録済みのドラッグ イベントを受信できます。これは、リスナーが ACTION_DROP イベント。

これらの各ステップについては、 ドラッグ&ドロップ オペレーション

ドラッグ イベント

システムはドラッグ イベントを DragEvent オブジェクトの形式で送信します。 には、ドラッグ&ドロップで起きていることを説明するアクション タイプが含まれています。 プロセスですアクション タイプに応じて、オブジェクトに他のデータを含めることもできます。

ドラッグ イベント リスナーは DragEvent オブジェクトを受け取ります。リスナーでアクション タイプを取得するためには、DragEvent.getAction() を呼び出します。DragEvent クラスの定数によって定義される有効な値は 6 つあります。 これらについては表 1 をご覧ください。

表 1. DragEvent のアクション タイプ

アクション タイプ 意味
ACTION_DRAG_STARTED アプリケーションが startDragAndDrop() を呼び出し、 ドロップしますリスナーがドラッグ イベントを引き続き受信したい場合 このオペレーションでは、ブール値 true を ありません
ACTION_DRAG_ENTERED ドラッグ シャドウは、ドラッグ イベント リスナーの境界ボックスに入ります。 View。これはリスナーの最初のイベント アクション タイプです。 ドラッグ シャドウが境界ボックスに入ったときに受信するメッセージを渡します。
ACTION_DRAG_LOCATION アジェンダは、 ACTION_DRAG_ENTERED イベントで、ドラッグ シャドウが ドラッグ イベント リスナーの境界ボックス内で、 View
ACTION_DRAG_EXITED ACTION_DRAG_ENTERED と少なくとも 1 つの ACTION_DRAG_LOCATION イベントが発生すると、ドラッグ シャドウが移動します。 イベント リスナーの境界ボックスの外側に View
ACTION_DROP ドラッグ シャドウは、ドラッグ イベント リスナーの View。このアクション タイプは View に送信されます。 オブジェクトのリスナーがブール値を返した場合に限り、 次に対する true: ACTION_DRAG_STARTED のドラッグ イベント。このアクション タイプは ユーザーが View 上でドラッグ シャドウを解放すると送信されます。 リスナーが登録されていない場合、またはユーザーがドラッグを離した場合、 現在のレイアウトに含まれていないものにはシャドウを付けることができます。

次の場合、リスナーはブール値 true を返します。 ドロップが正常に処理されます。それ以外の場合は、 false

ACTION_DRAG_ENDED ドラッグ&ドロップ オペレーションが終了しています。このアクション タイプ は、必ずしも ACTION_DROP イベントの後に来るとは限りません。条件 システムが ACTION_DROP を送信し、 ACTION_DRAG_ENDED アクション タイプは、 ドロップ成功です。リスナーは、 getResult(), 表 2 に示すとおりに操作し、 ACTION_DROP への応答で返されます。もし ACTION_DROP イベントが送信されない場合、 getResult()false を返します。

DragEvent オブジェクトには、アプリが処理するデータとメタデータも格納されます。 startDragAndDrop() の呼び出しでシステムに提供します。データの一部は 表 2 に示すように、特定のアクション タイプでのみ有効です。詳細情報 イベントとその関連データの詳細については、 ドラッグ&ドロップ オペレーションです

表 2. アクション タイプごとの有効な DragEvent データ

getAction()
getClipDescription()
getLocalState()
getX()
getY()
getClipData()
getResult()
ACTION_DRAG_STARTED ✓ ✓        
ACTION_DRAG_ENTERED ✓ ✓        
ACTION_DRAG_LOCATION ✓ ✓ ✓ ✓    
ACTION_DRAG_EXITED ✓ ✓        
ACTION_DROP ✓ ✓ ✓ ✓ ✓  
ACTION_DRAG_ENDED   ✓       ✓

DragEvent メソッド getAction() describeContents()writeToParcel()、 常に toString() 個 有効なデータを返します。

メソッドに特定のアクション タイプに対する有効なデータが含まれていない場合、メソッドが返します。 結果の型に応じて null または 0。

ドラッグ シャドウ

ドラッグ&ドロップ操作の間は、ユーザーが入力した画像を ドラッグします。データを移動する場合は、この画像はドラッグ中のデータを表します。その他の操作の場合は、そのドラッグ オペレーションをなんらかのかたちで表す画像になります。

この画像はドラッグ シャドウと呼ばれます。宣言するメソッドを使用して作成することで、 View.DragShadowBuilder 渡されます。ドラッグ&ドロップの開始時に、ビルダーをシステムに渡します。 startDragAndDrop() を使用したオペレーション。アラートに対する startDragAndDrop(): システムは、 View.DragShadowBuilder を使用してドラッグ シャドウを取得します。

View.DragShadowBuilder クラスには、以下の 2 つのコンストラクタがあります。

View.DragShadowBuilder(View)

このコンストラクタでは、アプリのあらゆる View オブジェクトを使用できます。このコンストラクタにより View オブジェクトが View.DragShadowBuilder オブジェクトに格納されるため、コールバックがアクセスしてドラッグ シャドウを作成できます。ビューは必ずしも ドラッグ オペレーションを開始するためにユーザーが選択する View

このコンストラクタを使用すれば、View.DragShadowBuilder を拡張したり、そのメソッドをオーバーライドしたりする必要がなくなります。デフォルトでは 引数として渡す View と同じ外観を持つシャドウ ユーザーが画面に触れた位置の中央に配置されます。

View.DragShadowBuilder()

このコンストラクタを使用する場合、View オブジェクトが View.DragShadowBuilder オブジェクト。このフィールドは null に設定されています。延長が必要 View.DragShadowBuilder を使用してそのメソッドをオーバーライドするか、 目立たないドラッグシャドウですシステムはエラーをスローしません。

View.DragShadowBuilder クラスには、ドラッグ を作成する 2 つのメソッドがあります。 shadow:

onProvideShadowMetrics()

startDragAndDrop() を呼び出すとすぐに、システムによってこのメソッドが呼び出されます。このメソッドを使用して、ドラッグ シャドウのサイズやタッチポイントをシステムに送信します。このメソッドには、次の 2 つのパラメータがあります。

outShadowSize: Point 渡されます。ドラッグ シャドウの幅は、 x。高さは y

outShadowTouchPoint: Point オブジェクト。タッチポイントは ドラッグ シャドウ内に配置する必要があります。この位置はドラッグ中にユーザーの指の下に配置する必要があります。 その X 位置を xY 位置を y に指定します。

onDrawShadow()

onProvideShadowMetrics() 呼び出しの直後に、ドラッグ シャドウを作成する onDrawShadow() が呼び出されます。このメソッドには単一の 引数。Canvas オブジェクトであり、 システムの構築は onProvideShadowMetrics()。このメソッドでは、ドラッグ シャドウが指定された Canvas

パフォーマンスを向上させるには、ドラッグ シャドウのサイズを小さくしてください。単一の アイコンを使用することをおすすめします。複数のアイテムを選択する場合は、 画面全体に広がる完全な画像ではなく、積み重ねた形でアイコンを使用する。

ドラッグ イベント リスナーとコールバック メソッド

View は、以下を実装するドラッグ イベント リスナーとともにドラッグ イベントを受け取ります。 View.OnDragListener を使用するか、ビューの onDragEvent() コールバック メソッドを使用します。日時 システムがメソッドまたはリスナーを呼び出すと、 DragEvent 引数。

ほとんどの場合、コールバック メソッドよりもリスナーを使用することをおすすめします。UI を設計する場合、通常は View クラスをサブクラス化しませんが、コールバック メソッドを使う場合は、メソッドをオーバーライドするためにサブクラスを作成する必要があります。これに対してリスナークラスは、1 つ実装すれば、そのリスナークラスを異なる複数の View オブジェクトで使用できます。匿名のインライン クラスとして実装することもできます。 ラムダ式ですView オブジェクトのリスナーを設定するには、以下を呼び出します。 setOnDragListener()

代わりに、onDragEvent() のデフォルト実装を変更することもできます。 オーバーライドできます価格を OnReceiveContentListener あります。詳細については、以下をご覧ください。 setOnReceiveContentListener()。 この場合、onDragEvent() メソッドはデフォルトで次の処理を行います。

  • startDragAndDrop() の呼び出しに対して true を返します。
  • 電話 performReceiveContent() ドラッグ&ドロップのデータをビューにドロップした場合に 発生しますデータは メソッドを ContentInfo オブジェクトとして渡します。「 メソッドが OnReceiveContentListener を呼び出します。

  • ドラッグ&ドロップ データがビューにドロップされると true を返します。 OnReceiveContentListener は、すべてのコンテンツを使用します。

OnReceiveContentListener を定義して、データ固有の 。API レベル 24 までの下位互換性を確保するには、Jetpack バージョンの OnReceiveContentListener

View オブジェクトに対して、ドラッグ イベント リスナーとコールバック メソッドを システムは最初にリスナーを呼び出します。システムは リスナーが false を返す場合を除きます。

onDragEvent() メソッドと View.OnDragListener の組み合わせは次のようになります。 これは onTouchEvent() および View.OnTouchListener 使用します。