見出し画像

【Android】ドラッグアンドドロップで新しいViewを追加できるようにする方法(Java)

あるButtonをドラッグアンドドロップしたら、ドロップした位置に新しいButtonが作成される方法を紹介します。

1. onLongClickListenerを作る。
2. onDragListenerを作る。
3. ドラッグ元のButtonとそれぞれのListengerを紐付ける。

という順番で行います。


1. onLongClickListenerを作る。

@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public boolean onLongClick(View v) {
   v.startDrag(null, new View.DragShadowBuilder(v), v, 0);
   return true;
}

ドラッグ元のButtonが長押しされたときの処理を書きます。
startDragとすることで、長押しされた瞬間に次に紹介するonDragの処理が実行されます。

startDragの引数の三番目のDragShadowBuilderは、ドラッグ中に薄く表示されるものを指定するんですが、ここでは、vとすることで、ドラッグ元のボタンを入れています。


2. onDragListenerを作る。

@Override
public boolean onDrag(View v, DragEvent event) {
   switch (event.getAction()) {
           default: {
               Log.d("default", String.valueOf(event.getAction()));
           }
           // Drag end
           case DragEvent.ACTION_DRAG_ENDED: {
               Log.d("end", "end");
               return true;
           }
           // Drag start
           case DragEvent.ACTION_DRAG_STARTED: {
               View dragView = (View) event.getLocalState();
               Log.d("start", "startDrag");
               return true;
           }
           // Drag drop
           case DragEvent.ACTION_DROP: {
               Log.d("drop", "drop");
               Button addedButton = new Button(this);
               addedButton.setText("dkkdk");
               addedButton.setX(event.getX());
               addedButton.setY(event.getY());
               ((ConstraintLayout) constraintLayout).addView(addedButton);
               return true;
           }
    }
}

ドラッグ中に、このonDragが何回も呼び出されます。ドラッグの状態によって、event.getAction()に入っている値(int)が異なるので、それによって処理を変えます。値についてはこちらを参照.

case DragEvent.ActionDropの中で、新しいButtonオブジェクトを生成し、親のViewの追加しています。(こうすることで、元のButtonの移動ではなく、新しいButtonを追加する処理にしています。)


3. ドラッグ元のButtonとそれぞれのListengerを紐付ける。

newTaskButton.setOnLongClickListener(this::onLongClick);
constraintLayout.setOnDragListener(this::onDrag);

これを、MainActivityのonCreateとかでやります。

setOnDragListenerは、ドラッグするViewに対してではなく、ドロップされる側のViewにセットすることに注意!(LinearLayoutとかConstraintLayoutとか)

以上で完了。

いちよ、自分の全体のコードを載せときます。

public class MainActivity extends AppCompatActivity implements View.OnLongClickListener, View.OnDragListener {

   ConstraintLayout constraintLayout;
   Button newTaskButton;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       newTaskButton = findViewById(R.id.newTaskButton);
       constraintLayout = findViewById(R.id.constraintLayout);

       newTaskButton.setOnLongClickListener(this::onLongClick);

       constraintLayout.setOnDragListener(this::onDrag);
   }

   @RequiresApi(api = Build.VERSION_CODES.N)
   @Override
   public boolean onLongClick(View v) {
       v.startDrag(null, new View.DragShadowBuilder(v), v, 0);
       return true;
   }


   @Override
   public boolean onDrag(View v, DragEvent event) {
       switch (event.getAction()) {
           default: {
               Log.d("default", String.valueOf(event.getAction()));
           }
           // Drag end
           case DragEvent.ACTION_DRAG_ENDED: {
               Log.d("end", "end");
               return true;
           }
           // Drag start
           case DragEvent.ACTION_DRAG_STARTED: {
               View dragView = (View) event.getLocalState();
               Log.d("start", "startDrag");
               return true;
           }
           // Drag drop
           case DragEvent.ACTION_DROP: {
               Log.d("drop", "drop");
               Button addedButton = new Button(this);
               addedButton.setText("dkkdk");
               addedButton.setX(event.getX());
               addedButton.setY(event.getY());
               ((ConstraintLayout) constraintLayout).addView(addedButton);
               return true;
           }
       }
   }

}

この記事が気に入ったらサポートをしてみませんか?