【Unity】Androidでスイッチで設定を変更するダイアログを使う 
2017/11/22 Wed [edit]
今回は Android で設定画面などによく使われるスイッチ(トグルボタン)を動的生成するカスタムダイアログを作ってみた。これは実質的には複数選択ダイアログと変わらないのだが、スイッチの場合はオン・オフを明確にするのに良いかも知れない。つまり、複数選択はオン(=選択された)のみでオフ(=選択されない)は結果に送られてこないが、スイッチはオン・オフどちらも送られてくるという違いを設けてある(→オン以外はオフと検出すればどちらも同じ結果となる)。スイッチは Unity には標準ではない UI なので(もちろん「Toggle」や「Slider」をいい感じにエディットすれば同じことはできるが)意外と便利な気がする。
今回も Androidの基本機能を利用するプラグインのアップデート版となる。追加内容・仕様変更などはなるべく更新履歴に書くようにしているが、基本的にはそのまま使えるようにしているので、旧バージョンがある場合は上書きでも構わないと思う。プラグイン自体のセットアップは以前の記事を参照して欲しい。自分で作りたい場合は簡略化したものだが、今回も元の Java コードを書いておくので挑戦してみるのも良いだろう(※Java コードは解説用に一部抜粋・省略したものであって、そのままコピペでは使えないことに注意)。
|
パッケージに同梱されているサンプルでは、シーン「Assets/_Test/Scenes/DialogExTest」にまとまっているので、適当に複製などして自由に使って欲しい。
(※) Unity 5.6.3p1 / AndroidStudio 2.3.3 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認
■スイッチダイアログ(カスタムダイアログ)を使う

●Unity から Android のスイッチダイアログ(カスタムダイアログ)を使う C# コード
using FantomLib;
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowSwitchDialog(title, message, items[], itemKeys[], checkedItems[], itemsTextColor,
callbackGameObject, callbackMethod, okCaption, cancelCaption, style);
#endif
●プラグイン内の対応する Java コード
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.widget.CompoundButton;
import android.widget.Switch;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;
CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checkedItems[(int)buttonView.getTag()] = isChecked;
}
};
DialogInterface.OnClickListener oklistener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
String str = "";
for (int i = 0; i < items.length; i++) {
if (i > 0)
str += "\n";
if (itemKeys != null)
str += itemKeys[i] + "=" + checkedItems[i];
else
str += checkedItems[i];
}
UnitySendMessage(callbackGameObject, callbackMethod, str);
}
}
};
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
for (int i = 0; i < items.length; i++) {
Switch sw = new Switch(context);
sw.setTag(i);
sw.setChecked(checkedItems[i]);
if (itemsTextColor != 0)
sw.setTextColor(itemsTextColor);
sw.setText(items[i]);
sw.setOnCheckedChangeListener(listener);
layout.addView(sw);
}
AlertDialog.Builder builder = new AlertDialog.Builder(context, styleId);
builder.setTitle(title)
.setMessage(message)
.setView(layout.getRootView())
.setPositiveButton(okCaption, oklistener)
.setNegativeButton(cancelCaption, null)
.show();
これはスイッチのオン・オフの選択状態を返すことによって機能を切り替える等のカスタムダイアログである。スイッチ以前はトグルボタンがよく使われていたが、近年ではスイッチの方が設定画面などに使われることが多い(内容的には形状の違いだけで同じものと考えて良い)。少し前に作った複数選択もオン・オフという意味では近いが、こちらはオフの設定も結果として送られてくるという違いがある。
戻り値は「OK」ボタンを押したとき、キー(itemKeys)が設定されている場合は "key=true" または "key=false" のようにイコール("=")でキーと真偽値のペアが、キーが未設定(itemKeys = null)のときは、真偽値のみが、改行("\n")で結合されて、ヒエラルキーにある GameObject 名(callbackGameObject)のメソッド(callbackMethod)に文字列で返ってくる。またキャンセルボタンを押した時と、Android のダイアログの場合、範囲外をクリックするとダイアログが消えるが、その場合は何も返って来ない。
一応簡単に、戻り値のオン・オフ状態を取得するコードを書いておくと、 C# では、
string[] arr = result.Split('\n'); //result を結果の文字列とする
bool[] switched = new bool[arr.Length]; //オン・オフの状態を格納する配列
for (int i = 0; i < arr.Length; i++)
{
switched[i] = arr[i].EndsWith("true");
}
//※ System.Linq を使うなら以下でも同じ
var switched = result.Split('\n').Select(e => e.EndsWith("true")).ToArray();
でも十分だろう。キーを設定した場合は、連想配列(Dictionary, Hashtable)に格納した方が使いやすいかも知れない。基本的に Android → Unity でのやりとりは一つづきの文字列なので、適宜加工して使うことになる。
また、サンプルには設定などを簡単に保存できるように、PlayerPrefs を少し拡張して、真偽値、オブジェクト(クラス・構造体)、配列、リスト、辞書、キー&値ペア配列を保存できるクラスを「Assets/FantomLib/Scripts/System/XPlayerPrefs.cs」にまとめておいた。特にダイアログ専用というわけではないので、他のデータ保存など自由に使って貰っても構わない。
あと、Android のダイアログの仕様という感じなのだが、ダイアログに収まりきらないほどオブジェクトを並べた場合、メッセージ文字列(タイトルの下に表示される文字列)が非表示となることに注意(タイトルと決定ボタンのみは上下に固定され、並べたオブジェクトはスクロールされる)。どうしてもメッセージ文字列を表示したい場合は、ダイアログの大きさに収まる数で配置して、いくつかのダイアログに分けた方が良いだろう(そちらの方がスクロールで見えない部分もなく、項目を探しやすいというメリットもある)。
また、テキスト色に関しては、プラグインは Java で作ってあるため int 型の ARGB 形式になっているが、少し不便に感じたので、Unity の Color 形式のオーバーロードも作っておいた。あと少し特殊な仕様として色のパラメタ(ここでは itemsTextColor)に int値で 0 (= Color.clear)を与えた場合「指定なし」となるようにしてある(本来なら 0 は無色透明になるが、テキスト色には必要ないため)。ダイアログのスタイルの引数(ここでは style)を当てることもやってみたが、上手く反映されないようなので、個別に設定するようにした次第だ。指定するのが面倒なときはとりあえず 0 にしておけば良い(通常は黒になると思う)。また、int 型の ARGB 形式と Unity の Color 形式の相互変換は「Assets/FantomLib/Scripts/Graphics/XColor.cs」にまとめておいたので、自由に使って貰っても構わない。
ダイアログにはスタイル(テーマ)を当てられるようにしてある。省略=空文字("")のときはアクティビティのテーマと同じものになる。スタイルの引数は "android:Theme.DeviceDefault.Dialog.Alert" のように、名前のアンダバー("_")をドット(".")に変えたものを指定する。端末の API Level によって使えるものとそうでないものがあるので、アプリのビルドの API Level に合わせて指定する必要があるので注意。
(参考)R.style.theme
サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestDialogSwitch()」「ReceiveSwitches()」あたりを見て欲しい。
■更新履歴
今回のアップデートを簡単に説明しておくと以下のようになる。[⇒全体の更新履歴はこちら]
・スイッチダイアログ(カスタムダイアログ)を追加。
・スライダーダイアログ(カスタムダイアログ)を追加。
・真偽値、オブジェクト(クラス・構造体)、配列、リスト、辞書、キー&値ペアを保存する「XPlayerPrefs」クラスをライブラリとして追加。
※以前のバージョン上書きでも問題なく動作すると思います。
実際の Java コードは色々値をチェックしたり条件分岐したり、高速化のためにキャッシュしたり、StringBuilderを使ったりしているが、長くなるのでここでは簡略化したものを書いてあると考えて欲しい。Java を知っている人なら中身は非常に簡単なものばかりなので、AndroidStudio を使ったことあるなら AAR プラグインをビルドするのに挑戦してみるのも良いだろう。
※この記事のUnityアセットはプラグインとして配布されています。
(関連記事)
【Unity】Androidでカスタマイズしたダイアログを動的生成できるプラグインを作ってみた
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】Androidでスライダーで設定を変更するダイアログを使う
【Unity】Androidで日付・時刻選択ダイアログ(DatePicker, TimePicker)を使う
【Unity】Androidで数値・半角英数・パスワード入力ダイアログを使う
【Unity】Androidでテキスト入力ダイアログを使う
【Unity】Androidの選択ダイアログを使う
【Unity】Androidのテキスト読み上げ(TextToSpeech)を使う
【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする
【Android】【Java】AlertDialog を使ってみる
- 関連記事
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/280-308c046a
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |