kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

こんなに簡単だとは思わなかった!Viewのドラッグ方法

Viewをドラッグ・アンド・ドロップするというと、どのように実装するのか直ぐには思い浮かばなかったので、調べたところ、Viewをドラッグするだけなら、非常に簡単に実装できることがわかりました。私が作成した実験プログラムを紹介してみます。

画面イメージ

作成したプログラムの画面イメージは、次のようになります。画面内のドロイド君アイコンをドラッグすることが出来ます。

プログラム構成

画面のレイアウト構成、実装するクラスの構成を図にしました。レイアウトは、ドロイド君アイコンを表示するImageViewと、そのImageViewを自由に配置可能なFrameLayoutで構成してあります。実装するクラスは、図中の緑色のボックスで、DragActivityとDragViewListenerの2つです。ピンク色のボックスは、継承元となるAndroidのクラスです。

プログラム詳細

レイアウトXML(drag_activity.xml)は、次のようになります。ドロイド君アイコンを表示するためにImageViewを使っています。ドロイド君アイコンは「@drawable/ic_launcher」です。ImageViewをドラッグした時に、自由に移動させるため、ImageViewのレイアウトにはFrameLayoutを使っています。LinerLayoutは無くても構いません。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_margin="30dip"
        android:background="#333333" >
        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher" />
    </FrameLayout>
</LinearLayout>

アクティビティのクラス(DragActivity.java)です。上記のレイアウトXMLを呼び出し、レイアウト内のImageViewのTouchイベントに、リスナーを紐付けています。

public class DragActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.drag_activity);
		// ドラッグ対象Viewとイベント処理クラスを紐付ける
		ImageView dragView = (ImageView) findViewById(R.id.imageView1);
		DragViewListener listener = new DragViewListener(dragView);
		dragView.setOnTouchListener(listener);
	}
}

Touchイベントを処理するリスナークラス(DragViewListener.java)です。上記のアクティビティクラスに記述することも可能ですが、ドラッグ処理の部分を明確にしたかったので、別クラスとしました。Touchイベントのアクションに「ACTION_MOVE」が設定されている場合、ImageViewが動かされた事になります。動かされた移動量を取得し、その分だけ、ImageViewの配置を変更しています。

public class DragViewListener implements OnTouchListener {
	// ドラッグ対象のView
	private ImageView dragView;
	// ドラッグ中に移動量を取得するための変数
	private int oldx;
	private int oldy;

	public DragViewListener(ImageView dragView) {
		this.dragView = dragView;
	}

	@Override
	public boolean onTouch(View view, MotionEvent event) {
		// タッチしている位置取得
		int x = (int) event.getRawX();
		int y = (int) event.getRawY();

		switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE:
			// 今回イベントでのView移動先の位置
			int left = dragView.getLeft() + (x - oldx);
			int top = dragView.getTop() + (y - oldy);
			// Viewを移動する
			dragView.layout(left, top, left + dragView.getWidth(), top
					+ dragView.getHeight());
			break;
		}

		// 今回のタッチ位置を保持
		oldx = x;
		oldy = y;
		// イベント処理完了
		return true;
	}
}

環境

  • 動作可能な最小OSバージョン:Android 2.1
  • 動作確認端末:Xperia SO-01B

参考サイト

次のサイトを参考にして作成しました。感謝です。