精简的底部弹框

作者: 今晚月色 | 来源:发表于2018-07-25 18:07 被阅读263次
    镇楼图

    在下小白一个,准备写写和自己开发息息相关的控件,希望大家批评指正。这是第一个常用的底部弹窗,使用了最简单的分装方式。适合新人使用,分装的不是很完全,使用者可以自己进行修改参数。

    废话不多说先上代码
    1、头文件里面声明了一个代理和初始化方法。

    #import <UIKit/UIKit.h>
    
    @class WDActionSheet;
    
    @protocol WDActionSheetDelegate
    
    - (void)selectedIndex:(NSInteger)index;
    
    @end
    
    @interface WDActionSheet : UIView
    
    @property (nonatomic, weak) id <WDActionSheetDelegate> delegate;
    
    // 单例
    + (instancetype)shareInstances;
    
    /**
     初始化ActionSheet
    
     @param titleArray 标题文字数组---不能为空
     @param cancelButtonTitle 取消按钮文字---可以为空
     @param selectDelegate 代理
     */
    - (void)setUIWithTitleArray:(NSArray<NSString *> *)titleArray
              cancelButtonTitle:(NSString *)cancelButtonTitle
                 selectDelegate:(id <WDActionSheetDelegate>)selectDelegate;
    
    @end
    

    2、实现文件里面进行页面的绘制、数据处理和事件处理。

    #import "WDActionSheet.h"
    
    #define Sheet_IS_iPhoneX ([UIScreen mainScreen].bounds.size.width == 375 && [UIScreen mainScreen].bounds.size.height == 812)
    #define Sheet_IPHONEX_MARGIN_BOTTOM (34)
    #define Sheet_ScreenWidth UIScreen.mainScreen.bounds.size.width
    #define Sheet_ScreenHeight UIScreen.mainScreen.bounds.size.height
    
    typedef void (^ClickHandler)(NSInteger index);
    
    @interface WDActionSheet  ()<UIGestureRecognizerDelegate>
    // 背景页面
    @property (nonatomic, strong)  UIView *containerView;
    
    @end
    
    @implementation WDActionSheet
    
    #pragma mark -- 单例初始化
    + (instancetype)shareInstances{
        
        static WDActionSheet* single;
        static dispatch_once_t onceToken;
        
        dispatch_once(&onceToken, ^{
            single = [[WDActionSheet alloc] init];
        });
        
        return single;
    }
    
    #pragma mark -- 捕捉错误
    - (void)setUIWithTitleArray:(NSArray<NSString *> *)titleArray cancelButtonTitle:(NSString *)cancelButtonTitle selectDelegate:(id<WDActionSheetDelegate>)selectDelegate{
        
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                              action:@selector(dismissView)];
        tap.delegate                = self;
        [self addGestureRecognizer:tap];
        
        @try {
            if(titleArray.count == 0) {
                @throw [NSException exceptionWithName:NSStringFromClass([self class])
                                               reason:@"标题数组不能为空"
                                             userInfo:nil];
            } else if (selectDelegate == nil) {
                @throw [NSException exceptionWithName:NSStringFromClass([self class])
                                               reason:@"未设置代理对象"
                                             userInfo:nil];
            } else {
                [self createUIWithTitleArray:titleArray cancelButtonTitle:cancelButtonTitle selectDelegate:selectDelegate];
            }
            
        } @catch (NSException *exception) {
            @throw exception;
        } @finally {
           
        }
    }
    
    #pragma mark -- 进行页面绘制
    - (void)createUIWithTitleArray:(NSArray<NSString *> *)titleArray cancelButtonTitle:(NSString *)cancelButtonTitle selectDelegate:(id<WDActionSheetDelegate>)selectDelegate{
        
        self.containerView = [[UIView alloc] init];
        CGFloat W          = Sheet_ScreenWidth;
        CGFloat X          = 0;
        CGFloat H          = 55;
        CGFloat Speace     = 15;
        
        // 设置了 取消按钮的文字
        if(cancelButtonTitle.length > 0) { // 设置取消了按钮
            for (int i = 0; i < titleArray.count; i++) {
                UIButton *button = [self createButtonWithTitle:titleArray[i] buttonTag:10 + I];
                button.frame = CGRectMake(X, H * i, W,  H);
                if( i > 0 ) {
                    UIView *line = [self createLine];
                    line.frame   = CGRectMake(X,  H * i + 0.5, W,  0.5);
                }
            }
            UIButton *cancalButton = [self createButtonWithTitle:cancelButtonTitle buttonTag:9];
            if(Sheet_IS_iPhoneX) {
                cancalButton.frame = CGRectMake(X, (H + 0.5) * titleArray.count + Speace , W, H + Sheet_IPHONEX_MARGIN_BOTTOM);
            } else {
                cancalButton.frame = CGRectMake(X, (H + 0.5) * titleArray.count + Speace , W, H);
            }
           
        }else{  // 没有取消按钮
            for (int i = 0; i < titleArray.count; i++) {
                UIButton *button = [self createButtonWithTitle:titleArray[i] buttonTag:10 + I];
                if(i == titleArray.count-1) {
                    if(Sheet_IS_iPhoneX){
                        button.frame = CGRectMake(X, H * i , W, H + Sheet_IPHONEX_MARGIN_BOTTOM);
                    } else {
                        button.frame = CGRectMake(X, H * i , W, H);
                    }
                } else {
                    button.frame = CGRectMake(X, H * i, W,  H);
                }
                if( i > 0 ) {
                    UIView *line = [self createLine];
                    line.frame   = CGRectMake(X,  H * i + 0.5, W,  0.5);
                }
            }
        }
        
        self.delegate = selectDelegate;
        CGFloat AllHeight = cancelButtonTitle.length > 0  ? (H * (titleArray.count + 1) + 15) : (H * titleArray.count);
        if(Sheet_IS_iPhoneX) {
            AllHeight += Sheet_IPHONEX_MARGIN_BOTTOM;
        }
        [self showViewWithHeight:AllHeight];
    }
    
    #pragma mark -- 按钮点击事件进行传值
    - (void)buttonAction:(UIButton *)sender {
        if(sender.tag != 9) {
            [self.delegate selectedIndex:sender.tag - 10];
        }
        [self dismissView];
    }
    
    #pragma mark -- 公共创建按钮
    - (UIButton *)createButtonWithTitle:(NSString *)title buttonTag:(NSInteger)buttonTag {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button setTitle:title forState:UIControlStateNormal];
        [button sizeToFit];
        [button setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
        button.backgroundColor = UIColor.whiteColor;
        button.tag = buttonTag;
        [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
        [self.containerView addSubview:button];
        return button;
    }
    
    #pragma mark -- 公共创建View
    - (UIView *)createLine {
        UIView *line = [[UIView alloc] init];
        line.backgroundColor = UIColor.lightGrayColor;
        [self.containerView addSubview:line];
        return line;
    }
    
    #pragma mark -- 页面显示
    - (void)showViewWithHeight:(CGFloat)height {
        [UIApplication.sharedApplication.keyWindow addSubview:self];
        [self addSubview:self.containerView];
        
        self.frame = UIScreen.mainScreen.bounds;
        self.containerView.frame = CGRectMake(0, Sheet_ScreenHeight, Sheet_ScreenWidth, 0);
        
        [UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
            self.containerView.frame = CGRectMake(0, Sheet_ScreenHeight-height, Sheet_ScreenWidth, height);
        } completion:^(BOOL finished) {
    
        }];
    }
    
    #pragma mark -- 页面消失
    - (void)dismissView {
        [UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            self.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
            self.containerView.frame = CGRectMake(0, Sheet_ScreenHeight, Sheet_ScreenWidth, 0);
        } completion:^(BOOL finished) {
            [self removeFromSuperview];
            [self.containerView removeFromSuperview];
        }];
    }
    @end
    

    3、使用方法,遵循WDActionSheetDelegate
    无取消按钮

    // cancelButtonTitle可以直接输入空字符串或者nil
    [[WDActionSheet shareInstances] setUIWithTitleArray:@[@"拍照",@"打开相册"] cancelButtonTitle:@"" selectDelegate:self];
    

    带取消按钮

    [[WDActionSheet shareInstances] setUIWithTitleArray:@[@"拍照",@"打开相册"] cancelButtonTitle:@"取消" selectDelegate:self];
    

    4、Swift版创建

    import UIKit
    
    class WDActionSheet: UIView , UIGestureRecognizerDelegate{
        
        private var containerView : UIView?
        private let Sheet_ScreenHeight = UIScreen.main.bounds.size.height
        private let Sheet_ScreenWidth = UIScreen.main.bounds.size.width
        private var delegate : WDActionSheetDelegate?
        
        // MARK: -  初始化
        convenience init(titleArray : Array<String> ,cancelButtonTitle : String , delegate : WDActionSheetDelegate) {
            self.init()
            let tap:UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(dismissView))
            tap.delegate = self
            self.addGestureRecognizer(tap)
            
            if titleArray.count == 0 {
                fatalError("标题数组不能为空")
            } else {
                setupUI(titleArray: titleArray, cancelButtonTitle: cancelButtonTitle, delegate: delegate)
            }
        }
        
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        
        // MARK: -  绘制页面
        private func setupUI(titleArray : Array<String> ,cancelButtonTitle : String , delegate : WDActionSheetDelegate) {
            containerView = UIView.init()
            containerView?.backgroundColor = UIColor.lightGray
            let W:CGFloat = Sheet_ScreenWidth
            let X:CGFloat = 0
            let H:CGFloat = 55
            let Speace:CGFloat = 15
            
            if cancelButtonTitle.count == 0 {
                for (index, _) in titleArray.enumerated() {
                    let button = setupButtons(title: titleArray[index], buttonTag: 10+index)
                    containerView?.addSubview(button)
                    button.frame = CGRect(x: X, y: H * CGFloat(index), width: W, height: H)
                    if index == titleArray.count - 1 {
                        let line = setupLineView()
                        containerView?.addSubview(line)
                        line.frame = CGRect(x: X, y: H * CGFloat(index) + 0.5, width: W, height: 0.5)
                    }
                }
                
            } else {
                
                for (index, _) in titleArray.enumerated() {
                    let button = setupButtons(title: titleArray[index], buttonTag: 10+index)
                    containerView?.addSubview(button)
                    button.frame = CGRect(x: X, y: H * CGFloat(index), width: W, height: H)
                    
                    if index > 0 {
                        let line = setupLineView()
                        containerView?.addSubview(line)
                        line.frame = CGRect(x: X, y: H * CGFloat(index) + 0.5, width: W, height: 0.5)
                    }
                }
                
                let cancalButton = setupButtons(title: cancelButtonTitle, buttonTag: 9)
                containerView?.addSubview(cancalButton)
                cancalButton.frame = CGRect(x: X, y: (H + 0.5) * CGFloat(titleArray.count) + Speace, width: W, height: H)
            }
            
            self.delegate = delegate
            
            var AllHeight:CGFloat = 0.0
            
            if cancelButtonTitle.count > 0 {
                AllHeight = H * CGFloat(titleArray.count + 1) + 15.0
            } else {
                AllHeight = H * CGFloat(titleArray.count)
            }
            
            showView(height: AllHeight)
        }
        
        
        // MARK: -  公共创建按钮
        private func setupButtons(title : String, buttonTag : Int) -> UIButton {
            let button = UIButton.init(type: .custom)
            button.sizeToFit()
            button.backgroundColor = UIColor.white
            button.setTitle(title, for: .normal)
            button.setTitleColor(UIColor.black, for: .normal)
            button.tag = buttonTag
            button.addTarget(self, action: #selector(buttonAction(sender:)), for: .touchUpInside)
            
            return button
        }
        
        
        // MARK: -  公共创建线条
        private func setupLineView() -> UIView {
            let line = UIView.init()
            line.backgroundColor = UIColor.lightGray
            return line
        }
        
        
        // MARK: -  点击事件并传值
        @objc private func buttonAction(sender : UIButton) {
            if sender.tag != 9 {
                delegate?.selectedIndex(index: sender.tag)
            }
    
            dismissView()
        }
        
        // MARK: -  页面显示
        private func showView(height:CGFloat) {
            
            UIApplication.shared.keyWindow?.addSubview(self)
            addSubview(containerView!)
            
            frame = UIScreen.main.bounds;
            containerView?.frame = CGRect(x: 0, y: Sheet_ScreenHeight, width: Sheet_ScreenWidth, height: 0)
            
            UIView.animateKeyframes(withDuration: 0.35, delay: 0, options: .calculationModeLinear, animations: {
                self.backgroundColor = UIColor.init(white: 0, alpha: 0.2)
                self.containerView?.frame = CGRect(x: 0, y: self.Sheet_ScreenHeight-height, width: self.Sheet_ScreenWidth, height: height)
            }, completion: nil)
        }
        
        
        // MARK: - 页面消失
        @objc private func dismissView() {
            
            UIView.animateKeyframes(withDuration: 0.35, delay: 0, options: .calculationModeLinear, animations: {
                self.backgroundColor = UIColor.init(white: 0, alpha: 0.0)
                self.containerView?.frame = CGRect(x: 0, y: self.Sheet_ScreenHeight, width: self.Sheet_ScreenWidth, height: 0)
    
            }) { (finished) in
                self.removeFromSuperview()
                self.containerView?.removeFromSuperview()
            }
        }
    }
    
    // MARK: -  代理
    @objc protocol WDActionSheetDelegate{
        func selectedIndex(index:Int) -> Void
    }
    

    5、Swift版使用方式,也要遵循WDActionSheetDelegate

     WDActionSheet.init(titleArray: ["拍照", "打开相册"], cancelButtonTitle: "取消", delegate: self)
     WDActionSheet.init(titleArray: ["拍照", "打开相册"], cancelButtonTitle: "", delegate: self)
    

    6、效果图两个版本现实都是一样的就放一个图了


    效果图.gif

    7、Demo地址:https://github.com/xlz520/WDActionSheet.git

    结尾:有问题希望大家指正!😄😄😄

    相关文章

      网友评论

        本文标题:精简的底部弹框

        本文链接:https://www.haomeiwen.com/subject/tbdymftx.html