将 UIImageView 添加到 UIAlertController
Adding UIImageView to UIAlertController
目标:通过子类化 UIAlertController
并向标题字符串添加新行字符 \n
,在 UIAlertController's
标题标签上方添加图像,使 space UIImageView
渴望
当前的
如您所见,能够成功将图像添加到 UIAlertController
,但图像未在标题上方 spacing/placed。它似乎正在添加到警报的中心。如何 space 图像正确地位于 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;
}
}
}
}
注意:图像和 swift
解决方案归功于@stringCode,。
UIAlertViewController 不应该被子class编辑。
documentation 的摘录说:
您仍然可以通过在视图上使用具有透明度的 UIViewController
和具有您想要的布局的子视图来获得您想要的 UI。
您还需要将这两个属性:ModalTransitionStyle
和 ModalPresentationStyle
设置为 UIModalTransitionStyle.CrossDissolve 和 UIModalPresentationStyle.OverCurrentContext 如果您希望自定义 UIAlertController 的行为与 UIAlertController
相同
更新:
这就是我的意思,你可以这样做:
在 Main.Storyboard 中放置一个 UIViewController 并根据需要更新设计。根据您在上面发布的图片,我创建了 UI,如下所示:
这是一张图片,标题和消息有2个UI标签,3个不同的操作有3个按钮(默认、销毁、取消)。所有这些控件都位于 UI 具有白色背景的视图中。对于我称之为 ContentView
的示例
在 UI 上添加 3 按钮似乎是使用此按钮的最简单方法,然后在您要显示警报时 hide/show 添加按钮。您还可以根据要显示的操作即时创建按钮。这由你决定。
创建一个ViewControllerClass,我将其命名为NiceAlertController,并将其赋值给Storyboard中的ViewController。此外,确保为所有 UI 控件(标签、按钮、图像等)创建后台属性(Outlets),以便您可以从 ViewController class.
Here 有关如何使用设计器上的 iOS 故事板的更多信息
现在,在您的 class 中,您需要添加代码以使其正常工作。
在您的 class 中,要使视图透明,您需要将其添加到您的 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 个属性(标题、消息和图像)如下所示:
public new string Title { get; private set; }
public string Message { get; private set; }
public UIImage Image { get; private set; }
为什么有这些属性?因为在您创建 class 时,视图上的控件尚不可用。它们只有在加载视图后才可用。这就是为什么我们需要添加其他更改,如下所示。
此处我们将值设置为 UI
上的控件
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:
private void ShowMyAlertController()
{
var alert = NiceAlertController.Create("Hello", "My nice alert controller");
this.PresentViewController(alert, true, null);
}
它应该是这样的:
要处理操作(点击按钮时执行的操作),您可以创建特定的方法,例如:
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.
希望这对您有所帮助。-
目标:通过子类化 UIAlertController
并向标题字符串添加新行字符 \n
,在 UIAlertController's
标题标签上方添加图像,使 space UIImageView
渴望
如您所见,能够成功将图像添加到 UIAlertController
,但图像未在标题上方 spacing/placed。它似乎正在添加到警报的中心。如何 space 图像正确地位于 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;
}
}
}
}
注意:图像和 swift
解决方案归功于@stringCode,
UIAlertViewController 不应该被子class编辑。
documentation 的摘录说:
您仍然可以通过在视图上使用具有透明度的 UIViewController
和具有您想要的布局的子视图来获得您想要的 UI。
您还需要将这两个属性:ModalTransitionStyle
和 ModalPresentationStyle
设置为 UIModalTransitionStyle.CrossDissolve 和 UIModalPresentationStyle.OverCurrentContext 如果您希望自定义 UIAlertController 的行为与 UIAlertController
更新:
这就是我的意思,你可以这样做:
在 Main.Storyboard 中放置一个 UIViewController 并根据需要更新设计。根据您在上面发布的图片,我创建了 UI,如下所示:
这是一张图片,标题和消息有2个UI标签,3个不同的操作有3个按钮(默认、销毁、取消)。所有这些控件都位于 UI 具有白色背景的视图中。对于我称之为 ContentView
的示例在 UI 上添加 3 按钮似乎是使用此按钮的最简单方法,然后在您要显示警报时 hide/show 添加按钮。您还可以根据要显示的操作即时创建按钮。这由你决定。
创建一个ViewControllerClass,我将其命名为NiceAlertController,并将其赋值给Storyboard中的ViewController。此外,确保为所有 UI 控件(标签、按钮、图像等)创建后台属性(Outlets),以便您可以从 ViewController class.
Here 有关如何使用设计器上的 iOS 故事板的更多信息
现在,在您的 class 中,您需要添加代码以使其正常工作。
在您的 class 中,要使视图透明,您需要将其添加到您的 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 个属性(标题、消息和图像)如下所示:
public new string Title { get; private set; }
public string Message { get; private set; }
public UIImage Image { get; private set; }
为什么有这些属性?因为在您创建 class 时,视图上的控件尚不可用。它们只有在加载视图后才可用。这就是为什么我们需要添加其他更改,如下所示。
此处我们将值设置为 UI
上的控件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:
private void ShowMyAlertController()
{
var alert = NiceAlertController.Create("Hello", "My nice alert controller");
this.PresentViewController(alert, true, null);
}
它应该是这样的:
要处理操作(点击按钮时执行的操作),您可以创建特定的方法,例如:
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.
希望这对您有所帮助。-