Xamrin.Forms アラートダイアログ(DisplayAlert)に画像を追加する方法

Xamrin.Forms アラートダイアログ(DisplayAlert)に画像を追加する方法を説明します。

1.共通プロジェクトに各OSのダイアログを呼び出すインターフェースを実装

public interface ICustomDisplayAlert {
    Task<bool> DisplayAlert(string title, string message,string cancel, string accept, FileImageSource file);
}

2.下記の記事にある手順の2〜3を行う

Xamrin.Forms アラートダイアログ(DisplayAlert)のボタンの文字色の変更方法
Xamrin.Forms アラートダイアログ(DisplayAlert)のボタンの文字色の変え方を説明します。1.共通プロジェクトに各OSのダイアログを呼び出すインターフェースを実装public interface ICu...

3.Androidプロジェクト内にダイアログを表示するクラスを追加

using Xamarin.Forms;
using System.Threading.Tasks;
using TestPrj;
using TestPrj.Droid;

[assembly: Dependency(typeof(CustomDisplayAlert))]
namespace TestPrj.Droid {
    public class CustomDisplayAlert : ICustomDisplayAlert {
        public CustomDisplayAlert() { }

        public Task<bool> DisplayAlert(string title, string message,string cancel, string accept, FileImageSource file) {
            var taskComplete = new TaskCompletionSource<bool>();
            var alert = new Android.Support.V7.App.AlertDialog.Builder(MainActivity.context, global::TestPrj.Droid.Resource.Style.CustomDialogStyle);
            alert.SetTitle(title);
            alert.SetMessage(message);

            var img = new Image();
            img.Source = file;
            var imageView = new ImageView(MainActivity.context);
            Device.BeginInvokeOnMainThread(async () => {
                var bitmap = await ImageSourceToBitmap(img.Source);
                imageView.SetImageBitmap(bitmap);

                LinearLayout linearLayout = new LinearLayout(MainActivity.context);
                linearLayout.Orientation = Orientation.Vertical;
                linearLayout.AddView(imageView);
                alert.SetView(linearLayout);

                if (!string.IsNullOrEmpty(accept)) {
                    alert.SetPositiveButton(accept, (sender, e) => {
                        taskComplete.SetResult(true);
                    });
                }
                if (!string.IsNullOrEmpty(cancel)) {
                    alert.SetNegativeButton(cancel, (sender, e) => {
                        taskComplete.SetResult(false);
                    });
                }
                alert.Create().Show();
            });
            return taskComplete.Task;
        }

        // ImageSourceをbitmapに変換
        async Task<Android.Graphics.Bitmap> ImageSourceToBitmap(ImageSource imageSource) {
          IImageSourceHandler handler;
          if (imageSource is UriImageSource)
            handler = new ImageLoaderSourceHandler();
          else if (imageSource is FileImageSource)
            handler = new FileImageSourceHandler();
          else if (imageSource is StreamImageSource)
            handler = new StreamImagesourceHandler();
          else
            return null;
          // 第二引数にはContextが必要。この例ではMainActivity.csにstaticな変数Contextを用意済み
          // ここのContextの取り方は好きなように実装してください
          return await handler.LoadImageAsync(imageSource, MainActivity.Context);
        }
    }
}

4.iOSプロジェクト内にダイアログを表示するクラスを追加

using Xamarin.Forms;
using System.Threading.Tasks;
using UIKit;
using TestPrj;
using TestPrj.iOS;
using Foundation;

[assembly: Dependency(typeof(CustomDisplayAlert))]
namespace TestPrj.iOS {
    public class CustomDisplayAlert : ICustomDisplayAlert {
        public Task<bool> DisplayAlert(string title, string message, string cancel, string accept, FileImageSource file) {
            var taskComplete = new TaskCompletionSource<bool>();
            UIApplication.SharedApplication.InvokeOnMainThread(() => {
                if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0)) {
                    var alertDialog = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);
                    UIView subView = null;
                    var imageRect = new RectangleF(0f, 0f, 64f, 64f);
                    var myImage = new UIImageView(imageRect);
                    myImage.Image = UIImage.FromFile(file);
                    myImage.Opaque = true;
                    // タイトル,メッセージが属するsubViewを取得 同階層に画像表示
                    subView = alertDialog.View.Subviews[0].Subviews[0].Subviews[0].Subviews[0];
                    subView.AddSubview(myImage);
                    nfloat temporaryImgX = 103;
                    subView.AddConstraint(
                        NSLayoutConstraint.Create(
                            subView,
                            NSLayoutAttribute.Height,
                            NSLayoutRelation.Equal,
                            null,
                            NSLayoutAttribute.NoAttribute,
                            1,
                            165
                        )
                    );
                    var imgY = 165 - 64 - 11;
                    //表示位置を変更
                    myImage.Frame = new CGRect(x: temporaryImgX, y: imgY, width: 64, height: 64);

                    alertDialog.AddAction(UIAlertAction.Create(accept, UIAlertActionStyle.Destructive, x => {
                        taskComplete.SetResult(true);
                    }));

                    alertDialog.AddAction(UIAlertAction.Create(cancel, UIAlertActionStyle.Cancel, x => {
                        taskComplete.SetResult(false);
                    }));

                    // ダイアログを表示
                    var ctl = GetViewController(UIApplication.SharedApplication.Windows);
                    if (ctl != null) {
                        ctl.PresentViewController(alertDialog, true, () => {
                            if (subView != null && subView.Subviews.Length > 1) {
                                nfloat dialogWidth = subView.Bounds.Width;
                                nfloat imgX = dialogWidth / 2 - subView.Subviews[1].Bounds.Width / 2;
                                // 表示位置を変更
                                if (temporaryImgX != imgX) {
                                    myImage.Frame = new CGRect(x: imgX, y: imgY, width: 64, height: 64);
                                }
                            }
                        });
                    }
                }
            });
            return taskComplete.Task;
        }

        UIViewController GetViewController() {
            var rootViewController = UIApplication.SharedApplication.KeyWindow.RootViewController;

            if (rootViewController.PresentedViewController == null)
                return rootViewController;

            if (rootViewController.PresentedViewController is UINavigationController)
                return ((UINavigationController)rootViewController.PresentedViewController).VisibleViewController;

            if (rootViewController.PresentedViewController is UITabBarController)
                return ((UITabBarController)rootViewController.PresentedViewController).SelectedViewController;

            return rootViewController.PresentedViewController;
        }
    }
}

5.呼び出して使う

await DependencyService.Get<ICustomDisplayAlert>().DisplayAlert("title", "message", "cancel", "OK", ImageFile) ;
タイトルとURLをコピーしました