UIAlertController 和 UIAlertControllerStyleActionSheet 自定义

Posted

技术标签:

【中文标题】UIAlertController 和 UIAlertControllerStyleActionSheet 自定义【英文标题】:UIAlertController and UIAlertControllerStyleActionSheet customization 【发布时间】:2016-11-18 11:20:02 【问题描述】:

我正在尝试使用样式 UIAlertControllerStyleActionSheet(以前的 UIActionSheet)创建自定义 UIAlertController,但我遇到了很多麻烦来简单地自定义它。我希望我的 UIAlertAction 在左侧包含一个图像减小按钮大小

我知道这是可行的:

(这正是我想要的)

我搜索了几个小时,但在互联网上找不到任何可以帮助我完成这项简单任务的 tut。另外,由于 UIActionSheet 自 ios 9 以来已被弃用,因此无论何时我尝试找到一个解决方案,它都不再可用。另外,我读到 UIAlertController 不打算被子类化......

有谁知道如何实现我的警报的轻量级自定义? 我是否必须继承 UIView 才能制作自己的警报表?

【问题讨论】:

【参考方案1】:

此解决方案确实使用私有 API/属性。根据我的研究和经验,这是我知道您可以自定义 UIAlertController 的唯一方法。如果您查看公共标头,UIAlertContoller 几乎没有自定义空间。不过,在 iOS 8 推出 UIAlertController 后,这个方案在开发者中普遍使用。你完全可以依赖 Github 的依赖。希望我的回答能解决你的问题。 我相信这就是您正在寻找的结果,结果如下所示:

首先,您必须创建一个UIAlertController

UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Alert Title" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];

自定义字体!即使只是某些字符。

NSMutableAttributedString *hogan = [[NSMutableAttributedString alloc] initWithString:@"Presenting the great... ***!"];
[hogan addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:30.0] range:NSMakeRange(24, 11)];
[alertVC setValue:hogan forKey:@"attributedTitle"];

现在,让我们创建一个 UIAlertAction,您可以在其中添加操作处理程序并添加图标。

UIAlertAction *button = [UIAlertAction actionWithTitle:@"First Button"
                                                 style:UIAlertActionStyleDefault
                                               handler:^(UIAlertAction *action)
                                                   //add code to make something happen once tapped
                                               ];
UIAlertAction *button2 = [UIAlertAction actionWithTitle:@"Second Button"
                                                 style:UIAlertActionStyleDefault
                                               handler:^(UIAlertAction *action)
                                                   //add code to make something happen once tapped
                                               ];

在这里,您将图标添加到 AlertAction。对我来说,你必须指定UIImageRenderingModeAlwaysOriginal

[button setValue:[[UIImage imageNamed:@"image.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forKey:@"image"];

[alertVC addAction:button2];
[alertVC addAction:button];

记得展示 ViewController

[self presentViewController:alertVC animated:YES completion:nil];

【讨论】:

此方法不允许我调整按钮高度。 UIAlert 占据了整个屏幕,真的很侵入! 您的按钮高度由图标和字体的大小决定。否则它是默认大小。 此解决方案利用了未记录的私有功能,这些功能可能会在未来的 iOS 更新中中断(崩溃或无法工作)。最好避免使用此类代码。 UIAlertControllerUIActionSheet 都不通过公共 API 支持此功能。因此,您应该找到一个自定义解决方案。 编辑:根据您的帖子,我设法将图片添加到按钮,但更改标题的字体大小不会使标题框变小。 (顺便说一句,我不需要任何标题,但我试图看看它是否会传播到按钮大小)。另外我注意到大图像实际上增加了按钮的高度,但小图像并没有减少它。我认为是按钮标签的字体决定了这个最小高度。有没有办法改变按钮标签字体?我开始认真考虑使用自定义 UIView 和 UIButtons 来模仿 UIAlertController,我走对了吗?【参考方案2】:

对于那些可能对我如何克服这个问题感兴趣的人,我发布了我的解决方案:

我终于放弃了 UIAlertController,它并不打算被子类化。相反,在我的 ViewController 中,我创建了一个以编程方式重新创建相同效果和渲染的方法:

    创建一个占据整个屏幕的 UIView,并将其 alpha 设置为 ~0.7。 (这有两个目标,一个是美学目标,一个是物理目标,即隐藏当前视图,避免点击自定义警报后面的按钮)

    创建 UIButtons 并将其手动放置在当前视图中。

    将此 foregroundView 和按钮添加到当前视图,单击按钮时只需将其删除。

示例代码:

-(void) displayAlertChoice

    // create foreground layer to hide current view
    foregroundLayer = [[UIView alloc] initWithFrame:CGRectMake(0,0,screenWidth,screenHeight)];
    foregroundLayer.backgroundColor = [UIColor blackColor];
    foregroundLayer.alpha = 0.0;
    [self.view addSubview:foregroundLayer];
    [UIView animateWithDuration:0.2 animations:^foregroundLayer.alpha = 0.7;]; // animation de son apparition (alpha)

    // Hide foreground layer when clicked
    UITapGestureRecognizer *tapForegroundLayer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickForegroundLayer:)];
    [foregroundLayer addGestureRecognizer:tapForegroundLayer];


    // CancelButton
    cancelButton= [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [cancelButton setFrame:CGRectMake(marginWidth,
                                      2*screenHeight - buttonHeight - marginHeight, // OFF SCREEN
                                      buttonWidth,
                                      buttonHeight)];
    [cancelButton setTitle:@"Annuler" forState:UIControlStateNormal];
    [cancelButton addTarget:self action:@selector(alertCancelButton:) forControlEvents:UIControlEventTouchUpInside];
    [cancelButton setBackgroundColor:[UIColor whiteColor]];
    cancelButton.layer.cornerRadius = 8;
    [self.view addSubview:cancelButton];
    [UIView animateWithDuration:0.2 animations:^ // animation de son apparition (fram up)
        [cancelButton setFrame:CGRectMake(marginWidth,
                                          screenHeight - buttonHeight - marginHeight, // ON SCREEN
                                          buttonWidth,
                                          buttonHeight)];
    ];

这段代码比仅仅添加视图和按钮要复杂一些,以便在警报出现时重新创建动画:

使用 [UIView animateWithDuration: animations:^]; 我能够逐渐模糊前景视图并使取消按钮从屏幕底部显示。 注意:不能将 UIButtons 直接添加到 foregroundView(这里称为 foregroundLayer),否则它们将继承我们之前设置的 0.7 alpha 我向foregroundView 添加了一个手势识别器选择器,它具有与cancelButton 选择器相同的效果:它从superview 中删除所有创建的对象。这样,当用户在列表边缘之外单击时,它会关闭自定义 AlertView。

【讨论】:

以上是关于UIAlertController 和 UIAlertControllerStyleActionSheet 自定义的主要内容,如果未能解决你的问题,请参考以下文章

UIAlertController 和 UIAlertControllerStyleActionSheet 自定义

如何同时关闭 UIAlertController 和键盘?

iOS UIAlertController

UIAlertController 和 UIViewAlertForUnsatisfiableConstraints 错误

如何获取 UIAlertController 的框架宽度?

禁止UIAlertController的dimiss