以编程方式切换 UIAlert Controller
Switch in UIAlert Controller programmatically
我正在 swift 中创建一个包含 3 个文本字段和一个开关的注册对话框,我成功地添加了三个文本字段和两个警报。以下代码显示相同。
let alertController = UIAlertController(title: "Register", message: "", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
// ...
exit(0)
}
alertController.addAction(cancelAction)
let OKAction = UIAlertAction(title: "Sign UP", style: .Default) { (action) in
// ...
let name0 = alertController.textFields![0] as UITextField
print("Text field: \(name0.text)")
let email1 = alertController.textFields![1] as UITextField
print("Text field: \(email1.text)")
let company2 = alertController.textFields![2] as UITextField
print("Text field: \(company2.text)")
}
alertController.addAction(OKAction)
alertController.addTextFieldWithConfigurationHandler { (textField) in
textField.placeholder = "Name"
textField.keyboardType = .EmailAddress
}
alertController.addTextFieldWithConfigurationHandler { (textField) in
textField.placeholder = "Email"
textField.secureTextEntry = false
}
alertController.addTextFieldWithConfigurationHandler { (textField) in
textField.placeholder = "Company"
textField.secureTextEntry = false
}
self.presentViewController(alertController, animated: true) {
// ...
}
现在我需要以编程方式向警报添加一个开关 View.We 正在 Swift2 中执行此操作。这可能吗?我是 Swift.
的新手
这可能对您有所帮助。
在上面的代码alertController.addAction(OKAction)
之后添加这个方法调用alertController.view.addSubview(createSwitch())
。
func createSwitch () -> UISwitch{
let switchControl = UISwitch(frame:CGRectMake(10, 20, 0, 0));
switchControl.on = true
switchControl.setOn(true, animated: false);
switchControl.addTarget(self, action: "switchValueDidChange:", forControlEvents: .ValueChanged);
return switchControl
}
func switchValueDidChange(sender:UISwitch!){
print("Switch Value : \(sender.on))")
}
输出:
您可以使用TextField 的RightView 添加按钮。添加一个开关会很好,但该开关不适合 TextField 高度,您也不能更改高度。为此,您可以添加一个按钮并使用图像制作一个 TickBox。
我已经从一个项目中删除了这个,所以示例图像比下面的多一点。
在ViewControllerheader中添加TextField Delegate
@interface CustomTableViewController : UITableViewController <UITextFieldDelegate>
然后创建您的 AlertController 并添加 TextField
// create an alert controller
UIAlertController *alertWithText = [UIAlertController alertControllerWithTitle:title message:body preferredStyle:UIAlertControllerStyleAlert];
// create the actions handled by each button
UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
}];
// add the actions to the alert
[alertWithText addAction:action1];
[alertWithText addAction:action2];
// Establish the weak self reference
__weak typeof(self) weakSelf = self;
[alertWithText addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
// Create button
UIButton *checkbox = [UIButton buttonWithType:UIButtonTypeCustom];
[checkbox setFrame:CGRectMake(2 , 2, 18, 18)]; // Not sure about size
[checkbox setTag:1];
[checkbox addTarget:weakSelf action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
// Setup image for button
[checkbox.imageView setContentMode:UIViewContentModeScaleAspectFit];
[checkbox setImage:[UIImage imageNamed:@"unchecked_checkbox.png"] forState:UIControlStateNormal];
[checkbox setImage:[UIImage imageNamed:@"checked_checkbox.png"] forState:UIControlStateSelected];
[checkbox setImage:[UIImage imageNamed:@"checked_checkbox.png"] forState:UIControlStateHighlighted];
[checkbox setAdjustsImageWhenHighlighted:TRUE];
// Setup the right view in the text field
[textField setClearButtonMode:UITextFieldViewModeAlways];
[textField setRightViewMode:UITextFieldViewModeAlways];
[textField setRightView:checkbox];
// Setup Tag so the textfield can be identified
[textField setTag:-1];
[textField setDelegate:weakSelf];
// Setup textfield
[textField setText:@"Essential"]; // Could be place holder text
}];
[self presentViewController:alertWithText animated:YES completion:nil];
如果您纯粹希望该行成为勾号,则需要停止编辑文本字段。
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if(textField.tag == -1){
return NO;
}
return YES;
}
以及您对按钮的操作
-(void)buttonPressed:(UIButton*)sender {
if(sender.selected){
[sender setSelected:FALSE];
} else {
[sender setSelected:TRUE];
}
}
这里还有一些勾选框图像(那里有很多,您甚至可以进行切换并尝试制作动画)。
此答案适用于 Objective C。它不使用文本字段,但确实按照主要问题中的要求将 UISwitch
添加到 UIAlertController
。我没有在 SO 上找到任何可以做到这一点的东西,所以我在这里发布这个答案,而不是发布另一个会被重复的问题。
此解决方案用于使用户能够对 UITableView
菜单(项目列表...)进行排序
感谢@technerd 的回答,我还UISwitch
更改了也在同一UIAlertController
视图中的UILabel
的文本。它在层中使用KVC(Key-Value编码)在UISwitch
值改变时将UILabel
id传递给目标动作。 (见代码中的setOrderLabelText
方法)
我还试图通过使用约束来绕过在标题或消息中添加换行符 ("\n\n\n\n") 以人为移动内容的技巧。
我用一个水平的UIStackView
来固定UISwitch
和它对应的UILabel
,然后使用约束来设置UIStack
的顶部锚点和一个高度UIAlertController
视图上的约束,使其足够大以包含 UIStackView
和 UIAlertController 标题。
我认为无法获得 UIAlertController
标题的高度或操作按钮的高度。所以我想出了在 iPhone X 和 iPad 2 上运行良好的值。与其他 SO 答案一样,我可能会想出一个自家种植的(或在 GitHub) 解决方案,使它更健壮。但是既然我已经走到这一步并且从其他很棒的 SO 答案中得到了很多,我想回馈一下并分享我的结果。
截图如下:
代码如下:
// using KVC, set the label text based on the label tag and toggle the tag
- (void)setOrderLabelText:(UISwitch *)orderSwitch {
UILabel *label = (UILabel *)[orderSwitch.layer valueForKey:@"label"];
label.text = label.tag ? @"Ascending" : @"Descending";
label.tag = label.tag ? 0 : 1;
}
// sort the data based on the user's selections
- (IBAction)sort:(UIButton *)sortButton {
UILabel *label = [[UILabel alloc] init];
label.text = @"Ascending";
label.textColor = UIColor.grayColor;
label.tag = 0;
[label sizeToFit];
UISwitch *orderSwitch = [[UISwitch alloc] init];
orderSwitch.on = YES;
[orderSwitch setOn:YES animated:YES];
// allow the switch to change the text in the label using KVC (key-value coding)
[orderSwitch addTarget:self action:@selector(setOrderLabelText:) forControlEvents:UIControlEventValueChanged];
[orderSwitch.layer setValue:label forKey:@"label"];
UIStackView *stackView = [[UIStackView alloc] init];
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.spacing = 8;
[stackView addArrangedSubview:orderSwitch];
[stackView addArrangedSubview:label];
UIAlertController *alert = [UIAlertController
alertControllerWithTitle: @"Sort Projects By"
message: nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *createdButton = [UIAlertAction
actionWithTitle:@"Created"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
[self sortBy:@"created" ascending:orderSwitch.isOn];
}];
UIAlertAction *titleButton = [UIAlertAction
actionWithTitle:@"Title"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
[self sortBy:@"title" ascending:orderSwitch.isOn];
}];
UIAlertAction *subtitleButton = [UIAlertAction
actionWithTitle:@"Subtitle"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
[self sortBy:@"subtitle" ascending:orderSwitch.isOn];
}];
UIAlertAction *cancelButton = [UIAlertAction
actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
}];
// add action buttons to the alert
[alert addAction:createdButton];
[alert addAction:titleButton];
[alert addAction:subtitleButton];
[alert addAction:cancelButton];
[alert.view addSubview:stackView];
// center the stack in the alert
[stackView.centerXAnchor constraintEqualToAnchor:alert.view.centerXAnchor].active = YES;
// turn off the autoresizing mask or things get weird
stackView.translatesAutoresizingMaskIntoConstraints = NO;
// use a topAnchor constraint to place the stackview, just below the title
// TODO: figure out how to get the height of the alert title (use 64 for now)
[stackView.topAnchor constraintEqualToAnchor:alert.view.topAnchor constant:64].active = YES;
// layout now to set the view bounds so far - NOTE this does not include the action buttons
[alert.view layoutIfNeeded];
// use a height constraint to make the alert view big enough to hold my stack view
// NOTE: strange, but this must include the header view AND all the action buttons
// TODO: figure out how to get the height of the action buttons (use 52 for each action button for now)
CGFloat height = alert.view.bounds.size.height + alert.actions.count * 52 + stackView.bounds.size.height;
[alert.view.heightAnchor constraintEqualToConstant:height].active = YES;
[self presentViewController:alert animated:YES completion:nil];
}
如果将上面的 Recycled Steel's 与 iOS 13 一起使用,则可以使用 SF 符号而不是 PNG。它将解决您可能遇到的任何缩放问题。
checkbox.imageView.tintColor = UIColor.blackColor;
if (@available(iOS 13.0, *)) {
[checkbox setImage: [UIImage systemImageNamed:@"square"] forState: UIControlStateNormal];
[checkbox setImage: [UIImage systemImageNamed:@"checkmark.square"] forState: UIControlStateHighlighted];
[checkbox setImage: [UIImage systemImageNamed:@"checkmark.square"] forState: UIControlStateSelected];
}
我正在 swift 中创建一个包含 3 个文本字段和一个开关的注册对话框,我成功地添加了三个文本字段和两个警报。以下代码显示相同。
let alertController = UIAlertController(title: "Register", message: "", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
// ...
exit(0)
}
alertController.addAction(cancelAction)
let OKAction = UIAlertAction(title: "Sign UP", style: .Default) { (action) in
// ...
let name0 = alertController.textFields![0] as UITextField
print("Text field: \(name0.text)")
let email1 = alertController.textFields![1] as UITextField
print("Text field: \(email1.text)")
let company2 = alertController.textFields![2] as UITextField
print("Text field: \(company2.text)")
}
alertController.addAction(OKAction)
alertController.addTextFieldWithConfigurationHandler { (textField) in
textField.placeholder = "Name"
textField.keyboardType = .EmailAddress
}
alertController.addTextFieldWithConfigurationHandler { (textField) in
textField.placeholder = "Email"
textField.secureTextEntry = false
}
alertController.addTextFieldWithConfigurationHandler { (textField) in
textField.placeholder = "Company"
textField.secureTextEntry = false
}
self.presentViewController(alertController, animated: true) {
// ...
}
现在我需要以编程方式向警报添加一个开关 View.We 正在 Swift2 中执行此操作。这可能吗?我是 Swift.
的新手这可能对您有所帮助。
在上面的代码alertController.addAction(OKAction)
之后添加这个方法调用alertController.view.addSubview(createSwitch())
。
func createSwitch () -> UISwitch{
let switchControl = UISwitch(frame:CGRectMake(10, 20, 0, 0));
switchControl.on = true
switchControl.setOn(true, animated: false);
switchControl.addTarget(self, action: "switchValueDidChange:", forControlEvents: .ValueChanged);
return switchControl
}
func switchValueDidChange(sender:UISwitch!){
print("Switch Value : \(sender.on))")
}
输出:
您可以使用TextField 的RightView 添加按钮。添加一个开关会很好,但该开关不适合 TextField 高度,您也不能更改高度。为此,您可以添加一个按钮并使用图像制作一个 TickBox。
我已经从一个项目中删除了这个,所以示例图像比下面的多一点。
在ViewControllerheader中添加TextField Delegate
@interface CustomTableViewController : UITableViewController <UITextFieldDelegate>
然后创建您的 AlertController 并添加 TextField
// create an alert controller
UIAlertController *alertWithText = [UIAlertController alertControllerWithTitle:title message:body preferredStyle:UIAlertControllerStyleAlert];
// create the actions handled by each button
UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
}];
// add the actions to the alert
[alertWithText addAction:action1];
[alertWithText addAction:action2];
// Establish the weak self reference
__weak typeof(self) weakSelf = self;
[alertWithText addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
// Create button
UIButton *checkbox = [UIButton buttonWithType:UIButtonTypeCustom];
[checkbox setFrame:CGRectMake(2 , 2, 18, 18)]; // Not sure about size
[checkbox setTag:1];
[checkbox addTarget:weakSelf action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
// Setup image for button
[checkbox.imageView setContentMode:UIViewContentModeScaleAspectFit];
[checkbox setImage:[UIImage imageNamed:@"unchecked_checkbox.png"] forState:UIControlStateNormal];
[checkbox setImage:[UIImage imageNamed:@"checked_checkbox.png"] forState:UIControlStateSelected];
[checkbox setImage:[UIImage imageNamed:@"checked_checkbox.png"] forState:UIControlStateHighlighted];
[checkbox setAdjustsImageWhenHighlighted:TRUE];
// Setup the right view in the text field
[textField setClearButtonMode:UITextFieldViewModeAlways];
[textField setRightViewMode:UITextFieldViewModeAlways];
[textField setRightView:checkbox];
// Setup Tag so the textfield can be identified
[textField setTag:-1];
[textField setDelegate:weakSelf];
// Setup textfield
[textField setText:@"Essential"]; // Could be place holder text
}];
[self presentViewController:alertWithText animated:YES completion:nil];
如果您纯粹希望该行成为勾号,则需要停止编辑文本字段。
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if(textField.tag == -1){
return NO;
}
return YES;
}
以及您对按钮的操作
-(void)buttonPressed:(UIButton*)sender {
if(sender.selected){
[sender setSelected:FALSE];
} else {
[sender setSelected:TRUE];
}
}
这里还有一些勾选框图像(那里有很多,您甚至可以进行切换并尝试制作动画)。
此答案适用于 Objective C。它不使用文本字段,但确实按照主要问题中的要求将 UISwitch
添加到 UIAlertController
。我没有在 SO 上找到任何可以做到这一点的东西,所以我在这里发布这个答案,而不是发布另一个会被重复的问题。
此解决方案用于使用户能够对 UITableView
菜单(项目列表...)进行排序
感谢@technerd 的回答,我还UISwitch
更改了也在同一UIAlertController
视图中的UILabel
的文本。它在层中使用KVC(Key-Value编码)在UISwitch
值改变时将UILabel
id传递给目标动作。 (见代码中的setOrderLabelText
方法)
我还试图通过使用约束来绕过在标题或消息中添加换行符 ("\n\n\n\n") 以人为移动内容的技巧。
我用一个水平的UIStackView
来固定UISwitch
和它对应的UILabel
,然后使用约束来设置UIStack
的顶部锚点和一个高度UIAlertController
视图上的约束,使其足够大以包含 UIStackView
和 UIAlertController 标题。
我认为无法获得 UIAlertController
标题的高度或操作按钮的高度。所以我想出了在 iPhone X 和 iPad 2 上运行良好的值。与其他 SO 答案一样,我可能会想出一个自家种植的(或在 GitHub) 解决方案,使它更健壮。但是既然我已经走到这一步并且从其他很棒的 SO 答案中得到了很多,我想回馈一下并分享我的结果。
截图如下:
代码如下:
// using KVC, set the label text based on the label tag and toggle the tag
- (void)setOrderLabelText:(UISwitch *)orderSwitch {
UILabel *label = (UILabel *)[orderSwitch.layer valueForKey:@"label"];
label.text = label.tag ? @"Ascending" : @"Descending";
label.tag = label.tag ? 0 : 1;
}
// sort the data based on the user's selections
- (IBAction)sort:(UIButton *)sortButton {
UILabel *label = [[UILabel alloc] init];
label.text = @"Ascending";
label.textColor = UIColor.grayColor;
label.tag = 0;
[label sizeToFit];
UISwitch *orderSwitch = [[UISwitch alloc] init];
orderSwitch.on = YES;
[orderSwitch setOn:YES animated:YES];
// allow the switch to change the text in the label using KVC (key-value coding)
[orderSwitch addTarget:self action:@selector(setOrderLabelText:) forControlEvents:UIControlEventValueChanged];
[orderSwitch.layer setValue:label forKey:@"label"];
UIStackView *stackView = [[UIStackView alloc] init];
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.spacing = 8;
[stackView addArrangedSubview:orderSwitch];
[stackView addArrangedSubview:label];
UIAlertController *alert = [UIAlertController
alertControllerWithTitle: @"Sort Projects By"
message: nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *createdButton = [UIAlertAction
actionWithTitle:@"Created"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
[self sortBy:@"created" ascending:orderSwitch.isOn];
}];
UIAlertAction *titleButton = [UIAlertAction
actionWithTitle:@"Title"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
[self sortBy:@"title" ascending:orderSwitch.isOn];
}];
UIAlertAction *subtitleButton = [UIAlertAction
actionWithTitle:@"Subtitle"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
[self sortBy:@"subtitle" ascending:orderSwitch.isOn];
}];
UIAlertAction *cancelButton = [UIAlertAction
actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
}];
// add action buttons to the alert
[alert addAction:createdButton];
[alert addAction:titleButton];
[alert addAction:subtitleButton];
[alert addAction:cancelButton];
[alert.view addSubview:stackView];
// center the stack in the alert
[stackView.centerXAnchor constraintEqualToAnchor:alert.view.centerXAnchor].active = YES;
// turn off the autoresizing mask or things get weird
stackView.translatesAutoresizingMaskIntoConstraints = NO;
// use a topAnchor constraint to place the stackview, just below the title
// TODO: figure out how to get the height of the alert title (use 64 for now)
[stackView.topAnchor constraintEqualToAnchor:alert.view.topAnchor constant:64].active = YES;
// layout now to set the view bounds so far - NOTE this does not include the action buttons
[alert.view layoutIfNeeded];
// use a height constraint to make the alert view big enough to hold my stack view
// NOTE: strange, but this must include the header view AND all the action buttons
// TODO: figure out how to get the height of the action buttons (use 52 for each action button for now)
CGFloat height = alert.view.bounds.size.height + alert.actions.count * 52 + stackView.bounds.size.height;
[alert.view.heightAnchor constraintEqualToConstant:height].active = YES;
[self presentViewController:alert animated:YES completion:nil];
}
如果将上面的 Recycled Steel's
checkbox.imageView.tintColor = UIColor.blackColor;
if (@available(iOS 13.0, *)) {
[checkbox setImage: [UIImage systemImageNamed:@"square"] forState: UIControlStateNormal];
[checkbox setImage: [UIImage systemImageNamed:@"checkmark.square"] forState: UIControlStateHighlighted];
[checkbox setImage: [UIImage systemImageNamed:@"checkmark.square"] forState: UIControlStateSelected];
}