2010年12月21日火曜日

android.widget.Buttonの座標を設定する方法

ボタンの配置を自由にカスタマイズできるような仕様のアプリを作ろうとしていたがここではまった
やりたいことはドラッグ中の座標にButtonを再配置するということ
はまった点は
 ドラッグ中の座標の取得(主にローカルとスクリーン座標について)
 ボタンの座標の設定方法

はじめに言っておくと直接座標指定するって方法は推奨されていないみたいです
画面配置が機種依存になってしまうからかなって推測



まずボタンの座標を設定する方法ですが直接設定できるようなメソッドは調べた限りでは無かった
ボタンの座標の取得はgetLeft() getRight() getTop() getBottom()など取得できるが設定のためのsetLeft()などは無いみたい

Buttonを追加する土台となるレイアウトの種類によってはButtonを追加する際に呼ぶメソッドに座標を指定するパラメータが無いものがある
じゃあ座標指定できるレイアウトはなんぞやってことだがAbsoluteLayout で座標が指定できるようになる

 //レイアウト作成
  AbsoluteLayout absoluteLayout = new AbsoluteLayout(this);
  setContentView(absoluteLayout);
  //ボタン作成
  Button button1 = new Button(this);
 //レイアウトにボタンを追加 ボタンのパラメータの設定
  absoluteLayout.addView(button1, new AbsoluteLayout.LayoutParams(150,50, 0, 0));

こんな感じで指定した座標にボタンを追加することができる
指定しているコードはAbsoluteLayout.LayoutParams(width,height, x, y)で行っている
xyはButtonの矩形の左上の座標になる

ボタンのパラメータを動的に指定したい場合は
button1.setLayoutParams(new AbsoluteLayout.LayoutParams(width,height, x, y));
とすると指定したパラメータにボタンが更新される




次にドラッグ中の座標取得ですが
ドラッグの実装についてはどっかのサイトを見たんだけどどこか忘れた・・・
それで、はまったのはどの座標系の座標を取ってきているかを勘違いしていたってことで

android.view.MotionEvent.getX()

ボタンのローカル座標
ボタンの持っている座標系の座標を取得するもんだと思う
詳しくリファレンス読んでないので間違ってるかもしれない

android.view.MotionEvent.getRawX()
スクリーン座標
こちらはスクリーンの座標系の座標を取得するものだと思う


きっちり調べたわけではないので間違ってること言っていたらご指摘お願いします。





上で述べた二つを組み合わせて作ったのがボタンをドラッグ中の座標に設定するサンプルプログラム
import android.app.Activity;
import android.os.Bundle;
import android.widget.AbsoluteLayout;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.Button;
import android.widget.TextView;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class AndroidFormTest extends Activity implements OnTouchListener {
 private Button button1;
 private TextView textView1, textView2,textView3;
 private int mState = 0;
 private int offsetX = 0;// ボタンクリックしたスクリーンのX座標とボタンのX座標の差分
 private int offsetY = 0;// ボタンクリックしたスクリーンのY座標とボタンのY座標の差分
 private final int STATE_NONE = 0;
 private final int STATE_DRAG = 1;
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  AbsoluteLayout absoluteLayout = new AbsoluteLayout(this);
  setContentView(absoluteLayout);
  //ボタン作成
  button1 = new Button(this);
  // イベントリスナの登録
  button1.setOnTouchListener(this);

  absoluteLayout.addView(button1, new AbsoluteLayout.LayoutParams(150,50, 0, 0));
  button1.setText(button1.getLeft() + "," + button1.getTop());
  textView1 = new TextView(this);
  absoluteLayout.addView(textView1, new AbsoluteLayout.LayoutParams(300,50, 20, 100));
  textView2 = new TextView(this);
  absoluteLayout.addView(textView2, new AbsoluteLayout.LayoutParams(300,50, 20, 150));
  textView3 = new TextView(this);
  absoluteLayout.addView(textView3, new AbsoluteLayout.LayoutParams(300,50, 20, 200));
 }
  @Override
 public boolean onTouch(View v, MotionEvent event) {
  // TODO 自動生成されたメソッド・スタブ
  // ドラッグ
  switch (event.getAction() & MotionEvent.ACTION_MASK) {
  case MotionEvent.ACTION_DOWN:
   offsetX = (int) event.getX();
   offsetY = (int) event.getY();
   textView1.setText("クリックした時点のローカル:" + offsetX + "," + offsetY);
   mState = STATE_DRAG;
   break;
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_POINTER_UP:
   mState = STATE_NONE;
   break;
  case MotionEvent.ACTION_MOVE:
   if (mState == STATE_DRAG) {
    int pointX, pointY;
    pointX = (int) event.getRawX() - offsetX;
    pointY = (int) event.getRawY() - (offsetY + button1.getHeight());
    button1.setLayoutParams(new AbsoluteLayout.LayoutParams(150,50, pointX, pointY));
    textView2.setText("ボタン座標(左上):" + button1.getLeft() + "," + button1.getTop());
    textView3.setText("スクリーン座標:" + (int) event.getRawX() + "," + (int) event.getRawY());
   }
   break;
  }
  return false;
 }
}
------------------------------------------------------------------------------------------------------------
追記
58行目のpointY = (int) event.getRawY() - (offsetY + button1.getHeight());
をpointY = (int) event.getRawY() - (offsetY + ステータスバーの高さ);と変更してください。
今回はステータスバーの高さとボタンの高さがたまたま一緒だったのでうまくいっています。
ステータスバーの高さを取得できる方法が分かり次第また追記します。


0 件のコメント:

コメントを投稿