• 検索結果がありません。

Androidの通常の画面構成は画面上端からステータスバー、タイトルバーがあり、その下

にビュー画面があります。タッチイベントの「event.getY();」で取得したy座標の原点は画 面の上端を原点にした値ですので、この値を元にビュー画面に表示する場合は補正が必要 になります。この補正をする値はステータスバーとタイトルバーの高さの合計です。これ らの高さを求める方法はいくつかありますが、ステータスバーとタイトルバーの高さを 個々に求める代わりに画面上端からビュー画面のトップ位置までの距離は以下で得られま す。なお、この値はonCreateメソッド内やGviewコンストラクタ内では画面構成が完成 していないため0となってしまいますので、onDrawメソッド内で取得しています。

float top=getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

したがってタッチイベントで得らられる「event.getY();」からこのtopを引いた値をビュ ー画面のy座標として使えばよいことになります。なお、ステータスバー、タイトルバー を消してフルスクリーンモードにすればこのような補正は必要ありません。

「例題6-2」ビュー画面の左上隅からタッチムーブ位置に直線を描きます。(px,py)がタッチ

位置です。

・MainActivity.java

package com.example.touch3;

import android.app.Activity;

import android.content.Context;

import android.graphics.*;

import android.os.Bundle;

import android.view.*;

public class MainActivity extends Activity { private float px=0,py=0;

private GView gv;

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

gv=new GView(this);

setContentView(gv);

}

private class GView extends View { private Paint paint;

public GView(Context context) { super(context);

paint=new Paint();

}

protected void onDraw(Canvas canvas) { float

top=getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

paint.setColor(Color.BLUE);

canvas.drawLine(0,0,px,py-top,paint);

} }

public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_MOVE){

px=event.getX(); // タッチ位置をメンバ変数に格納 py=event.getY();

gv.invalidate(); // 再描画 }

return super.onTouchEvent(event);

} }

「練習問題6-2」タッチムーブ位置にイメージを追従して移動しなさい。

・MainActivity.java

package com.example.touch4;

import android.app.Activity;

import android.content.Context;

import android.graphics.*;

import android.os.Bundle;

import android.view.*;

public class MainActivity extends Activity { private float px=0,py=0;

private GView gv;

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

gv=new GView(this);

setContentView(gv);

}

private class GView extends View { private ①

public GView(Context context) { super(context);

img=BitmapFactory.decodeResource(getResources(),R.drawable.sai);

}

protected void onDraw(Canvas canvas) { float

top=getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

canvas.drawBitmap( ② ,null);

} }

public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_MOVE){

px=event.getX();

py=event.getY();

gv.invalidate();

}

return super.onTouchEvent(event);

} }

6-3 画面サイズ

画面の幅と高さは onDraw メソッドの canvas 引数を使って canvas.getWidth()と canvas.getHeight()で取得できます。得られる高さにはステータスバーとタイトルバーの高 さの合計が含まれていますので、描画できる画面の高さは以下のようにtopを引いた値とな ります。

top=getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

h=canvas.getHeight()-top;

「例題6-3」画面中央に羅針盤を置き、タッチ位置から北東、南東、南西、北西の4方向を

判定します。

・MainActivity.java

package com.example.touch5;

import android.app.Activity;

import android.content.Context;

import android.graphics.*;

import android.os.Bundle;

import android.view.*;

public class MainActivity extends Activity { private float w,h,top;

private GView gv;

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

gv=new GView(this);

setContentView(gv);

}

private class GView extends View { private Bitmap img;

public GView(Context context) { super(context);

img=BitmapFactory.decodeResource(getResources(),R.drawable.compass);

}

protected void onDraw(Canvas canvas) {

top=getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

w=canvas.getWidth();

h=canvas.getHeight()-top;

canvas.drawBitmap(img,w/2-img.getWidth()/2,h/2-img.getHeight()/2,null);

} }

public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_MOVE){

float px=event.getX();

float py=event.getY()-top;

if (px>w/2 && py<h/2) setTitle("北東");

else if (px>w/2 && py>h/2) setTitle("南東");

else if (px<w/2 && py>h/2) setTitle("南西");

else if (px<w/2 && py<h/2) setTitle("北西");

}

return super.onTouchEvent(event);

} }

「注」画面の幅と高さはViewクラスのgetWidthメソッド、getHeightメソッドで取得で きます。これらのメソッドはGviewコンストラクタ内では幅と高さが確定していないので 値を取得できません。onDrawメソッド内で取得します。

int w=getWidth();

int h=getHeight();

Canvas クラスのgetWidthメソッド、getHeightメソッドを使って次のように取得する

こともできます。ただしこの場合、幅はView クラスの getWidthメソッドと同じですが、

高さはステータスバーとタイトルバーの高さも含んでいます。

int w=canvas.getWidth();

int h=canvas.getHeight();

画面サイズを別の方法で求めるには11章-「11-8 ブラウザ(WebView)」の「「注」

DisplayクラスのgetWidth()とgetHeight()」を参照。

「練習問題6-3」1~8のイメージを画面中央を中心とする半径160の円周上に配置します。

タッチ位置を元にタッチしたイメージを判定しなさい。

・MainActivity.java

package com.example.touch6;

import android.app.Activity;

import android.content.Context;

import android.graphics.*;

import android.os.Bundle;

import android.view.*;

public class MainActivity extends Activity { private int[] imageId={

R.drawable.num1,R.drawable.num2,R.drawable.num3,R.drawable.num4, R.drawable.num5,R.drawable.num6,R.drawable.num7,R.drawable.num8 };

private float w,h,top,iw,ih;

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(new GView(this));

}

private class GView extends View { public GView(Context context) { super(context);

}

protected void onDraw(Canvas canvas) {

top=getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

w=canvas.getWidth();

h=canvas.getHeight()-top;

for (int i=0;i<8;i++){

Bitmap

img=BitmapFactory.decodeResource(getResources(),imageId[i]);

float x=(float)(160*Math.cos(45*i*Math.PI/180));

float y=(float)(160*Math.sin(45*i*Math.PI/180));

iw=img.getWidth();

ih=img.getHeight();

canvas.drawBitmap(img, ① ,h/2-y-ih/2,null);

} }

}

public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN){

float px=event.getX();

float py=event.getY()-top;

for (int i=0;i<8;i++){

float x=(float)(160*Math.cos(45*i*Math.PI/180));

float y=(float)(160*Math.sin(45*i*Math.PI/180));

if ( ② && px<w/2-x+iw/2 && h/2-y-ih/2<py && py<h/2-y+ih/2) setTitle("No"+(i+1));

} }

return super.onTouchEvent(event);

} }

「 注 」Bitmap img=BitmapFactory.decodeResource(getResources(),imageId[i]);は onDrawメソッド内に置いているので2-1の「注」Android Lint Checksと2-4の「注」Android Lint Checksで示した理由により警告エラーとなります。onDrawメソッド外でリソースを作成 すればよいのですが、煩雑になるため、ここではonDraw内に置きました。

☆応用サンプル 羅針盤の針を回す

タッチムーブ位置の方向を指すように針を回転させます。羅針盤compassと針needle を画面中央に描画します。画面の中央位置を(w,h)に取得し、「canvas.translate(w,h);」で 画面中央に座標移動します。針の角度angleはタッチ位置(x,y)からアークタンジェントを 使って「Math.atan(y/x)*180/Math.PI」で求め、「canvas.rotate(angle);」で座標回転しま す。

・MainActivity.java

package com.example.compass;

import android.app.Activity;

import android.os.Bundle;

import android.content.Context;

import android.graphics.*;

import android.view.*;

public class MainActivity extends Activity { private GView gv;

private int w,h;

private float angle=0,top=0;

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

gv=new GView(this);

setContentView(gv);

}

private class GView extends View { private Bitmap needle,compass;

public GView(Context context) { super(context);

needle=BitmapFactory.decodeResource(getResources(),R.drawable.needle);

compass=

BitmapFactory.decodeResource(getResources(),R.drawable.compass);

}

protected void onDraw(Canvas canvas) {

top=getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

w=getWidth()/2;

h=getHeight()/2;

canvas.drawColor(Color.WHITE);

canvas.translate(w,h);

canvas.drawBitmap(compass,-compass.getWidth()/2, -compass.getHeight()/2, null);

canvas.rotate(angle);

canvas.drawBitmap(needle,-needle.getWidth()/2, -needle.getHeight()/2, null);

} }

public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_MOVE){

float x=event.getX()-w;

float y=event.getY()-top-h;

angle=(float)(Math.atan(y/x)*180/Math.PI);

if (x<0)

angle+=180;

gv.invalidate();

}

return super.onTouchEvent(event);

} }

7-2 アラート・ダイアログ

AlertDialogはユーザに何らかの処理に対する問い合わせ(OKやCANCELなど)を行

うダイアログクラスです。

1. AlertDialog.Builder

AlertDialgのコンストラクタには直接アクセスできませんので、以下のように

AlertDialog.Builderクラスのオブジェクトbuilderを使ってアラート・ダイアログの内容

を設定します。

AlertDialog.Builder builder=new AlertDialog.Builder(this);

builder.setTitle("確認");

builder.setMessage("処理してよいですか");

関連したドキュメント