ios开发整理iOS小白聚集地

精简的底部弹框

2018-07-25  本文已影响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

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

上一篇 下一篇

猜你喜欢

热点阅读