Swift UIAlertController-将自定义视图添加到操作表
当我们试图像截图一样附加一张图片时,我正在尝试制作iOS上消息应用程序中显示的操作表 我意识到在新的UIAlertController中,我们不能适应任何自定义视图。我有没有办法做到这一点 我的代码看起来很标准Swift UIAlertController-将自定义视图添加到操作表,swift,ios9,uialertcontroller,Swift,Ios9,Uialertcontroller,当我们试图像截图一样附加一张图片时,我正在尝试制作iOS上消息应用程序中显示的操作表 我意识到在新的UIAlertController中,我们不能适应任何自定义视图。我有没有办法做到这一点 我的代码看起来很标准 let alertController = UIAlertController(title: "My AlertController", message: "tryna show some images here man", preferredStyle: UIAlertCont
let alertController = UIAlertController(title: "My AlertController", message: "tryna show some images here man", preferredStyle: UIAlertControllerStyle.ActionSheet)
let okAction = UIAlertAction(title: "oks", style: .Default) { (action: UIAlertAction) -> Void in
alertController.dismissViewControllerAnimated(true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Screw it!", style: .Cancel) { (action: UIAlertAction) -> Void in
alertController.dismissViewControllerAnimated(true, completion: nil)
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.presentViewController(alertController, animated: true, completion: nil)
UIAlertController扩展了UIViewController,它具有视图属性。您可以将子视图添加到该视图中,以满足您的需求。唯一的问题是正确调整警报控制器的大小。你可以这样做,但下一次苹果调整UIAlertController的设计时,这可能很容易被打破 Swift 3
let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
let margin:CGFloat = 10.0
let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120)
let customView = UIView(frame: rect)
customView.backgroundColor = .green
alertController.view.addSubview(customView)
let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")})
alertController.addAction(somethingAction)
alertController.addAction(cancelAction)
DispatchQueue.main.async {
self.present(alertController, animated: true, completion:{})
}
Swift
let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
let margin:CGFloat = 10.0
let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120)
let customView = UIView(frame: rect)
customView.backgroundColor = .green
alertController.view.addSubview(customView)
let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")})
alertController.addAction(somethingAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion:{})
目标-C
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"\n\n\n\n\n\n" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
CGFloat margin = 8.0F;
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(margin, margin, alertController.view.bounds.size.width - margin * 4.0F, 100.0F)];
customView.backgroundColor = [UIColor greenColor];
[alertController.view addSubview:customView];
UIAlertAction *somethingAction = [UIAlertAction actionWithTitle:@"Something" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {}];
[alertController addAction:somethingAction];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:^{}];
也就是说,一种不太老练的方法是创建自己的视图子类,该子类的工作方式类似于UIAlertController的UIAlertActionStyle布局。事实上,同样的代码在iOS 8和iOS 9中看起来略有不同
iOS 8
iOS 9
iOS 10
对于懒惰的人,Swift 3.0和iOS>=9是@Keller答案的优化版本:
let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
let margin:CGFloat = 10.0
let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120)
let customView = UIView(frame: rect)
customView.backgroundColor = .green
alertController.view.addSubview(customView)
let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")})
alertController.addAction(somethingAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion:{})
我为UIAlertController(在Swift 4中)编写了一个扩展,它使用autolayout解决了布局问题。甚至还有一个回退消息字符串,以防出现问题(由于UIAlertController布局的未来更改) 下面是一个使用示例:
// Create a custom view for testing...
let customView = UIView()
customView.translatesAutoresizingMaskIntoConstraints = false
customView.backgroundColor = .red
// Set the custom view to a fixed height. In a real world application, you could use autolayouted content for height constraints
customView.addConstraint(NSLayoutConstraint(item: customView,
attribute: .height,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 1,
constant: 100))
// Create the alert and show it
let alert = UIAlertController(title: "Alert Title",
customView: customView,
fallbackMessage: "This should be a red rectangle",
preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Yay!", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
这将显示如下内容:
我试图绕过
UIAlertController
的限制,但无论我如何管理,它都不够好。如果你还在为此挣扎,我已经创造了一个可能会有所帮助。它允许您使用一组内置类型创建自定义图纸。它还可以进行扩展和重新设置样式。到目前为止,我使用自动布局约束找到的最干净的解决方案:
func showPickerController() {
let alertController = UIAlertController(title: "Translation Language", message: nil, preferredStyle: .actionSheet)
let customView = UIView()
alertController.view.addSubview(customView)
customView.translatesAutoresizingMaskIntoConstraints = false
customView.topAnchor.constraint(equalTo: alertController.view.topAnchor, constant: 45).isActive = true
customView.rightAnchor.constraint(equalTo: alertController.view.rightAnchor, constant: -10).isActive = true
customView.leftAnchor.constraint(equalTo: alertController.view.leftAnchor, constant: 10).isActive = true
customView.heightAnchor.constraint(equalToConstant: 250).isActive = true
alertController.view.translatesAutoresizingMaskIntoConstraints = false
alertController.view.heightAnchor.constraint(equalToConstant: 430).isActive = true
customView.backgroundColor = .green
let selectAction = UIAlertAction(title: "Select", style: .default) { (action) in
print("selection")
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(selectAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
输出:
这是@Cesare解决方案的Objective-C版本
- (void) showPickerController {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"Translation Language" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIView *customView = [[UIView alloc] init];
[alertController.view addSubview:customView];
customView.translatesAutoresizingMaskIntoConstraints = NO;
[customView.topAnchor constraintEqualToAnchor:alertController.view.topAnchor constant:45].active = YES;
[customView.rightAnchor constraintEqualToAnchor:alertController.view.rightAnchor constant:-10].active = YES;
[customView.leftAnchor constraintEqualToAnchor:alertController.view.leftAnchor constant:10].active = YES;
[customView.heightAnchor constraintEqualToConstant:250].active = YES;
alertController.view.translatesAutoresizingMaskIntoConstraints = NO;
[alertController.view.heightAnchor constraintEqualToConstant:430].active = YES;
customView.backgroundColor = [UIColor greenColor];
UIAlertAction* selectAction = [UIAlertAction actionWithTitle:@"Select" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
}];
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
}];
[alertController addAction:selectAction];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];
}
这真是太棒了,真的很有帮助。我在页边空白处的绿色视图后面还有一条线。我想我会在绿色视图周围放置一个容器视图。0页边距。谢谢,伙计。这太棒了。刚对自定义视图的宽度进行了轻微调整,但一切都很好!干杯,这代码太卑鄙了。当字体大小在iOS设备上因设置不同而不同时,我们不应该使用字符间距!这就是为什么我在回答中提到“一种不那么粗糙的方法是创建自己的视图子类,该子类的工作方式类似于UIAlertController的UIAlertActionStyle布局。事实上,相同的代码在iOS 8和iOS 9中看起来略有不同。”问题是向UIAlertController添加子视图,我相信UIAlertController的初始帧大小与UIView相同。在iPhone上,上述代码工作正常,因为alertController占据了设备的整个宽度。在iPad上,alertController的大小已调整。要使子视图自动调整大小,请设置大小调整掩码customView.autoresizingMask=UIViewAutoresizingFlexibleWidth;这很有效。只是想知道这是否会在审查过程中被拒绝,知道吗?没有涉及到私有API,所以我不知道苹果为什么要拒绝它。只面临一个问题,
customView
以灰色而不是红色显示。有什么想法吗?这看起来是一个很好的、干净的解决方案,但我认为人们强烈建议不要扩展UIAlertController
,因为苹果不希望你这样做,而且可能会在将来的更新中打破你的“黑客”。这个解决方案可能也是这样吗?我试图尽可能优雅地处理任何失败。如果苹果公司有任何结构上的变化,最坏的结果应该是,警报只显示回退文本消息,而不是自定义视图,这正是该情况下API的一部分。这是最好的答案,而不是“选择”的答案。我很高兴有人正确地做到了这一点:-)关于该主题的最佳答案。想知道为什么这不是一个公认的答案。
- (void) showPickerController {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"Translation Language" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIView *customView = [[UIView alloc] init];
[alertController.view addSubview:customView];
customView.translatesAutoresizingMaskIntoConstraints = NO;
[customView.topAnchor constraintEqualToAnchor:alertController.view.topAnchor constant:45].active = YES;
[customView.rightAnchor constraintEqualToAnchor:alertController.view.rightAnchor constant:-10].active = YES;
[customView.leftAnchor constraintEqualToAnchor:alertController.view.leftAnchor constant:10].active = YES;
[customView.heightAnchor constraintEqualToConstant:250].active = YES;
alertController.view.translatesAutoresizingMaskIntoConstraints = NO;
[alertController.view.heightAnchor constraintEqualToConstant:430].active = YES;
customView.backgroundColor = [UIColor greenColor];
UIAlertAction* selectAction = [UIAlertAction actionWithTitle:@"Select" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
}];
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
}];
[alertController addAction:selectAction];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];
}