3-2 ボタン(Button)とクリック・リスナー
ボタンにクリック・リスナーを付け、ボタンのクリック(タップ)で何かの処理を行う 方法を説明します。1. OnClickListener リスナーのインプリメント
「Button bt=(Button)findViewById(R.id.button);」で取得したボタン bt がクリックされ たときの処理を行うクリック・リスナーを付けるにはまず、「implements OnClickListener」 でOnClickListener インターフェースを Activity クラスに追加します。public class Widget1 extends Activity implements OnClickListener{
こうしておいてから「bt.setOnClickListener(this);」でボタン bt にクリック・リスナー を設定します。
2. インターフェース
C++では複数のクラスを継承する多重継承を認めていますが、Java はこれを認めていま せん。その代わりにインターフェースという概念により追加機能をクラスに実装できるよ うにしました。インターフェースはクラスと同じようなものですが、データ部やコンスト ラクタのない特別な小規模なクラスと考えることができます。インターフェースは implements によりクラスに追加します。複数のインターフェースを追加したい場合はコン マで区切ります。3. onClick メソッド
OnClickListener を追加した場合、そのクラス内に onClick メソッドが必要となります。 そしてこのonClick メソッド内にクリックが生じたときの処理内容を記述します。onClick メソッドの引数view にはクリックしたウイジェットの View クラスのオブジェクトが渡さ れます。public void onClick(View view) { クリックが生じたときの処理 }
4. タイトルバーへのテキストの表示
タイトルバーにテキストを表示するにはsetTitle メソッドを使って以下のようにします。 setTitle("テキスト");
「例題3-2」ボタンをクリックしたらタイトルバーにテキストを表示します。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="クリックしてね" /> </LinearLayout> ・MainActivity.java package com.example.button1; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Button bt=(Button)findViewById(R.id.button); bt.setOnClickListener(this);
}
public void onClick(View view) { setTitle("クリックしました!"); }
5.複数のボタンの判定
複数のボタンに同じクリック・リスナーを設定した場合は、onClick メソッドの view 引 数を使ってview.getId()でクリックされたボタンの ID を判定します。
public void onClick(View view) { if (view.getId()==R.id.button1) // ボタン 1 の処理 else if (view.getId()==R.id.button2) // ボタン 2 の処理 } 「練習問題3-2」ボタンを 2 つ配置し、クリックされたボタンをタイトルバーに表示します。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="ボタン1" /> <Button android:id="@+id/button2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="ボタン2" />
</LinearLayout> ・MainActivity.java package com.example.button2; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt1=(Button)findViewById(R.id.button1); bt1.setOnClickListener(this);
Button bt2=(Button)findViewById(R.id.button2); bt2.setOnClickListener(this);
}
public void onClick(View view) { if ( ① ) setTitle("ボタン1をクリック"); else if ( ② ) setTitle("ボタン2をクリック"); } }
3-3 テキストビュー(TextView)
TextView はテキスト表示用のウィジェットで、<TextView>タグで定義します。 テキストビューにテキストを表示するには、setText メソッドを使います。 TextView text1=(TextView)findViewById(R.id.text1); text1.setText("クリックしました"); テキストの表示色はsetTextColor で設定できます。 text1.setTextColor(Color.GREEN); 「例題3-3」ボタンをクリックしたら TextView にテキストを表示します。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="クリックしてね" /> </LinearLayout> ・MainActivity.java package com.example.textview1; import android.app.Activity;import android.os.Bundle; import android.view.View;
import android.view.View.OnClickListener; import android.widget.*;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Button bt=(Button)findViewById(R.id.button1); bt.setOnClickListener(this);
}
public void onClick(View view) {
TextView text1=(TextView)findViewById(R.id.text1); text1.setText("クリックしました"); } } 「練習問題3-3」ボタン 1 をクリックしたら緑で、ボタン 2 をクリックしたら赤で TextView にテキストを表示しなさい。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView
android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="ボタン1" /> <Button android:id="@+id/button2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="ボタン2" /> </LinearLayout> ・MainActivity.java package com.example.textview2; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt1=(Button)findViewById(R.id.button1); bt1.setOnClickListener(this);
bt2.setOnClickListener(this); }
public void onClick(View view) {
TextView text1=(TextView)findViewById(R.id.text1); if (view.getId()==R.id.button1){
text1.setTextColor( ① ); text1.setText("ボタン1をクリック"); }
else if (view.getId()==R.id.button2){ text1.setTextColor( ② ); text1.setText("ボタン2をクリック"); }
} }
3-5 チェックボックス(CheckBox)
CheckBox は項目のクリックのたびにチェック状態(ON)と非チェック状態(OFF)を 交互に繰り返すウイジェットで<CheckBox >タグで定義します。チェックボックスは個々 に次のように取得します。
CheckBox cb=(CheckBox)findViewById(R.id.check1);
このcb を用いて「cb.isChecked()」が true ならチェック状態、false なら非チェック状 態と判定できます。チェックボックスの項目のテキストは「cb.getText()」で取得できます。 「例題3-5」ボタンのクリックでりんご、みかん、いちごのチェックされている項目をタイ トルバーに表示します。チェックボックスが 3 個あるので、「CheckBox cb[]=new CheckBox[3];」のような CheckBox 型配列を用意し、cb[0],cb[1],cb[2]で 3 個のチェックボ ックスを管理します。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <CheckBox android:id="@+id/check1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="りんご" /> <CheckBox android:id="@+id/check2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="みかん" /> <CheckBox android:id="@+id/check3" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="いちご" /> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="クリックしてね" /> </LinearLayout> ・MainActivity.java package com.example.checkbox1; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt1=(Button)findViewById(R.id.button1); bt1.setOnClickListener(this);
}
public void onClick(View view) { CheckBox cb[]=new CheckBox[3];
cb[0]=(CheckBox)findViewById(R.id.check1); cb[1]=(CheckBox)findViewById(R.id.check2); cb[2]=(CheckBox)findViewById(R.id.check3); String msg="";
for (int i=0;i<3;i++){ if (cb[i].isChecked())
msg+=cb[i].getText()+":"; } setTitle(msg); } } 「練習問題3-5」CheckBox のチェックの判定に配列を使わずに個々に判定しなさい。 ・activity_main.xml 例題3-5 と同じ。 ・MainActivity.java package com.example.checkbox2; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt1=(Button)findViewById(R.id.button1); bt1.setOnClickListener(this);
}
public void onClick(View view) { String msg=""; CheckBox cb; cb=(CheckBox)findViewById(R.id.check1); if (cb.isChecked()) msg+=cb.getText()+":"; cb=(CheckBox)findViewById( ① ); if (cb.isChecked()) msg+=cb.getText()+":"; cb=(CheckBox)findViewById( ② ); if (cb.isChecked()) msg+=cb.getText()+":"; setTitle(msg); } }
3-6 ラジオボタン(RadioGroup と RadioButton)
RadioButton は RadioGroup でグループ化された各項目の中で、クリックされた 1 つを チェック状態(ON)に、他を非チェック状態(OFF)にするウイジェットです。グループ 単位で動作するため< RadioGroup >タグの中にそのグループに属するラジオボタンを <RadioButton>タグで定義します。初期設定でチェック状態にしておきたいラジオボタン に「android:checked="true"」を指定します。この指定がいずれかのラジオボタンになけれ ば、初期状態はどのラジオボタンもチェック状態にありません。 <RadioGroup・・・> ←グループの定義 <RadioButton・・・/> ←グループ内の個々のラジオボタン <RadioButton・・・/> </RadioGroup> グループ内でチェックされている項目は1 つです。この項目を取得するには次のように します。rg.getCheckedRadioButtonId()でグループ内でチェックされているラジオボタン のID を取得できます。 RadioGroup rg=(RadioGroup)findViewById(R.id.radiogroup); RadioButton rb=(RadioButton)findViewById(rg.getCheckedRadioButtonId()); rb.getText(); 「例題3-6」ボタンのクリックで、ON になっているラジオボタンの内容をタイトルバーに 表示します。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <RadioGroup android:id="@+id/radiogroup" android:layout_width="fill_parent" android:layout_height="wrap_content" > <RadioButtonandroid:id="@+id/radio1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:checked="true" android:text="男" /> <RadioButton android:id="@+id/radio2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="女" /> </RadioGroup> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="クリックしてね" /> </LinearLayout> ・MainActivity.java package com.example.radiobutton1; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt1.setOnClickListener(this); }
public void onClick(View view) {
RadioGroup rg=(RadioGroup)findViewById(R.id.radiogroup); RadioButton rb=(RadioButton)findViewById(rg.getCheckedRadioButtonId()); setTitle(rb.getText()); } } 「練習問題3-6」Android、iOS、Windows という 3 項目のラジオボタンを作り、チェック されているものをタイトルバーに表示しなさい。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <RadioGroup android:id="@+id/radiogroup" android:layout_width="fill_parent" android:layout_height="wrap_content" > <RadioButton android:id="@+id/radio1" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:checked="true" android:text= ① /> <RadioButton android:id="@+id/radio2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text= ② /> <RadioButton android:id="@+id/radio3" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text= ③ /> </RadioGroup> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="クリックしてね" /> </LinearLayout> ・MainActivity.java package com.example.radiobutton2; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt1=(Button)findViewById(R.id.button1); bt1.setOnClickListener(this);
}
public void onClick(View view) {
RadioGroup rg=(RadioGroup)findViewById(R.id.radiogroup); RadioButton
rb=(RadioButton)findViewById(rg.getCheckedRadioButtonId()); setTitle(rb.getText());
} }
3-7 スピナー(Spinner)
Spiner はスピナーの▼ボタンのクリックでスピナーに登録されている項目をポップアッ プ画面に表示し、その項目の中から1つを選択するウイジェットで<Spiner>タグで定義し ます。表示される各項目はラジオボタンと同様な動作をします。スピナーに登録する項目 はandroid:entries 属性に指定します。 <Spinner android:entries="@array/items" />@array/items は res/values フォルダの string.xml に次のように定義した内容を指します。
<resources> <string-array name="items"> <item>学生</item> <item>会社員</item> <item>主婦</item> </string-array> </resource> スピナーの選択されている項目の内容は以下のようにして取得できます。 Spinner sp=(Spinner)findViewById(R.id.spinner); sp.getSelectedItem(); 取得したデータはObject 型なので、項目の内容を取得するには (String) sp.getSelectedItem() または sp.getSelectedItem().toString() とします。 選択されている項目の番号(0 スタート)は「sp.getSelectedItemPosition()」で取得で きます。
「例題3-7」スピナーの▼ボタンのクリックでスピナーに登録されている項目の中から 1 つ を選択します。ボタンのクリックで、スピナーで選択されている項目の番号と内容をタイ トルバーに表示します。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Spinner android:id="@+id/spinner" android:layout_width="fill_parent" android:layout_height="wrap_content" android:entries="@array/items" /> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="選択した後でクリックしてね" /> </LinearLayout> ・res/values/string.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Spinner1</string>
<string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string-array name="items"> <item>学生</item> <item>会社員</item> <item>主婦</item> </string-array> </resources>
・MainActivity.java package com.example.spinner1; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*;
public class MainActivity extends Activity implements OnClickListener{ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt1=(Button)findViewById(R.id.button1); bt1.setOnClickListener(this);
}
public void onClick(View view) {
Spinner sp=(Spinner)findViewById(R.id.spinner);
setTitle(sp.getSelectedItemPosition()+":"+(String)sp.getSelectedItem()); }
「 注 」Android 4.0 以 後 は Spinner は デ フ ォ ル ト で ド ロ ッ プ ダ ウ ン 形 式 「android:spinnerMode="dropdown" 」 と な り ま す 。 ダ イ ア ロ グ 形 式 に す る に は 「android:spinnerMode="dialog"」とします。 「練習問題3-7」スピナーの項目を Android、iOS、Windows、Linux の 4 項目にしなさい。 ・activity_main.xml,Spinner2.java 例題3-7 と同じ。 ・res/values/strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Spinner2</string>
<string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string-array name="items"> ① ② ③ ④ </string-array> </resources>
3-8 リストビュー(ListView)
ListView は項目の一覧をリスト形式で表示するウイジェットで<ListView>タグで定義 します。リスト項目の登録の仕方はスピナーの場合と同じです。 <ListView android:entries="@array/items" />1. OnItemClickListener
リストビューでは通常、リスト項目の選択というイベントで処理を行います。そこでリ ストビューには次のようにしてOnItemClickListener を設定します。 ListView lv=(ListView)findViewById(R.id.listview); lv.setOnItemClickListener(new ItemClick());class ItemClick implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) { リスト項目が選択されたときの処理
} }
選択された項目はonItemClick メソッドの parent と position 引数を使って次のように取 得します。 String item=(String)((ListView)parent).getItemAtPosition(position); 「注」ラジオボタン、チェックボックス、スピナーはクリックしたときの選択状態を保持 しているので、これらのウイジェットの直接のクリックイベントでなく、ボタンのクリッ クイベントで、これらのウイジェットの選択状態を取得できました。ところがリストビュ ーは項目をクリックしたとき、選択状態などを保持できません。そのためリストビュー自 体にイベントリスナーを設定します。
2. ジェネリッククラス
クラス名の右に「<T>」という「型パラメーター」を指定したクラスをジェネリッククラ スと呼びます。たとえばList クラスは Integer、String などのデータ要素をリストとして 扱うことができるジェネリッククラスです。使用する場合は<>内にデータ型を指定します。
List<String> list = new ArrayList<String>(); list.add(new String("Ann"));
String x =list.get(0);
ListView、Spinner は AdapterView のサブクラスです。このため onItemClick メソッド の第1 引数は「AdapterView<?> parent」です。(ListView) parent のように実際のクラス にキャストしてから使います。さてここでAdapterView はジェネリッククラスですが、型 パラメータは<?>となっています。<?>はワイルドカードで無名のオブジェクト型を示しま す。コンパイル時には型を特定せず、実行時に渡された型を適用することを意味します。 「例題3-8」リストビューで選択された項目の内容をタイトルバーに表示します。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:entries="@array/items" /> </LinearLayout> ・strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Listview1</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string>
<string-array name="items"> <item>学生</item> <item>会社員</item> <item>主婦</item> </string-array> </resources> ・MainActivity.java package com.example.listview1; import android.app.Activity; import android.os.Bundle; import android.widget.*; import android.widget.AdapterView.OnItemClickListener; import android.view.View;
public class MainActivity extends Activity { @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lv=(ListView)findViewById(R.id.listview); lv.setOnItemClickListener(new ItemClick());
}
class ItemClick implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
String item =(String) ((ListView) parent).getItemAtPosition(position);
setTitle(item); }
} }
「練習問題3-8」「学生、会社員、主婦」の次に「男、女」のリストビューを追加しなさい。 各リストビューの選択項目はTextView に表示しなさい。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ListView android:id="@+id/listview1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:entries="@array/items1" /> <TextView android:id="@+id/text2" android:layout_width="fill_parent" android:layout_height="wrap_content" />
<ListView android:id="@+id/listview2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:entries= ① /> </LinearLayout> ・strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Listview2</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string-array name="items1"> <item>学生</item> <item>会社員</item> <item>主婦</item> </string-array> <string-array ② > <item>男</item> <item>女</item> </string-array> </resources>v ・MainActivity.java package com.example.listview2; import android.app.Activity; import android.os.Bundle; import android.widget.*; import android.widget.AdapterView.OnItemClickListener; import android.view.View;
public class MainActivity extends Activity { @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lv1=(ListView)findViewById(R.id.listview1); lv1.setOnItemClickListener(new ItemClick1());
ListView lv2=(ListView)findViewById(R.id.listview2); lv2.setOnItemClickListener(new ItemClick2());
}
class ItemClick1 implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
String item =(String) ((ListView) parent).getItemAtPosition(position);
TextView text1=(TextView)findViewById(R.id.text1); text1.setText(item);
} }
class ItemClick2 implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
String item =(String) ((ListView) parent).getItemAtPosition(position);
TextView text2=(TextView)findViewById(R.id.text2); text2.setText(item);
} } }
6-2 ビュー画面への描画
1. invalidate メソッド
タッチイベントの発生で呼び出されるメソッド内では直接ビュー画面への描画を行うこ とができません。このため GView クラスの gv をメンバ変数として宣言しておき、 gv.invalidate メソッドを使って onDraw メソッドを呼び出すことでビュー画面への描画を 行います。2. ビュー画面のトップ位置
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);
}
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 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("処理してよいですか");
2. ボタンのリスナーの設定
AlertDialog の OK ボタンをクリックしたときのリスナーは setPositiveButton メソッド を使って以下のように設定します。同様にCANCEL ボタンのリスナーは setNegativeButton メソッドを使って設定します。 builder.setPositiveButton("OK",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) {OK ボタンがクリックされたときの処理 } });
3. ダイアログの表示
上の1、2 で設定したアラートダイアログ・ビルダーの builder を使って、AlertDialg ク ラスのオブジェクトdialog を生成し show メソッドで表示します。 AlertDialog dialog=builder.create(); dialog.show();4. アイコン
「builder.setIcon(R.drawable.tab1);」でアイコンを指定できます。サイズは mdpi で 32 ×32 とします。5. Neutral ボタン
ボタンはNegativeButton,NeutralButton,PositiveButton の順に並びます。
builder.setNeutralButton("Neutral",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) {
setTitle("Neutral"); } }); 「注」Android 2.x ではボタンは PositiveButton、NeutralButton、NegativeButton の順 に並びます。 「例題7-2」画面のタッチでアラート・ダイアログを表示します。OK、CANCEL ボタンの クリックでどちらのボタンがクリックされたのかのメッセージをタイトルバーに表示しま す。 ・MainActivity.java package com.example.alert1; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.MotionEvent;
public class MainActivity extends Activity { @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); }
public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN){
AlertDialog.Builder builder=new AlertDialog.Builder(this); builder.setTitle("確認");
builder.setPositiveButton("OK",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { setTitle("OK");
} });
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { setTitle("CANCEL"); } }); AlertDialog dialog=builder.create(); dialog.show(); } return super.onTouchEvent(event); } }
「練習問題7-2」例題 7-2 にアイコンと Neutral ボタンを追加しなさい。 ・MainActivity.java package com.example.alert2; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.MotionEvent;
public class MainActivity extends Activity { @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); }
public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN){
AlertDialog.Builder builder=new AlertDialog.Builder(this); builder.setTitle("確認");
builder.setMessage("処理してよいですか"); builder.setIcon( ① ); builder.setPositiveButton("OK",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { setTitle("OK");
} });
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { setTitle("CANCEL");
} });
builder. ② ("Neutral",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) {
setTitle("Neutral"); } }); AlertDialog dialog=builder.create(); dialog.show(); } return super.onTouchEvent(event); } }
☆応用サンプル 食文化判定
質問項目を示す2 分木の項目ノードが node[ ]に、左、右へのポインタが left[ ],right[ ] に格納されています。ノード位置をp で示し、ルートノード(p=0)から初めて left[p]また はright[p]が「-1」になるまで木を進みます。質問項目はアラート・ダイアログで表示し、 「Yes」ボタンで左の木へ進み、「No」ボタンで右の木へ進みます。 ・MainActivity.java package com.example.tree1; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.MotionEvent;
public class MainActivity extends Activity { private String node[]={
"お米が好きですか", "味噌汁が好きですか", "パスタが好きですか", "あなたは和食派です", "あなたは中華派です", "あなたはイタリアンです",
"あなたはフレンチです"};
private int left[]={1,3,5,-1,-1,-1,-1}; private int right[]={2,4,6,-1,-1,-1,-1}; private static int p=0;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); }
public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN){
final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("食文化判定");
builder.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { p=left[p]; if (p==-1){ p=0; } else { builder.setMessage(node[p]); builder.create().show(); } }}); builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { p=right[p]; if (p==-1){ p=0; } else { builder.setMessage(node[p]); builder.create().show(); }
}}); builder.setMessage(node[p]); builder.create().show(); } return super.onTouchEvent(event); } }
10-3 イメージを画面上で移動する
一定時間ごとの処理の具体例として、イメージを画面上で移動します。1. ボールの移動
ボールのイメージファイルはball.png、サイズは 10×10 ピクセル、1 回にボールが進む 距離は10 ピクセルとします。ボールの位置(左上隅)を x,y、移動量を dx,dy とすると、 ボールを左右に移動するには「x+=dx」、ボールを上下に移動するには「y+=dy」とします。 斜めに移動する場合は「x+=dx」と「y+=dy」の両方を行います。2. 壁にボールがあたったときの判定
ボールが左右壁にあたったときにdx の値の符号を反転するには次のようにします。w は 画面の幅です。10 はボールのサイズです。 if (x<=0 || w-10<=x) dx=-dx; ボールが上下壁にあたったときにdy の値の符号を反転するには次のようにします。h は 画面の高さです。 if (y<=0 || h-10<=y) dy=-dy; 「例題10-3」ボールを 100 ミリ秒単位で横方向に移動し、左右壁でボールを跳ね返します。 ・MainActivity.java package com.example.handler5; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.view.*; import android.graphics.*;private int x=60,dx=10,w;
private Handler hd=new Handler(); private GView gv;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
gv=new GView(this); setContentView(gv); hd.post(this); }
public void run() { x+=dx; if (x<=0 || w-10<=x) dx=-dx; gv.invalidate(); hd.postDelayed(this,100); }
class GView extends View { private Bitmap ball;
public GView(Context context) { super(context);
ball=BitmapFactory.decodeResource(getResources(),R.drawable.ball); }
public void onDraw(Canvas canvas){ w=getWidth();
canvas.drawColor(Color.WHITE); canvas.drawBitmap(ball,x,60,null); }
} }
「練習問題10-3」ボールを 100 ミリ秒単位で斜めに移動し、上下壁、左右壁でボールを跳 ね返しなさい。 ・MainActivity.java package com.example.handler6; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.view.*; import android.graphics.*;
public class MainActivity extends Activity implements Runnable{ private int x=60,y=60,dx=10,dy=10,w,h;
private Handler hd=new Handler(); private GView gv;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
gv=new GView(this); setContentView(gv); hd.post(this); }
public void run() { x+=dx;y+=dy;
dx=-dx; if ( ① ) dy=-dy; gv.invalidate(); hd.postDelayed(this,100); }
class GView extends View { private Bitmap ball;
public GView(Context context) { super(context);
ball=BitmapFactory.decodeResource(getResources(),R.drawable.ball); }
public void onDraw(Canvas canvas){ w=getWidth();
h= ②
canvas.drawColor(Color.WHITE); canvas.drawBitmap(ball,x,y,null); }
} }
☆応用サンプル ラケットゲーム
1
タッチムーブイベントでラケットを移動し、ボールを跳ね返します。「練習問題10-3」 を元にラケットの移動処理とボールをラケットで跳ね返す処理を追加します。ボールがラ ケットに当たったを判定するのにy 座標に関する等価比較を行うため、ラケットの y 座標 はボールの移動量の10 の倍数とします。画面の高さを元に以下で計算します。 ry=(getHeight()/10)*10-100; ボールとラケットのイメージのサイズは以下で計算します。ボールの高さと幅は同じと仮 定しています。ballW=ball.getWidth(); barW=bar.getWidth();
・MainActivity.java package com.example.racket1; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.view.*; import android.graphics.*;
public class MainActivity extends Activity implements Runnable{ private int x=100,y=100,dx=10,dy=10,rx=100,ry,w,ballW,barW; private GView gv;
private Handler hd=new Handler(); @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
gv=new GView(this); setContentView(gv); hd.post(this); }
public void run() { x+=dx;y+=dy;
if (x<=0 || w-ballW<=x) dx=-dx;
if (y<=0) dy=-dy;
if (rx-ballW<=x && x<=rx+barW && y+ballW==ry) // ラケットで跳ね返す dy=-dy;
gv.invalidate();
hd.postDelayed(this,100); }
class GView extends View { private Bitmap ball,bar;
public GView(Context context) { super(context);
ball=BitmapFactory.decodeResource(getResources(),R.drawable.ball); bar=BitmapFactory.decodeResource(getResources(),R.drawable.bar); ballW=ball.getWidth();
barW=bar.getWidth(); }
public void onDraw(Canvas canvas){ w=getWidth();
ry=(getHeight()/10)*10-100; canvas.drawColor(Color.WHITE); canvas.drawBitmap(ball,x,y,null); canvas.drawBitmap(bar,rx,ry,null); }
}
public boolean onTouchEvent(MotionEvent event) { // ラケットの移動 if (event.getAction()==MotionEvent.ACTION_MOVE){ rx=(int)event.getX()-barW/2; if (rx<barW/2) rx=0; if (rx>w-barW) rx=w-barW; gv.invalidate(); } return super.onTouchEvent(event);
} }
17-2 複数のテキストを読み上げる
txt[ ]配列の読み上げテキストが行単位で格納されているとき、行間に 1 秒のサイレント を入れるには以下のようにします。なお、複数のテキストを連続して読み上げる場合は 「QUEUE_ADD」モードにします。「QUEUE_FLUSH」モードだと最後のテキストしか 読み上げられません。
for (int i=0;i<n;i++){
ts.speak(txt[i],TextToSpeech.QUEUE_ADD,null); ts.playSilence(1000,TextToSpeech.QUEUE_ADD,null); } 「例題17-2」複数のテキストを、行間に 1 秒のサイレントを入れて読み上げます。 ・MainActivity.java package com.example.speech2; import java.util.Locale; import android.app.Activity; import android.os.Bundle; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.OnInitListener; import android.view.MotionEvent; import android.widget.*;
public class MainActivity extends Activity implements OnInitListener{ private TextToSpeech ts;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); ts=new TextToSpeech(this,this);
}
public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN){
if (ts.isSpeaking()) ts.stop(); ts.setSpeechRate(1.0f);
for (int i=0;i<txt.length;i++){
ts.speak(txt[i],TextToSpeech.QUEUE_ADD,null); ts.playSilence(1000,TextToSpeech.QUEUE_ADD,null); }
}
return super.onTouchEvent(event); }
public void onInit(int status) { if (status==TextToSpeech.SUCCESS){ Locale locale=Locale.ENGLISH;
if (ts.isLanguageAvailable(locale)>=TextToSpeech.LANG_AVAILABLE) ts.setLanguage(locale);
else
Toast.makeText(this,"この言語は未サポートです ",Toast.LENGTH_LONG).show();
} else
Toast.makeText(this,"音声合成できません",Toast.LENGTH_LONG).show(); }
protected void onDestroy(){ super.onDestroy();
if (ts!=null) ts.shutdown(); }
17-3 通訳アプリ
音声合成機能を使って簡単な通訳アプリを作ることができます。 「例題17-3」ListView に登録した日本語に対応する英語を読み上げます。 ・activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> ・MainActivity.java package com.example.speech3; import java.util.Locale; import android.app.Activity; import android.os.Bundle; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.OnInitListener; import android.view.*; import android.widget.*;public class MainActivity extends Activity implements OnInitListener{ private TextToSpeech ts;
private String[] Japanese={
"おはよう","こんにちは","おやすみ","ありがとう", "お名前は","お値段は","すみません","美味しいです", "何時ですか","友達になってください","何をお求めですか",
"病院はどこですか","お茶を飲みましょう","もう一度言って下さい"}; private String[] English={
"Good morning","Hello","Good night","Thank you",
"What is the name?","How much is a price?","I'm sorry","I am delicious", "What time is it?","Please make friends","What is it a request in?", "Where is the hospital?","Let's drink tea","Please say once again"}; @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
for (int i=0;i<Japanese.length;i++) adapter.add(Japanese[i]);
ListView lv=(ListView)findViewById(R.id.listview); lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
if (ts.isSpeaking()) ts.stop(); ts.setSpeechRate(1.0f);
ts.speak(English[position],TextToSpeech.QUEUE_FLUSH,null); }
});
ts=new TextToSpeech(this,this); }
public void onInit(int status) { if (status==TextToSpeech.SUCCESS){ Locale locale=Locale.ENGLISH;
if (ts.isLanguageAvailable(locale)>=TextToSpeech.LANG_AVAILABLE) ts.setLanguage(locale);
else
Toast.makeText(this,"この言語は未サポートです", Toast.LENGTH_LONG).show();
else
Toast.makeText(this,"音声合成できません", Toast.LENGTH_LONG).show(); }
protected void onDestroy(){ super.onDestroy();
if (ts!=null) ts.shutdown(); }