このサイトでは、分析、カスタマイズされたコンテンツ、および広告に Cookie を使用します。このサイトを引き続き閲覧すると、Cookie の使用に同意するものと見なされます。
Hi, Developers,
straightapps.com ロゴ
作成 July 23, 2022
トップページ > Android 開発トップ > Android Studio でボタン表示&入力
line
Android 開発
line

ここでは、Android Studio でボタンを表示し入力を受け付けるコードについて、書いています。

Canvas だけでもアプリはできる!

ノート PC に、Visual Studio Community 2022 の C++ によるモバイル開発機能のインストールと、 その時点で最新だった Android Studio のインストールを完了しましたので、 Android アプリの開発環境が整ったということになりました。

Android Studio で文字を自由に描画する」 で、独自のビューを作成して Empty Activity に設定し文字を描画、 続く「Android Studio で画像を自由に描画する」 で、PNG 画像をプロジェクトに取り込んで、描画関数 onDraw が引数で受け取った Canvas画像を描画しました。 拡大・縮小もできていますし、画面タッチの検出もできました。

Android Studio でタイマーによる自動画面更新」ではタイマーをセットし、 一定間隔で独自に作成したビューを無効化して、ユーザーの操作がなくても画面を更新できるようにし、 「Android Studio で効果音を鳴らす」では、クイズで正解したときなどに鳴らす 短い効果音の再生処理も実装しました。

前回「Android Studio で画面を準備する」では画面の事前準備として、 アクションバーの非表示画面を縦固定背景画像の描画、 そして画面のタッチからブラウザでウェブサイトを開く、といった項目を実装しています。

ここではゲームに必要な、ボタンの表示やタッチによるボタン入力、関連して座標計算のコードを検討しています。

ここまで作成したコードへの追記の形となっていますが、すべて必要と言うわけではありません。

過去すでに Android Studio を別のマシンで使用して 「素因数分解トレーニングアプリ」 を開発していますが、改めてちゃんとアプリを作りたいな、と思い、リスタートしています。

なお、使用している Android Studio は、2022 年 5 月中旬にインストールした、2021.2.1 Patch 1 の Chipmunk です。

android studio chipmunk

▼ セクション一覧

座標管理クラスを作成する
ボタンを描画する
ボタンのタッチを認識する
ゲームクラスを作成しておく

なお、本サイトの ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。

座標管理クラスを作成する

投稿 July 23, 2022

Android Studio で画面を準備する」で描画した背景画像に、 4 つのボタンを描画して、入力を受け付けたいと思います。

背景画像

ボタンの配置を行うために、まずはボタン画像を Drawable に取り込みましょう。 詳しい手順は「描画したい画像を用意する」に書いています。

今回ボタン画像として用意したのは、560 x 240 ピクセルで透過ありの png 画像です。 ファイル名は、button_bg.png です。 アンダースコアは使えますが、mp3 ファイルの登録で失敗したようにハイフンが使えないかもしれませんので、お気を付けください。

ボタン画像登録

簡単に書くなら、画面左側で Resource Manager を開き、 Drawable タブを選択した状態で、エクスプローラーから画像ファイルを Ctrl キーを押しながら、ドロップします。 その後、確認画面を進めば、画像が登録されます。 ここで登録したリソース名はファイル名のまま、button_bg です。

アプリ独自のビューとして作成した FlashSosuuView クラスの最初で、 bmpBtn にこの画像データを読み込んでおきます。

ボタン画像の読み込み

背景画像の読み込みに続けて、ボタン背景画像を読み込むようにしています。

private Bitmap bmpBtn = BitmapFactory.decodeResource(getResources(),R.drawable.button_bg);

これでボタン画像の描画準備ができましたので、どこにボタンを表示するかを決めます。

背景画像を描画するとき、 「背景画像を描画する(座標計算)」で、 さまざまな画面解像度のデバイスを解像度を気にせずに扱えるよう、 画面が 900 x 1,600 ピクセルであるとして座標を指定することにしましたので、 900 x 1,600 ピクセルであるとして、そのどこにボタンを表示するかを決めることになります。

用意した 900 x 1,600 ピクセルの背景画像の上部にはアプリタイトルと、「次のうち、素数はどれ?」の文字があります。 この文字の下、y 座標は 600 から下にスペースがあります。

背景画像の下のほうには「2022 StraightApps.com」の文字がありますが、 以前「ウェブサイトを開く」で y 座標 1,400 より下 ( 画像で確認すると、本当は 1,480 ぐらいが最適でした。 ) はウェブサイトを開くようにしていますので、y 座標 1,400 位置まではボタンに使えます。

空いている y 領域は 600 から 1,400 までの 800 ピクセルで、4 選択肢(ボタン)を表示したいので、1 選択肢は 200 ピクセルまで使えます。 1 ボタンを横 560 ピクセル、縦 140 ピクセルのサイズで、x 座標は (900 - 560) / 2 = 170、y 座標はそれぞれ 600、800、1000、1,200 で表示することにします。 なお、ここではピクセルと書いていますが、 画面の座標やサイズではなく、900 x 1,600 ピクセル座標系での「ピクセル」です。

背景画像の描画時には、背景画像を表示する領域を画面の 900 x 1,600 サイズで中央いっぱいにするよう計算しましたが、 ここでは座標計算用のクラスを作成して、計算を行うことにします。

プロジェクトのパッケージ名を選択して、右クリックメニューを表示させます。

Java Class の追加

NewJava Class と選択し、 Class が選ばれた状態で、saCoords クラスを作成します。

New Java Class

もちろん作成するクラス名は自由で構いませんが、 あまりにも一般的な名前だと既存の、あるいは将来的にシステムと当たるかもしれませんので、少し工夫した感じがいいでしょう。 ちなみに saCoords の sa は当サイト StraightApps の略、Coords は座標を意味する Coordinates を省略したものです。

Enter キーを押すと saCoords クラスが作成され、開かれますので、コードを追加します。

計算に必要なのは実際の画面のサイズ拡大・縮小レートですので、変数を定義し、設定関数を作成します。 変数名は、背景画像の描画時に定義した FlashSosuuView クラスのものと同じ名前にしておきます。

変数の定義

SetViewSize 関数を実装し、各値を計算します。 ビューが作成されたとき onWindowFocusChanged 関数からこの関数を呼び出す想定です。

SetViewSize 関数

これは単なる関数ですので、ただ入力すればいいものです。 メニューなどから挿入する必要はありません。 900 x 1,600 を柔軟に変更できるよう、cxCoordscyCoords を定数として定義して使用しています。

定数の定義

続けて、900 x 1,600 系で指定した座標から実際の画面の座標を計算して返す関数を実装します。

GetRealRect 関数

GetRealRect 関数として、欲しい領域の左上の座標と右下の座標をもらい、Rect を返すことにします。 Rect が import されていませんから、マウスポインタをのせ、Import class で解決します。

GetRealRect 関数

画面中央部に表示するためにオフセット値を加味して、disp_rate の拡大・縮小率を掛けて算出しています。

何もしませんが、コンストラクタもあったほうがいいでしょう。

コンストラクタ

ひとまずこれで、座標計算クラスの最低限の実装ができました。


FlashSosuuView クラスで座標計算クラス saCoords を作成し、sacoords に入れます。 coords はすでに使われている名称のようですから、使えません。 いま思えば m_coords にしたいのですが、ここまでそういうルールできていませんので、まぎらわしいですが sacords にしています。

座標計算クラスの定義

onWindowFocusChanged 関数で背景画像を描画するために座標を計算している部分、 うまくいかない場合に備え、 今までのコードも残したまま ( 新しいコードで問題がないことを確認してから削除します。 ) にして、sacoords を呼び出しています。

SetViewSize 関数呼び出し

背景画像を描画している onDraw 関数で、 背景画像の座標指定を、sacoords での指定に変えてみます。

onDraw 関数

これで今までと同じように背景画像が表示されるはずですので、ここまで実機でテストしてみます。 実機でのテストについては、「実機で動作を確認」に詳しく書いています。

問題なく、同じように背景画像が表示されましたので、 独自のビュー FlashSosuuView 内部での座標計算を削除します。

不要なコードの削除

スッキリしました。

タッチイベント処理 onTouchEvent 関数も調整が必要でしたので、ついでに y 座標が 1,480 〜 1,600 ピクセルの領域内(より適切な座標範囲)ならウェブサイトを開くようにしました。

onTouchEvent 関数

反応する領域をいったん Rect 型の r に設定し、その内側かどうかを判定しています。

▲ページ先頭へ

ボタンを描画する

投稿 July 23, 2022

座標計算クラスを作成できましたので、4 つのボタン背景を描画してみます。

まずは単純に、onDraw 関数の背景描画のあとにに、ボタンの描画コードを追加してみます。

onDraw 関数

drawBitmap 関数 では画面に対する座標を渡す必要がありますので、先ほど作成した GetRealRect 関数で実際の座標を得て、描画しています。

第 3、第 4 引数は計算式で指定していますが、このほうが間違いありませんし、 ビルドの際には計算された値が使用されるはずですので、処理上の無駄はなく、わかりやすいです。

問題なく、描画が行われました。

ボタン表示

あとで回答入力のためのボタンタッチ位置の判定にも使用しますので、 4 つのボタンの座標は、毎回計算せず、あらかじめ変数として持っておくことにします。

Rect 変数定義

ここでは 4 変数にしていますが、配列で用意するほうが美しいかと思います。

値の設定は、座標計算クラスの SetViewSize 関数 を呼び出したあとに行う必要がありますので、onWindowFocusChanged 関数に追加します。

onWindowFocusChanged 関数

これで、描画関数 onDraw がシンプルになります。

onDraw 関数

onDraw 関数でのボタン描画コードがかなりスッキリしました。


タイマーの動作確認のために、「value = 0」のようなテキストを描画していますが、 その部分を書き換えて、ボタンに文字が表示されるようにしてみます。

onDraw 関数の、"value" の文字列を表示している部分をコメントアウトし、 ボタン 1 に "abc" の文字が表示されるようにしてみます。

onDraw 関数

Rect 型の rcBounds を用意して、センタリング表示のため、描画する文字のサイズを取得することにします。

Paint クラスsetTextSize では、文字のサイズを適当なピクセル単位のサイズを指定していますので、それが実際には何ピクセルになるのかを知る必要があります。 getTextBounds 関数で、 必要な領域のサイズがわかります。

取得できた rcBounds の left と top は 0 だと思いますが、形としてサイズを計算するようにし、 ボタン 1 の領域 rcButton1 の中央に表示されるよう、x と y を計算しています。 なお、y 指定は文字の下端ですので、bottom からマイナスする形になっています。

これでボタン 1 の中央に "abc" の文字が表示されるはずです。

ボタンに文字表示

ちゃんと表示されましたので、問題に対する選択肢をボタンに表示する方法について、解決と言えます。

▲ページ先頭へ

ボタンのタッチを認識する

投稿 July 25, 2022

タッチしたボタンの認識テストとして、 それぞれのボタンがタッチされたとき、画面にどのボタンがタッチされたかを表示します。 表示方法は、開発中のみですので、 Toast を使います。 短いメッセージが短時間、画面に表示され、消えるものです。

タッチイベント処理関数 onTouchEventACTION_UP に処理を追加します。

タッチイベント

追加位置は、画面下部のリンクを開く領域かを判定したあとです。

すべてのボタンの有効な x 領域は同じですので、さきに x 領域内にあるかどうかを判断しています。 気にするほどのことではないとも言えなくはありませんが、これで少しでも無駄な判断を減らせます。

続けて、y 位置がボタン 1 〜 ボタン 4 の領域内にあるかを判断してから、どのボタン領域内にあるかを判定しています。 今はまだ、それぞれコメントを置いているだけです。

ちゃんと判定できているかを確認するため、 Toast を使って確認できるようにします。

Toast 表示

いったんコメントにしていたそれぞれのボタン処理で、 Toast クラスの makeText 関数で指定の文字列を持ったトーストを作成し、 そのまま show 関数を呼び出すと、トーストが表示されます。

同じように、ボタン 2 〜 4 にも追加しておきます。

実機で実行させると、正しく判定されていることがわかりました。

Toast 表示

▲ページ先頭へ

ゲームクラスを作成しておく

投稿 July 25, 2022

次はいよいよ、ゲームクラスを作成してゲームを成立させます。

内容的にはそこそこのボリュームになるでしょうから、ここではクラスの作成までを行っておきます。 クラスの作成は、座標計算クラスを作成した手順と同じです。

簡単に振り返れば、Android Studio 画面の左側、 app の java にあるパッケージ名を右クリックし、NewJava Class と選択していきます。

クラス名は何でも構いませんが、saGame と名前を付けました。 一般的すぎない名前であれば、将来的にも問題ないでしょう。

ゲームクラス

クラスを作成できたら、とりあえず必要になりそうな変数を定義しました。

変数定義

nNumSosuu は、100 までの素数の数で、 このあとに定義している配列 nSosuu の要素数と一致することにしています。 final で定義していますので変更不可、あとで代入して別の値を設定することはできません。 C/C++ でいう const や #define のイメージだと思います。

nSosuu は int 型の配列で、100 までの素数を保持することにしています。 このように中カッコで囲んだカンマ区切りの要素を並べることで、配列を一気に初期化できるようです。 こちらも final にしていますので、書き換え不可です。 コメントアウトしているように、いったん配列として定義して初期化しない場合、 1 つづつ値を設定する必要があるようですから、面倒になります。

bInPlay は、ゲーム中かどうかを判断するために使用する予定です。

int 型の nOpt 配列は、4 つのボタンが持つ値を設定します。

最後に nAnswer として、どれが正解なのかを nOpt 配列のインデックスとして持つこととします。

コンストラクタ

新しい問題を作成する CreateNew 関数を用意しておきます。

Create New 関数

nOpt 配列に、このあと定義する getNonSosuu 関数で取得した「素数ではない値」を設定しています。 そのあと nAnswer に正解とするインデックスを決め、その選択肢を getSosuu 関数で取得した素数を設定しています。 なお、Math.random 関数は、0 以上 1 未満の乱数を返す関数です。 4.0 を掛けて 0 以上 4 未満の値にして、int 型にキャストして 0 から 3 までの整数にしています。

ランダムに素数を 1 つ返す getSosuu 関数も用意しておきます。

getSosuu 関数

Math.random 関数に 100 までの素数の数が設定されている nNumSosuu を掛けて、 0 から nNumSosuu - 1 までの値を nSel に設定、nSosuu 配列の値を返しています。

ランダムに素数ではない値を 1 つ返す getNonSosuu 関数です。

getNonSosuu 関数

n に、4 から 99 までの値を設定しています。 ただし、同じ選択肢が複数になるとゲーム的に良くないので、 引数で受けた値と一致している値なら別の値にします。 また、適当に選んだ値が素数なら、別の値にします。

ここでの最後は、指定の値が素数であるかを判断する isSosuu 関数です。

getNonSosuu 関数

素数リスト nSosuu と一致する値は素数、一致しない場合は素数ではありません。 ただし、ここでは例外的に、本来は素数ではない 1 も、素数として判断されるような処理を追加してあります。


ここまででゲームクラス saGame の形ができました。

将来を見据えて ( 今は 1 つのビューだけで全処理を行いますが、複数ビューになるとビュー内で定義した変数が見えません。 ) 、MainActivity でクラスを作成します。

saGame

onCreate 関数の前で、public な saGame クラス game を作成しています。

いつものように private を付けてしまうと、自分のクラス内からのアクセスのみとなり、 外部クラスである独自のビュー FlashSosuuView からアクセスできなくなると思いますので、注意します。

FlashSosuuView のコンストラクタの最後で、新しい問題を作成する CreateNew 関数を呼び出すようにしてみます。

CreateNew 関数呼び出し

getContext 関数でこのビューの親コンテキストを取得できますので、 MainActivity にキャストして、いったん ma に入れています。

saGame クラスの game は public で定義してありますので、このように参照することができます。


最後に、ボタン上に選択肢を表示するまで、実装します。

onDraw 関数

onDraw 関数で、先ほど "abc" と表示した部分を書き換えて、選択肢 nOpt の値を表示するようにします。

MainActivity の game クラスにアクセスし、getOption 関数で取得した値を String.valueOf 関数で文字列に変換し、いったん str に設定しています。

getOption 関数

必要な領域を getTextBounds 関数で計算し、 ボタンの中央に表示されるよう座標を計算、drawText 関数で描画します。

同じようにボタン 2 以降にも描画を行います。

スクリーンショット

ちゃんと数字が表示され、また、このうち 1 つだけが素数になっています。

▲ページ先頭へ
line
関連トピックス
line

Canvas だけでもアプリはできる! #1
Android Studio で文字を自由に描画する

このシリーズの最初です。 アプリ独自のビューを作成し、テキストを描画するまでのコードを作成しています。

Canvas だけでもアプリはできる! #2
Android Studio で画像を自由に描画する

透過ありの PNG 画像をリソースに追加し、等倍で、あるいは拡大・縮小して描画します。 タッチ処理も追加し、タッチした位置に画像が追従してくるコードにしています。

Canvas だけでもアプリはできる! #3
Android Studio でタイマーによる自動画面更新

MainActivity にタイマーを設定して、一定間隔で処理を呼び出すコードを作成しています。

Canvas だけでもアプリはできる! #4
Android Studio で効果音を鳴らす

効果音のような短い音を鳴らすコードを作成しています。

Canvas だけでもアプリはできる! #5
Android Studio で画面を準備する

効果音再生が不要でしたら、アクションバーの消去、画面の縦固定指定、背景画像描画、そしてタッチでウェブサイトを開くコードに進んでも構いません。


Canvas だけでもアプリはできる! #7
Android Studio でゲームクラスを更新

正解のボタンをタッチしたとき効果音を鳴らす等の正解処理を行い、2 秒後に次の問題に自動的に進む処理を実装しています。 不正解ならトーストで理由を表示します。


Android Studio で全画面プロジェクトを作成する

Empty Activity では画面上部に邪魔になり得るタイトル表示領域がありますが、 Fullscreen Ativity なら、それがなくなるのか、新規プロジェクトを作成して確認しています。

Android Studio で ActionBar を非表示にする

Empty Activity では画面上部に邪魔になり得るタイトル表示領域がありますが、 プロジェクト内の設定の書き換えにより、別プロジェクトにしなくても非表示にできるようです。

Android Studio で Native C++ プロジェクトを作成する

目的としている C++ ネイティブコードを併用する Activity は、 Native C++ プロジェクトを作成すれば、比較的簡単に着手できそうです。

Android Studio で AdMob プロジェクトを作成する

もうひとつの目的としては、AdMob でアプリ内に広告を入れる、です。 AdMob Ads Activity なら簡単に実装できるのでしょうか?

アプリケーション名を指定する

C++ ネイティブアプリでアプリ名を設定する方法の詳細を検討しています。

line
その他のおすすめ
line

Android 開発に関する記事をまとめた Android 開発トップ もご覧ください。

素因数分解トレーニング

以降の数学の基本となる素因数分解の基本部分を、ひたすらトレーニングするための JavaScript コードについて書いています。

因数分解トレーニング(1)

因数分解の公式の一部について、ひたすらトレーニングするための JavaScript コードについて書いています。



© 2017-2022 StraightApps.com 無断転載を禁じます。No reproduction without permission.