Добавление UIImageView в UIAlertController - PullRequest
0 голосов
/ 21 февраля 2019

Цель: добавить изображение над UIAlertController's меткой заголовка, создав подкласс UIAlertController и добавив символы новой строки \n в строку заголовка, чтобы освободить место для UIImageView

Желание goal image Текущий current image

Как можно видеть, можно успешно добавить изображение в UIAlertController, но изображение не находится на расстоянии или расположено вышеНазвание.Похоже, что добавление в центр оповещения.Как правильно разместить изображение над заголовком UIAlertController?

Текущий код:

namespace XamarinFormsApp1.Extensions
{
    public class AlertController : UIAlertController
    {
        private string originalTitle;
        private string spaceAdjustedTitle;
        private UIImageView imageView = null;
        private CoreGraphics.CGSize previousImgViewSize 
            = CoreGraphics.CGSize.Empty;
        public override UIAlertControllerStyle PreferredStyle
        {
            get
            {
                return UIAlertControllerStyle.Alert;
            }
        }

    public override string Title
    {
        get
        {
            return originalTitle;
        }
        set
        {
            if (Title != spaceAdjustedTitle ||
                string.IsNullOrEmpty(Title) || 
                string.IsNullOrEmpty(spaceAdjustedTitle))
            {
                originalTitle = value;
            }
        }
    }

    public void setTitleImage(UIImage image)
    {
        if (this.imageView == null)
        {
            UIImageView imageView = new UIImageView(image);
            this.View.AddSubview(imageView);
            this.imageView = imageView;
            return;
        }
        imageView.Image = image;
    }

    public override void ViewDidLayoutSubviews()
    {
        if (imageView == null)
        {
            base.ViewDidLayoutSubviews();
            return;
        }
        //  Adjust title if image size has changed
        if (previousImgViewSize != imageView.Bounds.Size)
        {
            previousImgViewSize = imageView.Bounds.Size;
            adjustTitle(imageView);
        }
        //  Position `imageView`
        var linesCount = newLinesCount(imageView);
        var padding = Constants.Padding(PreferredStyle);
        var x = View.Bounds.Width / 2.0;
        var y = padding + linesCount * lineHeight / 2.0;
        CoreGraphics.CGPoint cgPoint = imageView.Center;
        cgPoint.X = (nfloat)x;
        cgPoint.Y = (nfloat)y;
        imageView.Center = cgPoint;
        base.ViewDidLayoutSubviews();
    }

    private void adjustTitle(UIImageView imageView)
    {
        var linesCount = (int)newLinesCount(imageView);
        var lines = Enumerable
            .Range(1, linesCount)
            .Select(i => "\n")
            .Aggregate((c, n) => $"{c}{n}");
        spaceAdjustedTitle = lines + (originalTitle ?? "");
        Title = spaceAdjustedTitle;
    }

    private double newLinesCount(UIImageView imageView)
    {
        return Math.Ceiling(
            imageView.Bounds.Height / lineHeight);
    }

    private float lineHeight
    {
        get
        {
            UIFontTextStyle style = this.PreferredStyle
                == UIAlertControllerStyle.Alert 
                ? UIFontTextStyle.Headline 
                : UIFontTextStyle.Callout;
            return (float)UIFont
                .GetPreferredFontForTextStyle(style)
                .PointSize;
        }
    }

    struct Constants
    {
        static float paddingAlert = 22;
        static float paddingSheet = 11;
        public static float Padding(UIAlertControllerStyle style)
        {
            return style == UIAlertControllerStyle.Alert 
                ? Constants.paddingAlert 
                : Constants.paddingSheet;
        }
    }
}
}

Примечание: кредит @stringCode для изображения и swift решения, см. .

1 Ответ

0 голосов
/ 22 февраля 2019

UIAlertViewController не предназначен для создания подклассов.

В выдержке из документации написано:

enter image description here

Вы все еще можете получить желаемый пользовательский интерфейс, используя UIViewController с прозрачностью в представлении и подпредставлением с желаемым макетом.

Вам также необходимо установить эти два свойства: ModalTransitionStyle и ModalPresentationStyle на UIModalTransitionStyle.CrossDissolve и UIModalPresentationStyle.OverCurrentContext соответственно, если вы хотите свой пользовательский UIAlertController соответственноведет себя так же, как UIAlertController

Обновление:

Это то, что я имел в виду, что вы могли бы сделать:

В выпадении Main.Storyboard UIViewController и обновите дизайн по своему желанию.Следуя изображению, которое вы разместили выше, я создал пользовательский интерфейс, как показано ниже:

enter image description here

Это изображение, 2 UILabels для Заголовок и Сообщение и 3 кнопки для 3 различных действий (По умолчанию, Уничтожить, Отмена).Все эти элементы управления находятся внутри UIView с белым фоном.Для примера, который я назвал, это ContentView

Добавление кнопки 3 в пользовательском интерфейсе, кажется, самый простой способ работать с этим, а затем скрыть / показать их, когда вы собираетесь представить свое предупреждение,Вы также можете создавать кнопки на лету, основываясь на действиях, которые вы хотите показать.Это зависит от вас.

Создайте класс ViewController, я назвал его NiceAlertController и назначьте его ViewController в раскадровке.Кроме того, убедитесь, что вы создали обратные свойства (Outlets) для всех UIControls (Label, Button, Image и т. Д.), Чтобы вы могли получить к ним доступ из класса ViewController.

Здесь дополнительная информация окак работать с iOS Storyboard на конструкторе

Теперь в вашем классе вам нужно будет добавить код, чтобы он работал.

В вашем классе, чтобы сделать представление прозрачным, вам нужно будет добавитьэто к вашему методу ViewDidLoad:

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    this.View.BackgroundColor = UIColor.Clear.ColorWithAlpha(0.2f);
    this.View.Opaque = false;
}

Кроме того, мы могли бы имитировать способ создания UIAlertControllers и создать наш метод, подобный этому:

public static NiceAlertController Create(string title, string message, UIImage image = null)
{
    //New instance of your ViewController UI
    var storyboard = UIStoryboard.FromName("Main", NSBundle.MainBundle);
    var alertController = storyboard.InstantiateViewController(nameof(NiceAlertController)) as NiceAlertController;

    //Using the same transition and presentation style as the UIAlertViewController
    alertController.ModalTransitionStyle = UIModalTransitionStyle.CrossDissolve;
    alertController.ModalPresentationStyle = UIModalPresentationStyle.OverCurrentContext;

    //This assumes your properties are called Title, Message and Image 
    alertController.Title = title;
    alertController.Message = message;
    alertController.Image = image;

    return alertController;
}

3 свойства, использованные выше (Title,Сообщение и изображение) выглядит следующим образом:

public new string Title { get; private set; }

public string Message { get; private set; }

public UIImage Image { get; private set; }

Почему эти свойства?потому что к моменту создания класса элементы управления в представлении еще не доступны.Они будут доступны только после загрузки представления.Вот почему нам нужно будет добавить другие изменения, как показано ниже.

Здесь мы устанавливаем значения для элементов управления в пользовательском интерфейсе

public override void ViewWillAppear(bool animated)
{
    base.ViewWillAppear(animated);

    this.titleLabel.Text = Title;
    this.messageLabel.Text = Message;

    //If you don't set an image while Create, it will use the default image you set on the Designer.
    if (Image != null)
    {
        this.imageView.Image = Image;
    }
}    

Теперь из любого другого ViewController вы можете вызватьэтот ViewController, как если бы вы вызывали AlertViewController:

private void ShowMyAlertController()
{
    var alert = NiceAlertController.Create("Hello", "My nice alert controller");
    this.PresentViewController(alert, true, null);
}

И он должен выглядеть следующим образом:

enter image description here

для обработки действий(Что делать, когда кнопки нажимаются) вы можете создать специальные методы, такие как:

public void AddDefaultAction(string title, Action action)
{
    //Logic here
}

public void AddCancelAction(string title, Action action)
{
    //Logic here
}

public void AddDestructiveAction(string title, Action action)
{
    //Logic here
}

Надеюсь, что это дает вам представление о том, как создать пользовательский UIViewcontroller и сделать его похожим на UIAlertViewController.

Надеюсь, это поможет .-

...