アプリ開発日記 #30 ついに、Xamarin.Formsでテキストボックスのあるダイアログの表示に成功
今日の目標
Xamarin.Formsでテキスト入力ができるダイアログを表示する。
実際にやったこと
昨日の時点では、ダイアログを表示しようとした場合に、異常終了でアプリが落ちてしまっていましたが、今日、やっとその原因が判明し、ダイアログの表示に成功しました。
そして、ダイアログ表示時にアプリが異常終了していた原因は、ダイアログ表示の際に引数として渡していたContextが原因でした。
実際のロジック
実際に入力テキストボックス付きのダイアログを表示させたロジックです。
実装したロジックは、以下の3つのパートから作成されます。
1.AndroidとiOSの共通プロジェクトへのInterfaceの実装
using System.Threading.Tasks; namespace DoXXXXX.View.CustomDialog { /// <summary> /// テキスト入力ができるダイアログを表示するためのインターフェース /// </summary> public interface IEntryAlertService { Task<DialogResult> Show(string title, string message, string entryText, string accepte, string cancel); } }
namespace DoXXXXX.View.CustomDialog { /// <summary> /// ダイアログの戻り値を格納するクラス /// </summary> public class DialogResult { public string PressedButtonTitle { get; set; } public string Text { get; set; } } }
2.Xamarin.Androidプロジェクトへのクラスの追加
Android用のダイアログを表示するためのロジックです。
Xamarin.Androidプロジェクト側では、1で追加したInterfaceを実装したクラスを作成します。
そして、Dependencyサービスをアトリビュートすることで、共通処理からDependencyサービス経由でAndroidのダイアログを呼び出すことが可能です。
なお、[assembly: Dependency(typeof(EntryAlertService))]はnamespaceの外側に記述する必要があります。
そのため、Xamarin.Androidプロジェクトで作成したダイアログの名前空間をusingする必要があります。
[assembly: Dependency(typeof(EntryAlertService))] namespace DoXXXXX.Droid { public class EntryAlertService : IEntryAlertService { public Task<DialogResult> Show(string title, string message, string entryText, string accepte, string cancel) { var tcs = new TaskCompletionSource<DialogResult>(); var edtSwotItem = new EditText(MainActivityContext.MainViewContext); edtSwotItem.InputType = global::Android.Text.InputTypes.ClassText; edtSwotItem.Text = entryText; edtSwotItem.SetWidth(200); // ダイアログの作成 var dialogBuilder = new AlertDialog.Builder(MainActivityContext.MainViewContext); // ダイアログのタイトル、メッセージ、テキストボックスの設定 dialogBuilder.SetTitle(title); dialogBuilder.SetMessage(message); dialogBuilder.SetView(edtSwotItem); // ダイアログボタンの設定 dialogBuilder.SetNegativeButton(cancel,(obj,e) => tcs.SetResult( new DialogResult() { PressedButtonTitle = cancel, Text = edtSwotItem.Text })); dialogBuilder.SetPositiveButton(accepte, (obj, e) => tcs.SetResult( new DialogResult() { PressedButtonTitle = accepte, Text = edtSwotItem.Text })); dialogBuilder.Show(); return tcs.Task; } } }
そして、今回ダイアログが表示できなかった原因は、ダイアログ作成時に渡していた引数(上記ソースコードではMainActivityContext.MainViewContextを渡している箇所)にAndroid.App.Application.Contextを渡していたためでした。
Androidのダイアログを表示するために必要となるコンテキストは、画面Activityのコンテキストである必要があります。
しかし、Android.App.Application.Contextは画面Activityのコンテキストではないようです。
そして、Forms.Contextは、新しいバージョンでは使用することができません。
そのため、多少強引ではありますが、staticクラスを作成し、Xamarin.AndroidプロジェクトのMainActivityのOnCreateの中で、MainActivityをstaticクラスのプロパティーに設定することで、Android用のダイアログを表示するくらすでもしようできるようにしています。
(ちなみに、MainActivityContext.MainViewContextがMainActivityを設定したstaticクラスのプロパティーです)
3.Xamarin.iOSプロジェクトへのクラスの追加
iOS用のダイアログを表示するためのロジックです。
iOS版も、基本はAndroid版と同じになります。
なお、iOS版でもAlertViewが非推奨となっておりましたので、UIAlertControllerを使用するようにしています。
※iOS版は動作の確認を行っていません。
[assembly:Dependency(typeof(EntryAlertService))] namespace DoXXXXX.iOS { public class EntryAlertService : IEntryAlertService { public Task<DialogResult> Show(string title, string message, string entryText, string accepte, string cancel) { var tcs = new TaskCompletionSource<DialogResult>(); UIApplication.SharedApplication.InvokeOnMainThread( () => { // ダイアログの作成 var dialog = new UIAlertController(); dialog.Title = title; dialog.Message = message; dialog.AddTextField( (textField) => { textField.Text = entryText; }); // ダイアログボタンのイベントの登録 var cancelAction = UIAlertAction.Create(cancel, UIAlertActionStyle.Cancel, (action) => tcs.SetResult( new DialogResult() { PressedButtonTitle = cancel, Text = dialog.TextFields[0].Text })); dialog.AddAction(cancelAction); var acceptAction = UIAlertAction.Create(accepte, UIAlertActionStyle.Cancel, (action) => tcs.SetResult( new DialogResult() { PressedButtonTitle = accepte, Text = dialog.TextFields[0].Text })); dialog.AddAction(acceptAction); // ダイアログの表示 dialog.PresentViewController(dialog.PresentedViewController, true, null); }); return tcs.Task; } } }
明日への思い
ダイアログで入力された値で、データを更新できるようにする。
更新した情報で画面を再描画できるようにする。
入力エラーがあった場合は、入力ダイアログを再表示できるようにする。
最近読んだ本
1分で話せ 世界のトップが絶賛した大事なことだけシンプルに伝える技術
- 作者: 伊藤羊一
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2018/03/14
- メディア: 単行本
- この商品を含むブログ (1件) を見る
改訂版 金持ち父さん 貧乏父さん:アメリカの金持ちが教えてくれるお金の哲学 (単行本)
- 作者: ロバートキヨサキ,白根美保子
- 出版社/メーカー: 筑摩書房
- 発売日: 2013/11/08
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (6件) を見る
読みたい本
- 作者: Jr FrederickP.Brooks,Jr.,Frederick P. Brooks,滝沢徹,牧野祐子,富澤昇
- 出版社/メーカー: 丸善出版
- 発売日: 2014/04/22
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (19件) を見る
- 作者: 成瀬 雅光
- 出版社/メーカー: 日経BP
- 発売日: 2018/03/30
- メディア: Kindle版
- この商品を含むブログを見る
プログラムをもっときれいに書けるようにするために
- 作者: エリックガンマ,ラルフジョンソン,リチャードヘルム,ジョンブリシディース,Erich Gamma,Ralph Johnson,Richard Helm,John Vlissides,本位田真一,吉田和樹
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 1999/10
- メディア: 単行本
- 購入: 21人 クリック: 711回
- この商品を含むブログ (202件) を見る
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
- 作者: Dustin Boswell,Trevor Foucher,須藤功平,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2012/06/23
- メディア: 単行本(ソフトカバー)
- 購入: 68人 クリック: 1,802回
- この商品を含むブログ (140件) を見る
C#実践開発手法 デザインパターンとSOLID原則によるアジャイルなコーディング
- 作者: ゲイリーマクリーンホール
- 出版社/メーカー: 日経BP社
- 発売日: 2015/06/25
- メディア: Kindle版
- この商品を含むブログ (1件) を見る