16
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Xamarin.Forms でテキスト入力可能なダイアログを表示する

Last updated at Posted at 2014-07-02

Xamarin.Forms にはシンプルなポップアップダイアログを表示する手段が標準で提供されています。

Pop-ups | Xamarin

とてもシンプルであるため、この方法で取得できるのは"Yes/No"、または"複数ある内のどのボタンが押されたか"だけです。

そこで、この記事ではDependencyServiceを使って"パスワード入力などに利用可能なダイアログを表示する方法"をご紹介します。

プロジェクトの作成

新規にソリューションを作成します。種類はBlank Apps (Xamarin.Forms Portable)、名前はEntryAlertSampleにします。

PCLプロジェクト

EntryAlertSampleプロジェクトに空のインターフェースIEntryAlertService.csを新規作成し、中身を以下のように書きます。ShowメソッドのisPasswordパラメータの設定で入力テキストを隠せるようにします。

EntryAlertResultは押されたボタンと入力テキストを返すためのデータクラスです。

IEntryAlertService.cs
using System.Threading.Tasks;

namespace EntryAlertSample
{
	public interface IEntryAlertService
	{
		Task<EntryAlertResult> Show(string title, string message,
			string accepte, string cancel, bool isPassword = false);
	}

	public class EntryAlertResult
	{
		public string PressedButtonTitle { get; set; }
		public string Text { get; set; }
	}
}

MainPage.csを追加し、動作検証用のボタンとラベルを持ったMainPageクラスを定義します。

MainPage.cs
using Xamarin.Forms;

namespace EntryAlertSample
{
	public class MainPage : ContentPage
	{
		public MainPage ()
		{
			var label = new Label ();
			var plainTextButton = new Button { Text = "Show plain text dialog" };
			var passwordButton = new Button { Text = "Show password dialog" };

			plainTextButton.Clicked += async (sender, e) => {
				var result = await DependencyService.Get<IEntryAlertService>().Show(
					"Prain text", "Please enter text.", "OK", "Cancel", false);
				label.Text = string.Format("{0}:{1}", result.PressedButtonTitle, result.Text);
			};

			passwordButton.Clicked += async (sender, e) => {
				var result = await DependencyService.Get<IEntryAlertService>().Show(
					"Password", "Please enter password.", "OK", "Cancel", true);
				label.Text = string.Format("{0}:{1}", result.PressedButtonTitle, result.Text);
			};

			Content =  new StackLayout {
				Orientation = StackOrientation.Vertical,
				VerticalOptions = LayoutOptions.CenterAndExpand,
				HorizontalOptions = LayoutOptions.CenterAndExpand,
				Children = { label, plainTextButton, passwordButton }
			};
		}
	}
}

最後にApp.csファイルを次のように修正します。

App.cs
...省略
public class App
{
	public static Page GetMainPage()
	{   
		return new MainPage();
	}
}

iOSプロジェクト

EntryAlertSample.iOSプロジェクトにEntryAlertService.csを新規作成し、EntryAlertSampleプロジェクトで定義したIEntryAlertServiceインターフェースを実装します。[assembly: Dependency (typeof(EntryAlertService))]の記述により、PCLプロジェクトからDependencyService経由でEntryAlertServiceのインスタンスを取得することが可能になります。

EntryAlertService.cs
using EntryAlertSample;
using EntryAlertSample.iOS;
using Xamarin.Forms;
using MonoTouch.UIKit;
using System.Threading.Tasks;

[assembly: Dependency (typeof(EntryAlertService))]

namespace EntryAlertSample.iOS
{
	public class EntryAlertService : IEntryAlertService
	{
		public Task<EntryAlertResult> Show (string title, string message,
		                                    string accepte, string cancel, bool isPassword = false)
		{
			var tcs = new TaskCompletionSource<EntryAlertResult> ();

			UIApplication.SharedApplication.InvokeOnMainThread (() => {
				var alert = new UIAlertView (title, message, null, cancel, new[]{ accepte });
				
				if (isPassword) {
					alert.AlertViewStyle = UIAlertViewStyle.SecureTextInput;
				} else {
					alert.AlertViewStyle = UIAlertViewStyle.PlainTextInput;
				}

				alert.Clicked += (sender, e) => tcs.SetResult (new EntryAlertResult {
					PressedButtonTitle = alert.ButtonTitle (e.ButtonIndex),
					Text = alert.GetTextField (0).Text
				});
				alert.Show ();
			});

			return tcs.Task;
		}
	}
}

ポイントはTaskCompletionSource<T>を使用していることです。ボタンが押された際にTaskCompletionSource<T>.SetResult(T)を実行することにより、IEntryAlertService.Showの呼び出し側でダイアログの入力完了を待機可能になります。ダイアログの表示にはUIAlertViewを使います。

Androidプロジェクト

EntryAlertSample.AndroidプロジェクトもiOSプロジェクトと同様にEntryAlertService.csを新規作成し、EntryAlertSampleプロジェクトで定義したIEntryAlertServiceインターフェースを実装します。

EntryAlertService.cs
using System.Threading.Tasks;
using Android.App;
using Android.Widget;
using Xamarin.Forms;

using EntryAlertSample;
using EntryAlertSample.Android;

[assembly: Dependency (typeof(EntryAlertService))]

namespace EntryAlertSample.Android
{
	public class EntryAlertService : IEntryAlertService
	{
		public Task<EntryAlertResult> Show (string title, string message,
		                                    string accepte, string cancel, bool isPassword = false)
		{
			var tcs = new TaskCompletionSource<EntryAlertResult> ();

			var editText = new EditText (Forms.Context);
			if (isPassword) {
				editText.InputType = global::Android.Text.InputTypes.TextVariationPassword
				| global::Android.Text.InputTypes.ClassText;
			}

			new AlertDialog.Builder (Forms.Context)
				.SetTitle (title)
				.SetMessage (message)
				.SetView (editText)
				.SetNegativeButton (cancel, (o, e) => tcs.SetResult (new EntryAlertResult {
				PressedButtonTitle = cancel,
				Text = editText.Text
			}))
				.SetPositiveButton (accepte, (o, e) => tcs.SetResult (new EntryAlertResult {
				PressedButtonTitle = accepte,
				Text = editText.Text
			}))
				.Show ();

			return tcs.Task;
		}
	}
}

EditTextAlertDialog.Builderのコンストラクタで必要なコンテキストはForms.Contextから取得します。Androidから始まる名前空間がEntryAlertSample.Androidと認識されてしまうためglobal::から始める必要があります。

実行結果

実行すると次の画面のようになります。

iOS

スクリーンショット 2014-07-02 22.30.52.jpg

Android

スクリーンショット 2014-07-02 22.26.15.jpg

16
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?