I am creating an registration dialog in swift with 3 text field and one Switch and I successfully add three text field two the Alert. The following code shows the same.
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) {
// ...
}
Now I need to add a switch programmatically to the Alert View.We are doing this in Swift2. Is it possible?, i am new to Swift.
This may help you.
Add this method call alertController.view.addSubview(createSwitch()) in above code after alertController.addAction(OKAction).
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))")
}
OutPut :
You can use the RightView of the TextField to add a button. Adding a switch would be nice but the switch does not fit into the TextField height nor can you change the height. To this end you can add a button and use images to make a TickBox.
I have ripped this out of a project so the example image is a little more than below.
In the ViewController header add the TextField Delegate
#interface CustomTableViewController : UITableViewController <UITextFieldDelegate>
Then create your AlertController and add the 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];
You need to stop the textfield from editing if you purely want that line to be a tick.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if(textField.tag == -1){
return NO;
}
return YES;
}
And your action for your button
-(void)buttonPressed:(UIButton*)sender {
if(sender.selected){
[sender setSelected:FALSE];
} else {
[sender setSelected:TRUE];
}
}
Here are some tick box images too (there are plenty out there, you could even make a switch and try and animate).
This answer is for Objective C. It doesn't use text fields but it does add a UISwitch to a UIAlertController as asked in the main question. I didn't find anything on SO that does exactly this so I'm posting this answer here, rather than posting another question that will get dinged as a duplicate.
This solution is used to enable users to sort a UITableView menu (of a list of projects...)
Thanks to the answer by #technerd, I also made the UISwitch change the text of a UILabel that is also on the same UIAlertController view. It uses KVC (Key-Value Coding) in the layer to pass the UILabel id to the target action when the UISwitch value is changed. (See the setOrderLabelText method in the code)
I was also trying to get around the trick of adding newlines ("\n\n\n\n") to the title or message to artificially move things around, by using constraints.
I used a horizontal UIStackView to hold the UISwitch and it's corresponding UILabel, and then used constraints to set the top anchor of the UIStack and a height constraint on the UIAlertController view to make it big enough to contain the UIStackView and the UIAlertController title.
I don't think it is possible to get the height of the title of the UIAlertController or the height of the action buttons. So I came up with values that worked well on an iPhone X and an iPad 2. As in other SO answers, I will likely come up with a home grown (or find one on GitHub) solution to make this more robust. But since I got this far and got so much from other awesome SO answers, I wanted to give back a bit and share my results.
Here's a screenshot:
And here's the code:
// 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];
}
If you use Recycled Steel's answer above with iOS 13 you can use SF Symbols instead of PNGs. It will solve any scaling issues you might have.
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];
}
Related
I have stored 5 images in an NSMutableArray named as _dict in the code.
In .h file:
#property(weak,nonatomic)IBOutlet UIButton *b1;
#property(weak,nonatomic)IBOutlet UIButton *b2;
#property(weak,nonatomic)IBOutlet UIButton *b3;
#property(weak,nonatomic)IBOutlet UIButton *b4;
#property(weak,nonatomic)IBOutlet UIButton *b5;
#property(weak,nonatomic)IBOutlet UIButton *b6;
#property(weak,nonatomic)IBOutlet UIButton *b7;
#property(weak,nonatomic)IBOutlet UIButton *b8;
#property(weak,nonatomic)IBOutlet UIButton *b9;
In.m file
dict=[[NSMutableArray alloc]init];
dict= _array;
NSLog(#"%#",dict);
colorimage = [dict objectAtIndex:0];
[_b1 setBackgroundImage:colorimage forState:UIControlStateNormal];
colorimage1 = [dict objectAtIndex:1];
[_b2 setBackgroundImage:colorimage1 forState:UIControlStateNormal];
colorimage2 = [dict objectAtIndex:2];
[_b3 setBackgroundImage:colorimage2 forState:UIControlStateNormal];
colorimage3 = [dict objectAtIndex:3];
[_b4 setBackgroundImage:colorimage3 forState:UIControlStateNormal];
colorimage4 = [dict objectAtIndex:4];
[_b5 setBackgroundImage:colorimage4 forState:UIControlStateNormal];
int j=0;
img=[[NSMutableArray alloc]init];
}
-(IBAction)button1:(id)sender{
k++;
[img addObject:colorimage];
[sender setBackgroundImage:[UIImage imageNamed:#"apple.png"] forState:UIControlStateNormal];
[self check];
}
-(IBAction)button2:(id)sender{
k++;
[img addObject:colorimage1];
[sender setBackgroundImage:[UIImage imageNamed:#"apple.png"] forState:UIControlStateNormal];
[self check];
}
-(IBAction)button3:(id)sender
{
k++;
[img addObject:colorimage2];
[sender setBackgroundImage:[UIImage imageNamed:#"apple.png"] forState:UIControlStateNormal];
[self check];}
-(IBAction)button4:(id)sender
{
k++;
[img addObject:colorimage3];
[sender setBackgroundImage:[UIImage imageNamed:#"apple.png"] forState:UIControlStateNormal];
[self check];
}
-(IBAction)button5:(id)sender
{
k++;
[img addObject:colorimage4];
[sender setBackgroundImage:[UIImage imageNamed:#"apple.png"] forState:UIControlStateNormal];
[self check];
}
-(IBAction)button6:(id)sender
{
}
-(IBAction)button7:(id)sender
{
}
-(IBAction)button8:(id)sender
{
}
-(IBAction)button9:(id)sender
{
}
-(void)check{
if(k==5)
{
// NSArray *arr1 = [[NSArray alloc]initWithObjects:#"aa",#"bb",#"1",#"cc", nil];
// NSArray *arr2 = [[NSArray alloc]initWithObjects:#"aa",#"bb",#"1",#"cc", nil];
if([dict isEqualToArray:img])
{
NSLog(#"equal");
UIAlertController * alert=[UIAlertController alertControllerWithTitle:#"Title"
message:#"Message"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* Retry = [UIAlertAction actionWithTitle:#"you got"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSLog(#"you pressed Yes, please button");
// call method whatever u need
}];
[alert addAction:Retry];
[self presentViewController:alert animated:YES completion:nil];
}
else{
NSLog(#"not equal........");
UIAlertController * alert=[UIAlertController alertControllerWithTitle:#"Title"
message:#"Message"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* Retry = [UIAlertAction actionWithTitle:#"please try again............"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSLog(#"you pressed Yes, please button");
// call method whatever u need
}];
[alert addAction:Retry];
[self presentViewController:alert animated:YES completion:nil];
}
}
// else
// {
// UIAlertController * alert=[UIAlertController alertControllerWithTitle:#"Title"
// message:#"Message"
// preferredStyle:UIAlertControllerStyleAlert];
// UIAlertAction* Retry = [UIAlertAction actionWithTitle:#"please try again"
// style:UIAlertActionStyleDefault
// handler:^(UIAlertAction * action)
// {
// NSLog(#"you pressed Yes, please button");
// call method whatever u need
// }];
// [alert addAction:Retry];
// [self presentViewController:alert animated:YES completion:nil];
// }
}
i got the images.But as i told ,i have stored 5 images in dict.i need to display the images randomly tag of UIbutton.I tried with many code.But not got.
And also i have stored 10 images in NSMutableArray .And i need to select randomly 4 images from the array and need to display the image where unfilled uibutton img(that is...already 5 images will display on different tag of UIButtons and remaining 4 UIButton should display the images which is stored in array of 10 images).how to do?
The good way to use is to go for IBOutletCollection.
Instead of creating so many outlets you can use IBOutletCollection and make your code small. When you do that you can collect all your 9 buttons inside one array.
#IBOutlet var buttons: [UIButton]!
Now let's assume you have random tags generated - use some random generator - and stored inside:
var randomTags: [Int]
Now you can use this beautiful Swift syntax to filter and get new buttons array which has only those buttons whose tag is randomly generated and stored inside randomTags
let newButtons = buttons.filter { (button) -> Bool in
return randomTags.contains(button.tag)
}
Hope it helps.
Code that I wrote for iOS9, worked really well:
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Select source"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alert.view.backgroundColor = DARK_BLUE;
alert.view.tintColor = NEON_GREEN;
UIView *subview = alert.view.subviews.firstObject;
UIView *alertContentView = subview.subviews.firstObject;
alertContentView.backgroundColor = DARK_BLUE;
alertContentView.layer.cornerRadius = 10;
My point of view is that UIAlertController is inheriting from UIViewController, and UIViewController have property UIView that can be changed. And this is working. Now, that view inherited from UIViewController have it's own subview that is contentView showed as Alert. I can access it as firstObject in array of subviews. Now, why message for sending background color isn't working anymore? Do anyone know some new solution?
For everyone that will bump into the same problem, I've found the solution:
UIAlertController.view contains one subview, that is only container.
That subview contains subview that contains two it's own subviews, one is container, and another is layer for blurring it.
So, it needs for in loop to iterate through that two subviews and change background color of both.
Full code:
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Select source"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alert.view.tintColor = NEON_GREEN;
UIView *firstSubview = alert.view.subviews.firstObject;
UIView *alertContentView = firstSubview.subviews.firstObject;
for (UIView *subSubView in alertContentView.subviews) { //This is main catch
subSubView.backgroundColor = DARK_BLUE; //Here you change background
}
In Swift 3.0
let FirstSubview = alertController.view.subviews.first
let AlertContentView = FirstSubview?.subviews.first
for subview in (AlertContentView?.subviews)! {
subview.backgroundColor = UIColor.black
subview.layer.cornerRadius = 10
subview.alpha = 1
subview.layer.borderWidth = 1
subview.layer.borderColor = UIColor.yellow.cgColor
}
I use this:
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Alert!"
message:#"Message of alert"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"Ok"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
//Your code
}];
[alert addAction:defaultAction];
UIView * topview = alert.view.subviews.firstObject;
UIView * colorView = topview.subviews.firstObject;
colorView.backgroundColor = [UIColor yellowColor];
colorView.layer.cornerRadius = 10;
[self presentViewController:alert animated:YES completion:nil];
Currently I have a button that makes a draggable UIView with a subview of a UIButton. When I long press that UIButton, an alert view comes up and I have two buttons, a delete button and a cancel button. The delete button is supposed to delete the last long pressed UIButton, however it deletes the most recently made UIButton.
I would like for the delete button on the alert view to delete the last long pressed UIButton.(not the most recently created) I have tried different if statements, but this is what I have so far. Here is my code for my .m file:
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateBegan ) {
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Would you like to delete this rep?"
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* deleteButton = [UIAlertAction
actionWithTitle:#"Delete"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[_buttonField removeFromSuperview];
[alert dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancelButton = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:deleteButton];
[alert addAction:cancelButton];
[self presentViewController:alert animated:YES completion:nil];
}
}
- (void)panWasRecognized:(UIPanGestureRecognizer *)panner {
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
[self.buttonField addGestureRecognizer:longPress];
_draggedView = panner.view;
CGPoint offset = [panner translationInView:_draggedView.superview];
CGPoint center = _draggedView.center;
_draggedView.center = CGPointMake(center.x + offset.x, center.y + offset.y);
_draggedView.layer.borderWidth = 2.0f;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
[_buttonField setTintColor:[UIColor magentaColor]];
// Reset translation to zero so on the next `panWasRecognized:` message, the
// translation will just be the additional movement of the touch since now.
[panner setTranslation:CGPointZero inView:_draggedView.superview];
}
}
- (IBAction)addRepButton:(UIBarButtonItem *)newRep {
self.labelCounter++;
buttonCount ++;
if (buttonCount >= 0 )
{
_buttonField = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 28, 28)];
[_buttonField setTitle:[NSString stringWithFormat:#"%i", self.labelCounter]forState:UIControlStateNormal];
[_buttonField setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_buttonField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
_buttonField.userInteractionEnabled = YES;
_buttonField.layer.cornerRadius = 14;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_buttonField.layer.borderWidth = 2.0f;
_buttonField.titleLabel.font = [UIFont systemFontOfSize: 18];
UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(panWasRecognized:)];
[_buttonField addGestureRecognizer:panner];
[self.view addSubview:_buttonField];
}
}
How do I go about making the delete button remove the most recently long pressed _buttonField?
You are saying:
[_buttonField removeFromSuperview];
Well, as your loop shows (inside addRepButton), _buttonField is the most recently added button, because every time you add a button, you set it to that button. So what is happening is exactly what you are saying to happen.
I presume, although it is a little hard to tell from your code, that the button you want to delete is the one whose long press gesture recognizer this is — that is, gesture.view.
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateBegan ) {
//Update
UIButton *buttonPressedLatest;
UIView *ifBtnPressed = gesture.view;
if([ifBtnPressed isKindOfClass:[UIButton class]]){
buttonPressedLatest = (UIButton *)ifBtnPressed;
}
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Would you like to delete this rep?"
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* deleteButton = [UIAlertAction
actionWithTitle:#"Delete"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[buttonPressedLatest removeFromSuperview];
[alert dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancelButton = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:deleteButton];
[alert addAction:cancelButton];
[self presentViewController:alert animated:YES completion:nil];
}
}
Try this once and tell me if this works.
As everyone's aware, UIAlertView is deprecated now and Apple wants us to use the new UIAlertController with the style UIAlertControllerStyleAlert. However, using the UIAlertControllerStyleAlert you cannot trigger the UIAlertAction with style UIAlertActionStyleCancel by tapping outside the alert view.
Does anyone know of a way to dismiss the alert view by tapping outside of it?
Cheers
You can add a separate cancel action with style UIAlertActionStyleCancel for the alertViewController so that when user taps outside, you would get the callback.
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"Alert Title" message:#"A Message" preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
// Called when user taps outside
}]];
Try this code:
- (void)viewDidLoad {
[super viewDidLoad];
[self button];
}
- (void) button {
UIButton * AlertButton = [UIButton buttonWithType:UIButtonTypeSystem];
[AlertButton setTitle:#"Button" forState:UIControlStateNormal];
AlertButton.frame = CGRectMake((self.view.frame.size.width/2) - 50 , (self.view.frame.size.height/2) - 25, 100, 50);
[AlertButton addTarget:self action:#selector(Alert) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:AlertButton];
}
- (void)Alert {
UIAlertController * alert = [UIAlertController alertControllerWithTitle:#"Alert Title" message:#"Alert Message" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController: alert animated: YES completion:^{ alert.view.superview.userInteractionEnabled = YES; [alert.view.superview addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget: self action: #selector(DismissAlertByTab)]]; }];
}
- (void)DismissAlertByTab
{
[self dismissViewControllerAnimated: YES completion: nil];
}
Here is a screenshot of a UIAlertController. I was just playing around custom fonts and textfield properties but I was unable to accomplish the following:
clear background of the UITextField
no ugly border (black box) as shown below
As I dived more into the code and iOS runtime headers, I was able to modify border and background color but the above issue still remains as those properties belong to a container UITextView. Changing background to clearColor doesn't help.
Has anybody ever played around with this? Not sure if I would ever take my app into production with such ugly text fields.
EDIT (May 13, 15) The answer below by Rory McKinnel is tested for iOS 8 - 8.3 and works just fine. The result is below:
Had some fun with this. The following seems to work. Obviously judging by what was required, it has no future proofing and is a patch away from not working.
I figured this out by walking the view hierarchy in the debugger, from which I noticed a UIVisualEffectView. Removing that seems to give you what you want along with setting the containing view to a clear background. Without removing the visual effect, a clear background shows what is behind the alert view itself for some reason.
UIAlertController *alertController =
[UIAlertController alertControllerWithTitle:#"Its Not Pretty!"
message:#"Some times things get ugly!"
preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField){
textField.text = #"Text: No border and clear 8^)";
}];
[self presentViewController:alertController animated:TRUE completion:^{
}];
for (UIView* textfield in alertController.textfields) {
UIView *container = textField.superview;
UIView *effectView = container.superview.subviews[0];
if (effectView && [effectView class] == [UIVisualEffectView class]){
container.backgroundColor = [UIColor clearColor];
[effectView removeFromSuperview];
}
}
here is the important part in swift:
for textfield: UIView in alertController.textfields {
var container: UIView = textField.superview
var effectView: UIView = container.superview.subviews[0]
container.backgroundColor = UIColor.clearColor()
effectView.removeFromSuperview()
}
Swift 3 clear version
alertController.textFields?.forEach {
$0.superview?.backgroundColor = .clear
$0.superview?.superview?.subviews[0].removeFromSuperview()
}
You can try this.
As you need only clear color to textfield of your alertview.
simply add lines of code after your alertview is created.
UITextField *textField = [alertView textFieldAtIndex:0];
textField.backgroundColor=[UIColor clearColor];
textField.superview.backgroundColor=[UIColor clearColor];
EDIT
for alertviewCoontroller you can add
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.backgroundColor=[UIColor clearColor];
textField.superview.backgroundColor=[UIColor clearColor];
}];
Thanks, revert if any confusion.
You can change the border and background color like this:
let subview = alertController!.view.subviews.first! as UIView
let alertContentView = subview.subviews.first! as UIView
alertContentView.backgroundColor = UIColor.lightGrayColor()
alertContentView.layer.cornerRadius = 10;
alertContentView.layer.borderWidth = 2;
Swift 2.0 version:
for textField in alert.textFields! {
if let container = textField.superview, let effectView = container.superview?.subviews.first where effectView is UIVisualEffectView {
container.backgroundColor = UIColor.clearColor()
effectView.removeFromSuperview()
}
}
To address the situation as discussed in #Rory McKinnel and #Matthew where the superview are NULL and address modifying presented view:
extension UIAlertController {
override open func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.textFields?.forEach {
$0.superview?.backgroundColor = .color
$0.superview?.superview?.subviews[0].removeFromSuperview()
}
}
}
This is very hacky, so examine it well before using (tested on iOS 8.3):
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"My Alert"
message:#"This is an alert."
preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = #"This is my placeholder";
textField.backgroundColor = [UIColor colorWithRed:246.0/255.0 green:246.0/255.0 blue:246.0/255.0 alpha:1.0]; // You can change it to whatever color you want
[textField superview].backgroundColor = textField.backgroundColor;
[[textField superview] superview].backgroundColor = [UIColor whiteColor];
}];