• iOS开发-自定义UIAlterView(iOS 7)


    App中不可能少了弹框,弹框是交互的必要形式,使用起来也非常简单,不过最近需要自定义一个弹框,虽然iOS本身的弹框已经能满足大部分的需求,但是不可避免还是需要做一些自定义的工作。iOS7之前是可以自定义AlterView的,就是继承一下UIAlterView,然后初始化的时候通过addSubview添加自定义的View,但是iOS7之后这样做就不行了,不过还好有开源项目可以解决这个问题。

    iOS默认弹框

    viewDidLoad中添加两个按钮,代码如下:

        UIButton  *orignalBtn=[[UIButton alloc]initWithFrame:CGRectMake(100, 40, 100, 50)];
        [orignalBtn setBackgroundColor:[UIColor greenColor]];
        [orignalBtn setTitle:@"iOS弹框" forState:UIControlStateNormal];
        [orignalBtn addTarget:self action:@selector(orignalShow) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:orignalBtn];
        
        
        
        UIButton  *customlBtn=[[UIButton alloc]initWithFrame:CGRectMake(100, 140, 100, 50)];
        [customlBtn setBackgroundColor:[UIColor redColor]];
        [customlBtn setTitle:@"自定义弹框" forState:UIControlStateNormal];
        [customlBtn addTarget:self action:@selector(customShow) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:customlBtn];
    

     响应默认弹框事件:

    -(void)orignalShow{
        UIAlertView *alterView=[[UIAlertView alloc]initWithTitle:@"提示" message:@"博客园-Fly_Elephant" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
        [alterView show];
    }
    

      效果如下:

    自定义弹框

    主要解决iOS7之后的系统无法自定义弹框的问题,使用开源项目,项目地址:https://github.com/wimagguc/ios-custom-alertview,其实就是自定义了一个类:

    CustomIOSAlertView.h

    #import <UIKit/UIKit.h>
    
    @protocol CustomIOSAlertViewDelegate
    
    - (void)customIOS7dialogButtonTouchUpInside:(id)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
    
    @end
    
    @interface CustomIOSAlertView : UIView<CustomIOSAlertViewDelegate>
    
    @property (nonatomic, retain) UIView *parentView;    // The parent view this 'dialog' is attached to
    @property (nonatomic, retain) UIView *dialogView;    // Dialog's container view
    @property (nonatomic, retain) UIView *containerView; // Container within the dialog (place your ui elements here)
    
    @property (nonatomic, assign) id<CustomIOSAlertViewDelegate> delegate;
    @property (nonatomic, retain) NSArray *buttonTitles;
    @property (nonatomic, assign) BOOL useMotionEffects;
    
    @property (copy) void (^onButtonTouchUpInside)(CustomIOSAlertView *alertView, int buttonIndex) ;
    
    - (id)init;
    
    /*!
     DEPRECATED: Use the [CustomIOSAlertView init] method without passing a parent view.
     */
    - (id)initWithParentView: (UIView *)_parentView __attribute__ ((deprecated));
    
    - (void)show;
    - (void)close;
    
    - (IBAction)customIOS7dialogButtonTouchUpInside:(id)sender;
    - (void)setOnButtonTouchUpInside:(void (^)(CustomIOSAlertView *alertView, int buttonIndex))onButtonTouchUpInside;
    
    - (void)deviceOrientationDidChange: (NSNotification *)notification;
    - (void)dealloc;
    
    @end
    

    CustomIOSAlertView.m

    #import "CustomIOSAlertView.h"
    #import <QuartzCore/QuartzCore.h>
    
    const static CGFloat kCustomIOSAlertViewDefaultButtonHeight       = 50;
    const static CGFloat kCustomIOSAlertViewDefaultButtonSpacerHeight = 1;
    const static CGFloat kCustomIOSAlertViewCornerRadius              = 7;
    const static CGFloat kCustomIOS7MotionEffectExtent                = 10.0;
    
    @implementation CustomIOSAlertView
    
    CGFloat buttonHeight = 0;
    CGFloat buttonSpacerHeight = 0;
    
    @synthesize parentView, containerView, dialogView, onButtonTouchUpInside;
    @synthesize delegate;
    @synthesize buttonTitles;
    @synthesize useMotionEffects;
    
    - (id)initWithParentView: (UIView *)_parentView
    {
        self = [self init];
        if (_parentView) {
            self.frame = _parentView.frame;
            self.parentView = _parentView;
        }
        return self;
    }
    
    - (id)init
    {
        self = [super init];
        if (self) {
            self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
    
            delegate = self;
            useMotionEffects = false;
            buttonTitles = @[@"Close"];
            
            [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        }
        return self;
    }
    
    // Create the dialog view, and animate opening the dialog
    - (void)show
    {
        dialogView = [self createContainerView];
      
        dialogView.layer.shouldRasterize = YES;
        dialogView.layer.rasterizationScale = [[UIScreen mainScreen] scale];
      
        self.layer.shouldRasterize = YES;
        self.layer.rasterizationScale = [[UIScreen mainScreen] scale];
    
    #if (defined(__IPHONE_7_0))
        if (useMotionEffects) {
            [self applyMotionEffects];
        }
    #endif
    
        self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
    
        [self addSubview:dialogView];
    
        // Can be attached to a view or to the top most window
        // Attached to a view:
        if (parentView != NULL) {
            [parentView addSubview:self];
    
        // Attached to the top most window
        } else {
    
            // On iOS7, calculate with orientation
            if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
                
                UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
                switch (interfaceOrientation) {
                    case UIInterfaceOrientationLandscapeLeft:
                        self.transform = CGAffineTransformMakeRotation(M_PI * 270.0 / 180.0);
                        break;
                        
                    case UIInterfaceOrientationLandscapeRight:
                        self.transform = CGAffineTransformMakeRotation(M_PI * 90.0 / 180.0);
                        break;
                        
                    case UIInterfaceOrientationPortraitUpsideDown:
                        self.transform = CGAffineTransformMakeRotation(M_PI * 180.0 / 180.0);
                        break;
                        
                    default:
                        break;
                }
                
                [self setFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    
            // On iOS8, just place the dialog in the middle
            } else {
    
                CGSize screenSize = [self countScreenSize];
                CGSize dialogSize = [self countDialogSize];
                CGSize keyboardSize = CGSizeMake(0, 0);
    
                dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height);
    
            }
    
            [[[[UIApplication sharedApplication] windows] firstObject] addSubview:self];
        }
    
        dialogView.layer.opacity = 0.5f;
        dialogView.layer.transform = CATransform3DMakeScale(1.3f, 1.3f, 1.0);
    
        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionCurveEaseInOut
    					 animations:^{
    						 self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4f];
                             dialogView.layer.opacity = 1.0f;
                             dialogView.layer.transform = CATransform3DMakeScale(1, 1, 1);
    					 }
    					 completion:NULL
         ];
    
    }
    
    // Button has been touched
    - (IBAction)customIOS7dialogButtonTouchUpInside:(id)sender
    {
        if (delegate != NULL) {
            [delegate customIOS7dialogButtonTouchUpInside:self clickedButtonAtIndex:[sender tag]];
        }
    
        if (onButtonTouchUpInside != NULL) {
            onButtonTouchUpInside(self, (int)[sender tag]);
        }
    }
    
    // Default button behaviour
    - (void)customIOS7dialogButtonTouchUpInside: (CustomIOSAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
        NSLog(@"Button Clicked! %d, %d", (int)buttonIndex, (int)[alertView tag]);
        [self close];
    }
    
    // Dialog close animation then cleaning and removing the view from the parent
    - (void)close
    {
        CATransform3D currentTransform = dialogView.layer.transform;
    
        if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
            CGFloat startRotation = [[dialogView valueForKeyPath:@"layer.transform.rotation.z"] floatValue];
            CATransform3D rotation = CATransform3DMakeRotation(-startRotation + M_PI * 270.0 / 180.0, 0.0f, 0.0f, 0.0f);
    
            dialogView.layer.transform = CATransform3DConcat(rotation, CATransform3DMakeScale(1, 1, 1));
        }
    
        dialogView.layer.opacity = 1.0f;
    
        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone
    					 animations:^{
    						 self.backgroundColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f];
                             dialogView.layer.transform = CATransform3DConcat(currentTransform, CATransform3DMakeScale(0.6f, 0.6f, 1.0));
                             dialogView.layer.opacity = 0.0f;
    					 }
    					 completion:^(BOOL finished) {
                             for (UIView *v in [self subviews]) {
                                 [v removeFromSuperview];
                             }
                             [self removeFromSuperview];
    					 }
    	 ];
    }
    
    - (void)setSubView: (UIView *)subView
    {
        containerView = subView;
    }
    
    // Creates the container view here: create the dialog, then add the custom content and buttons
    - (UIView *)createContainerView
    {
        if (containerView == NULL) {
            containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 150)];
        }
    
        CGSize screenSize = [self countScreenSize];
        CGSize dialogSize = [self countDialogSize];
    
        // For the black background
        [self setFrame:CGRectMake(0, 0, screenSize.width, screenSize.height)];
    
        // This is the dialog's container; we attach the custom content and the buttons to this one
        UIView *dialogContainer = [[UIView alloc] initWithFrame:CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height)];
    
        // First, we style the dialog to match the iOS7 UIAlertView >>>
        CAGradientLayer *gradient = [CAGradientLayer layer];
        gradient.frame = dialogContainer.bounds;
        gradient.colors = [NSArray arrayWithObjects:
                           (id)[[UIColor colorWithRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:1.0f] CGColor],
                           (id)[[UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1.0f] CGColor],
                           (id)[[UIColor colorWithRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:1.0f] CGColor],
                           nil];
    
        CGFloat cornerRadius = kCustomIOSAlertViewCornerRadius;
        gradient.cornerRadius = cornerRadius;
        [dialogContainer.layer insertSublayer:gradient atIndex:0];
    
        dialogContainer.layer.cornerRadius = cornerRadius;
        dialogContainer.layer.borderColor = [[UIColor colorWithRed:198.0/255.0 green:198.0/255.0 blue:198.0/255.0 alpha:1.0f] CGColor];
        dialogContainer.layer.borderWidth = 1;
        dialogContainer.layer.shadowRadius = cornerRadius + 5;
        dialogContainer.layer.shadowOpacity = 0.1f;
        dialogContainer.layer.shadowOffset = CGSizeMake(0 - (cornerRadius+5)/2, 0 - (cornerRadius+5)/2);
        dialogContainer.layer.shadowColor = [UIColor blackColor].CGColor;
        dialogContainer.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:dialogContainer.bounds cornerRadius:dialogContainer.layer.cornerRadius].CGPath;
    
        // There is a line above the button
        UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, dialogContainer.bounds.size.height - buttonHeight - buttonSpacerHeight, dialogContainer.bounds.size.width, buttonSpacerHeight)];
        lineView.backgroundColor = [UIColor colorWithRed:198.0/255.0 green:198.0/255.0 blue:198.0/255.0 alpha:1.0f];
        [dialogContainer addSubview:lineView];
        // ^^^
    
        // Add the custom container if there is any
        [dialogContainer addSubview:containerView];
    
        // Add the buttons too
        [self addButtonsToView:dialogContainer];
    
        return dialogContainer;
    }
    
    // Helper function: add buttons to container
    - (void)addButtonsToView: (UIView *)container
    {
        if (buttonTitles==NULL) { return; }
    
        CGFloat buttonWidth = container.bounds.size.width / [buttonTitles count];
    
        for (int i=0; i<[buttonTitles count]; i++) {
    
            UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
    
            [closeButton setFrame:CGRectMake(i * buttonWidth, container.bounds.size.height - buttonHeight, buttonWidth, buttonHeight)];
    
            [closeButton addTarget:self action:@selector(customIOS7dialogButtonTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
            [closeButton setTag:i];
    
            [closeButton setTitle:[buttonTitles objectAtIndex:i] forState:UIControlStateNormal];
            [closeButton setTitleColor:[UIColor colorWithRed:0.0f green:0.5f blue:1.0f alpha:1.0f] forState:UIControlStateNormal];
            [closeButton setTitleColor:[UIColor colorWithRed:0.2f green:0.2f blue:0.2f alpha:0.5f] forState:UIControlStateHighlighted];
            [closeButton.titleLabel setFont:[UIFont boldSystemFontOfSize:14.0f]];
            [closeButton.layer setCornerRadius:kCustomIOSAlertViewCornerRadius];
    
            [container addSubview:closeButton];
        }
    }
    
    // Helper function: count and return the dialog's size
    - (CGSize)countDialogSize
    {
        CGFloat dialogWidth = containerView.frame.size.width;
        CGFloat dialogHeight = containerView.frame.size.height + buttonHeight + buttonSpacerHeight;
    
        return CGSizeMake(dialogWidth, dialogHeight);
    }
    
    // Helper function: count and return the screen's size
    - (CGSize)countScreenSize
    {
        if (buttonTitles!=NULL && [buttonTitles count] > 0) {
            buttonHeight       = kCustomIOSAlertViewDefaultButtonHeight;
            buttonSpacerHeight = kCustomIOSAlertViewDefaultButtonSpacerHeight;
        } else {
            buttonHeight = 0;
            buttonSpacerHeight = 0;
        }
    
        CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
        CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    
        // On iOS7, screen width and height doesn't automatically follow orientation
        if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
            UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
            if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
                CGFloat tmp = screenWidth;
                screenWidth = screenHeight;
                screenHeight = tmp;
            }
        }
        
        return CGSizeMake(screenWidth, screenHeight);
    }
    
    #if (defined(__IPHONE_7_0))
    // Add motion effects
    - (void)applyMotionEffects {
    
        if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
            return;
        }
    
        UIInterpolatingMotionEffect *horizontalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
                                                                                                        type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
        horizontalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent);
        horizontalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent);
    
        UIInterpolatingMotionEffect *verticalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
                                                                                                      type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
        verticalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent);
        verticalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent);
    
        UIMotionEffectGroup *motionEffectGroup = [[UIMotionEffectGroup alloc] init];
        motionEffectGroup.motionEffects = @[horizontalEffect, verticalEffect];
    
        [dialogView addMotionEffect:motionEffectGroup];
    }
    #endif
    
    - (void)dealloc
    {
        [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    }
    
    // Rotation changed, on iOS7
    - (void)changeOrientationForIOS7 {
    
        UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        
        CGFloat startRotation = [[self valueForKeyPath:@"layer.transform.rotation.z"] floatValue];
        CGAffineTransform rotation;
        
        switch (interfaceOrientation) {
            case UIInterfaceOrientationLandscapeLeft:
                rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 270.0 / 180.0);
                break;
                
            case UIInterfaceOrientationLandscapeRight:
                rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 90.0 / 180.0);
                break;
                
            case UIInterfaceOrientationPortraitUpsideDown:
                rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 180.0 / 180.0);
                break;
                
            default:
                rotation = CGAffineTransformMakeRotation(-startRotation + 0.0);
                break;
        }
    
        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone
                         animations:^{
                             dialogView.transform = rotation;
                             
                         }
                         completion:nil
         ];
        
    }
    
    // Rotation changed, on iOS8
    - (void)changeOrientationForIOS8: (NSNotification *)notification {
    
        CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
        CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    
        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone
                         animations:^{
                             CGSize dialogSize = [self countDialogSize];
                             CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
                             self.frame = CGRectMake(0, 0, screenWidth, screenHeight);
                             dialogView.frame = CGRectMake((screenWidth - dialogSize.width) / 2, (screenHeight - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height);
                         }
                         completion:nil
         ];
        
    
    }
    
    // Handle device orientation changes
    - (void)deviceOrientationDidChange: (NSNotification *)notification
    {
        // If dialog is attached to the parent view, it probably wants to handle the orientation change itself
        if (parentView != NULL) {
            return;
        }
    
        if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
            [self changeOrientationForIOS7];
        } else {
            [self changeOrientationForIOS8:notification];
        }
    }
    
    // Handle keyboard show/hide changes
    - (void)keyboardWillShow: (NSNotification *)notification
    {
        CGSize screenSize = [self countScreenSize];
        CGSize dialogSize = [self countDialogSize];
        CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    
        UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
            CGFloat tmp = keyboardSize.height;
            keyboardSize.height = keyboardSize.width;
            keyboardSize.width = tmp;
        }
    
        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone
    					 animations:^{
                             dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height);
    					 }
    					 completion:nil
    	 ];
    }
    
    - (void)keyboardWillHide: (NSNotification *)notification
    {
        CGSize screenSize = [self countScreenSize];
        CGSize dialogSize = [self countDialogSize];
    
        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone
    					 animations:^{
                             dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height);
    					 }
    					 completion:nil
    	 ];
    }
    
    @end
    

    调用代码:

    -(void)customShow{
        CustomIOSAlertView *alertView = [[CustomIOSAlertView alloc] init];
        
        [alertView setContainerView:[self customView]];
        
        [alertView setButtonTitles:[NSMutableArray arrayWithObjects:@"取消", @"确定", nil]];
        [alertView setDelegate:self];
        
        [alertView setOnButtonTouchUpInside:^(CustomIOSAlertView *alertView, int buttonIndex) {
            NSString *result=alertView.buttonTitles[buttonIndex];
            NSLog(@"点击了%@按钮",result);
            [alertView close];
        }];
        
        [alertView setUseMotionEffects:true];
        [alertView show];
    
    }
    
    - (UIView *)customView
    {
        UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 240, 160)];
        
        UILabel *tip=[[UILabel alloc]initWithFrame:CGRectMake(100, 10, 50, 30)];
        [tip setText:@"提示"];
        [customView addSubview:tip];
        
        
        UILabel *content=[[UILabel alloc]initWithFrame:CGRectMake(10, 60, 210, 30)];
        [content setText:@"http://www.cnblogs.com/xiaofeixiang"];
        [content setFont:[UIFont systemFontOfSize:12]];
        [customView addSubview:content];
        return customView;
    }
    

     效果如下:

  • 相关阅读:
    053-649
    053-648
    053-647
    053-646
    053-645
    053-644
    053-643
    053-642
    053-641
    053-640
  • 原文地址:https://www.cnblogs.com/xiaofeixiang/p/4453819.html
Copyright © 2020-2023  润新知