Android
 Computer >> コンピューター >  >> プログラミング >> Android

【Android】ドラッグ&ドロップ機能の実装方法をステップ解説

この記事では、Androidアプリでドラッグ&ドロップ機能を実装する方法を、実際のサンプルコードとともにステップ形式で解説します。完成すると、画面左側にある画像を指で長押ししてドラッグし、右側のエリアにドロップすることで移動できるようになります。

ドラッグ&ドロップの基本の仕組み

Androidのドラッグ&ドロップは、主に以下の2つのインターフェースで実現します。

  • View.OnTouchListener … ビューがタッチされたタイミングでstartDrag()を呼び出し、ドラッグを開始します。
  • View.OnDragListener … ドラッグ中に発生する各種イベントを受け取ります。特にACTION_DROP(ドロップ)を検知した際に、対象ビューを移動先のコンテナへ移動させます。

手順1:新規プロジェクトを作成する

Android Studioを起動し、メニューから「File」→「New Project」を選択します。必要な項目を入力して新しいプロジェクトを作成しましょう。テンプレートは「Empty Activity」で問題ありません。

手順2:レイアウトファイル(activity_main.xml)を編集する

res/layout/activity_main.xml に以下のコードを記述します。画面を左右2つのLinearLayoutで分割し、左側にドラッグ対象となるImageViewを配置しています。

<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/leftView"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        android:layout_weight="1"
        android:background="@android:color/darker_gray"
        android:gravity="center_vertical"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/boxView"
            android:layout_width="75dp"
            android:layout_height="75dp"
            android:layout_gravity="center_vertical|center_horizontal"
            android:layout_margin="10dp"
            android:background="@drawable/one" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/rightView"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        android:layout_weight="1"
        android:background="@android:color/darker_gray"
        android:gravity="center_vertical"
        android:orientation="vertical">
    </LinearLayout>
</LinearLayout>

@drawable/one の部分は、プロジェクト内に用意した任意の画像リソースに置き換えてください。

手順3:MainActivity.java を実装する

src/MainActivity.java に以下のコードを記述します。

import android.os.Bundle;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import androidx.appcompat.app.AppCompatActivity;

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

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

        // ドラッグ対象とドロップ先にリスナーを設定
        findViewById(R.id.boxView).setOnTouchListener(this);
        findViewById(R.id.leftView).setOnDragListener(this);
        findViewById(R.id.rightView).setOnDragListener(this);
    }

    // ドラッグイベントの処理
    @Override
    public boolean onDrag(View v, DragEvent event) {
        if (event.getAction() == DragEvent.ACTION_DROP) {
            // ドラッグ中のビューを取得
            View dragged = (View) event.getLocalState();
            ViewGroup source = (ViewGroup) dragged.getParent();
            source.removeView(dragged);

            // ドロップ先のコンテナに追加
            LinearLayout target = (LinearLayout) v;
            target.addView(dragged);

            dragged.setVisibility(View.VISIBLE);
        }
        return true;
    }

    // タッチイベントでドラッグを開始
    @Override
    public boolean onTouch(View view, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
            view.startDrag(null, shadowBuilder, view, 0);
            view.setVisibility(View.INVISIBLE);
            return true;
        }
        return false;
    }
}

※ 古いプロジェクトでは android.support.v7.app.AppCompatActivity を使用している場合があります。現在のAndroid Studioでは androidx.appcompat.app.AppCompatActivity が標準です。

コードのポイント

  • onTouch():指が画面に触れた瞬間(ACTION_DOWN)にstartDrag()を呼び出してドラッグを開始し、元のビューを一時的に見えなくします。
  • onDrag()ACTION_DROPを検知したら、ドラッグ中のビューを元の親レイアウトから削除し、ドロップ先のLinearLayoutに追加し直します。
  • DragEventには、ドラッグ開始(ACTION_DRAG_STARTED)、領域への出入り(ACTION_DRAG_ENTERED/EXITED)、ドラッグ終了(ACTION_DRAG_ENDED)など、さまざまなアクションが用意されており、用途に応じて処理を分岐できます。

手順4:AndroidManifest.xml を確認する

androidManifest.xml は以下の通りです。ドラッグ&ドロップに特別なパーミッションは不要のため、プロジェクト作成時に自動生成される内容でそのまま動作します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

アプリを実行してみる

それではアプリを実行してみましょう。ここでは、実機のAndroidスマートフォンをPCに接続していることを前提に説明します。Android Studioでプロジェクト内のアクティビティファイルを開き、ツールバーの「Run」アイコンをクリックしてください。接続したデバイスを選択して実行すると、端末に以下のような初期画面が表示されます。

【Android】ドラッグ&ドロップ機能の実装方法をステップ解説

左側の画像を長押ししてドラッグし、右側のグレーのエリアにドロップすると、画像が右側へ移動します。今回の仕組みを応用すれば、リストの並べ替えやゴミ箱への削除など、さまざまなUIに展開できます。ぜひ実際に試してみてください。

  1. iOS 11のドラッグ&ドロップ完全ガイド|ファイル移動からホーム画面整理まで

    iOS 11のドラッグ&ドロップとは?ドラッグ&ドロップは、iOS 11でiPhoneとiPadに搭載された新機能です。PCやMacで長年提供されてきた機能をさらに進化させたもので、その操作は驚くほどシンプル。移動したいアイテムを長押しすれば、そのアイテムが指先に「ピン留め」され、もう一方の手で画面をスワイプして好きな場所にドロップするだけです。iPhoneでは同一アプリ内でのドラッグ&ドロップに限定されていますが、この機能が真価を発揮するのはiPadです。iPadではアプリ間でアイテムをやり取りできるだけでなく、複数のアプリ自体をまとめて移動することなども可能になっています。以下では、iOS

  2. Androidの可視性リスナー(Visibility Listener)の使い方と導入すべき理由

    AndroidのUIはViewを組み合わせて構築されており、通常のアプリケーションには複数のViewが存在します。ユーザーが現在どのViewを見ているのかを把握するには、可視性リスナー(Visibility Listeners)を実装する必要があります。 この記事では、Viewの表示状態を検知するためのさまざまな手法について詳しく解説します。 Viewを画面に表示させる方法 リスナーを正しく機能させるには、まず対象のViewがレイアウト階層内に存在していることを確認する必要があります。これには2つの方法があります。 XMLファイルで定義されたレイアウトに、あらかじめViewが組み込まれている