Custom View in UIAlertController

后端 未结 2 2060
失恋的感觉
失恋的感觉 2021-01-14 14:30

I am trying to put a custom view inside a UIAlertController. I\'m running into some odd issues with the sizing of the custom view.

I want the custom vie

2条回答
  •  说谎
    说谎 (楼主)
    2021-01-14 15:12

    Here's an alternative.It's not adding subview to UIAlertControl's view hierarchy, but to UIWindow instead in appropriate position. To track UIAlertControl's view frame the view controller is extended with a custom .view getter using obj-c runtime/swift extension which calls UIViewController super class implementation. This allows avoiding genuine view's private class dependence and is neither subclassing UIAlertControl or modifying it's view hierarchy.

    Objective-C

    #import 
    #import 
    @implementation AppDelegate
    + (UIView*)alertHelperView
    {
        static UIView *alertHelperView = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            alertHelperView = [UIView new];
            alertHelperView.backgroundColor = [UIColor redColor];
            alertHelperView.frame = CGRectZero;
        });
        return alertHelperView;
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        [self.window addSubview:[AppDelegate alertHelperView]];
        return YES;
    }
    @end
    @implementation ViewController
    
    - (void)viewDidAppear:(BOOL)animated {
        Class class = [UIAlertController class];
        class_addMethod(class, @selector(view), imp_implementationWithBlock(^(__unsafe_unretained UIAlertController* self) {
            
            struct objc_super super = {
                .receiver = self,
                .super_class = class_getSuperclass(class)
            };
            
            id (*objc_msgSendSuper_typed)(struct objc_super *, SEL) = (void *)&objc_msgSendSuper;
            
            UIView* myView = objc_msgSendSuper_typed(&super, @selector(view));
            CGRect newFrame = myView.frame;
            if (!self.isBeingPresented) {
                [AppDelegate alertHelperView].frame = CGRectZero;
            } else {
                [[AppDelegate alertHelperView].superview bringSubviewToFront:[AppDelegate alertHelperView]];
                [AppDelegate alertHelperView].frame = CGRectMake(newFrame.origin.x,
                                                                 newFrame.origin.y,
                                                                 newFrame.size.width/2,
                                                                 newFrame.size.height/2);
            }
            return myView;
        }), "@@:");
        
        UIAlertController * alert=   [UIAlertController
                                      alertControllerWithTitle:@"Info"
                                      message:@"You are using UIAlertController"
                                      preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction* ok = [UIAlertAction
                             actionWithTitle:@"OK"
                             style:UIAlertActionStyleDefault
                             handler:^(UIAlertAction * action)
                             {
                             }];
        UIAlertAction* cancel = [UIAlertAction
                                 actionWithTitle:@"Cancel"
                                 style:UIAlertActionStyleDefault
                                 handler:^(UIAlertAction * action)
                                 {
                                 }];
        
        [alert addAction:ok];
        [alert addAction:cancel];
        
        [self presentViewController:alert animated:YES completion:nil];
    }
    @end
    

    Swift 3.1

    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        
        var window: UIWindow?
            static var alertHelperView : UIView!
           
            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
                AppDelegate.alertHelperView = UIView()
                AppDelegate.alertHelperView.backgroundColor = .red
                self.window?.addSubview(AppDelegate.alertHelperView!)
                return true
            }
      }
        
        extension UIAlertController {
            open override var view: UIView! {
                get {
                    let newFrame : CGRect = super.view.frame
                    if !self.isBeingPresented {
                        AppDelegate.alertHelperView.frame = CGRect.zero
                    } else {
                        AppDelegate.alertHelperView.superview?.bringSubview(toFront: AppDelegate.alertHelperView)
                        AppDelegate.alertHelperView.frame = CGRect(x:newFrame.origin.x,y:newFrame.origin.y,width:newFrame.size.width/2,height:newFrame.size.height/2)
                    }
                    return super.view
                }
                set(newValue) {
                    super.view = newValue
                }
            }
        }
    
        class ViewController: UIViewController {
            override func viewDidAppear(_ animated: Bool) {
                let alertController = UIAlertController(title: "Default Style", message: "A standard alert.", preferredStyle: .alert)
                
                let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { action in
                    // ...
                }
                alertController.addAction(cancelAction)
                
                let OKAction = UIAlertAction(title: "OK", style: .default) { action in
                    // ...
                }
                alertController.addAction(OKAction)
                self.present(alertController, animated: false) {
                }
            }
        }
    }
    

提交回复
热议问题