2017-04-19 12 views
1

UIAlertControllerの中にカスタムビューを配置しようとしています。私は、カスタムビューのサイズ変更に関するいくつかの奇妙な問題にぶち当たっています。UIAlertControllerのカスタムビュー

カスタムビューをUIAlertControllerの幅に広げたいと思います。私はCGRectGetWidth(alertController.view.bounds)を使用してアラートコントローラの幅を取得しています。しかし、これは代わりにビュー全体の幅を返すように思えます。 view.frameを使用しても差はありません。

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"My Title" message:nil preferredStyle:UIAlertControllerStyleAlert]; 

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(alertController.view.bounds), 50)]; 
view.backgroundColor = [UIColor blueColor]; 

[alertController.view addSubview:view]; 
[self presentViewController:alertController animated:YES completion:nil]; 

この結果は以下のとおりです。私はUIAlertControllerのX、Yの幅と高さのプロパティを取得しようと同じ問題があります。誰もハードコーディングされた番号を使用せずに警告コントローラの真ん中にこのビューを配置する方法を知っていますか?

enter image description here

答えて

4

あなたがそれを行うことになっていません。ドキュメントを引用するには:

UIAlertControllerクラスは、そのまま使用するためのものであり、サブクラス化をサポートしていません。

このクラスのビュー階層はプライベートであり、変更することはできません。

Appleのような明示的なステートメントに反対すると、すべての賭けは無効になり、現在のOSバージョンで動作するようになっても、将来のバージョンで破損する可能性があります。

+0

私は '使用すると、あなたは簡単に' UIAlertController'の挙動を再現することができますUIPresentationController'ことを追加しますどんなビュー/コントローラを提供してもかまいません。 – jjatie

+0

@jjatie、 'UIAresentController'を使って' UIAlertController'の振る舞いを複製/拡張するサンプルプロジェクト/ツットがありますか?私は 'UIPresentationController'でまだ働いていません。 –

+0

ここが出発点です。 CoolPresentationControllerが閉じます。 https://developer.apple.com/library/content/samplecode/LookInside/Introduction/Intro.html#//apple_ref/doc/uid/TP40014643関連するWWDCビデオもあります – jjatie

1

代替案があります。UIAlertControlのビュー階層にサブビューを追加するのではなく、代わりに適切な位置にUIWindowを追加します。 UIAlertControlのビューフレームを追跡するために、ビューコントローラは、UIViewControllerスーパークラス実装を呼び出すobj-cランタイム/スウィフト拡張を使用して、カスタム.viewゲッターで拡張されます。これにより、本物のビューのプライベートクラス依存を避けることができ、UIAlertControlをサブクラス化することも、ビューの階層を変更することもできません。

Example screenshot

のObjective-C

#import <objc/runtime.h> 
#import <objc/message.h> 
@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 

スウィフト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) { 
      } 
     } 
    } 
} 
関連する問題