Viewをタッチすると移動させることができるUIを考えてみる。
ツールボタン的なUIに活用できるかもしれない。
これを実現するためには、サンプルプログラムのように実装したOnTouchListenerを移動させたいViewへセットしておけばよい。
移動対象のViewはRelativeLayoutの子Viewとなっており、タッチイベントでLayoutParamsのtopMarginとleftMarginを書き換えている。
複数のViewに同じリスナを登録すれば、それぞれのViewごとに移動させることができる。
MainActivity.java
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final OnTouchListener moving = new OnTouchListener() {
private float downX;
private float downY;
private int downLeftMargin;
private int downTopMargin;
@Override
public boolean onTouch(View v, MotionEvent event) {
// ViewGroup.MarginLayoutParamsでキャストすることで
// FrameLayoutの子要素であっても同様に扱える。
final ViewGroup.MarginLayoutParams param =
(ViewGroup.MarginLayoutParams)v.getLayoutParams();
if( event.getAction() == MotionEvent.ACTION_DOWN ){
downX = event.getRawX();
downY = event.getRawY();
downLeftMargin = param.leftMargin;
downTopMargin = param.topMargin;
return true;
}
else if( event.getAction() == MotionEvent.ACTION_MOVE){
param.leftMargin = downLeftMargin + (int)(event.getRawX() - downX);
param.topMargin = downTopMargin + (int)(event.getRawY() - downY);
v.layout(
param.leftMargin,
param.topMargin,
param.leftMargin + v.getWidth(),
param.topMargin + v.getHeight());
return true;
}
return false;
}
};
// 別々のViewに、同じリスナをセットしておく
findViewById(R.id.myView1).setOnTouchListener(moving);
findViewById(R.id.myView2).setOnTouchListener(moving);
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:id="@+id/myView1"
android:layout_width="100dp"
android:layout_height="200dp"
android:background="#ffff0000"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="toolmenu" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button2" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button3" />
</LinearLayout>
<TextView
android:id="@+id/myView2"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="#ff0000ff"
android:layout_marginLeft="50dp"
android:layout_marginTop="0dp"
android:text="MyTextView" />
</RelativeLayout>
実行結果は以下のようになる。
赤いViewと青いViewをそれぞれタッチ&ムーブで移動できる。
![]() |
![]() |
このプログラムを始め作ったとき、37行目でrequestLayout()を使っていた。そうすると、Viewの一部が画面の外にはみ出すと中の要素が潰れてしまっていた。

その後、layout()メソッドを使えばUI要素が潰れないことが分かったのでプログラムを修正した。

ただし実用化するならば、画面外への移動は抑制させるなりの対処が必要だろう。


Viewを移動させるやり方がわからずに困っていたので、非常に助かりました。
コメントありがとうございました。
これからも役立つ情報を提供できるようがんばっていきます。
Drag Dropのサンプル探しまくったのだけど、これをRelativeLayoutで
やるという発想が素晴らしい。実は私もMargin使って自作しようとした
矢先でこれを見つけて、助かりました。
ありがとう。
ピンバック: 【iOS】UIViewをタッチして移動させる – ザワプロ!
試しに画像(ImageView)を動かしてみようとしたところ描画されませんでした。
が、
1行目のActivity → AppCompatActivityにすると描画されました。