Search code examples
swiftios9uialertcontroller

UIAlertController - add custom views to actionsheet


I'm trying to make the actionsheet as it shows in the messages app on iOS when we try to attach an image as in the screenshot.

I realized in new UIAlertController, we can't fit any custom views. Any way I can make exactly this?

My code looks pretty standard.

    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)

enter image description here


Solution

  • UIAlertController extends UIViewController, which has a view property. You can add subviews to that view to your heart's desire. The only trouble is sizing the alert controller properly. You could do something like this, but this could easily break the next time Apple adjusts the design of 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:{})
    

    Objective-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:^{}];
    

    That being said, a much less hacky approach would be to make your own view subclass that works similarly to UIAlertController's UIAlertActionStyle layout. In fact, the same code looks slightly different in iOS 8 and iOS 9.

    iOS 8 enter image description here

    iOS 9 enter image description here

    iOS 10 enter image description here