• 带有关闭按钮的alertView


    概述

    由于讨厌系统自带的alertView只能通过点击按钮才能关闭。你说万一按钮区域都是功能性的操作呢(这可不是我胡思乱想哦,要怪就产品的想法吧,呵呵哒),所以我们还是应该备有一个带有“X”(关闭按钮,为什么是叫X,因为X这个标志很明显嘛~)的alertView。

    详细

    一、程序实现

    1、程序结构

    B949195B-257D-4F01-8F2B-243092F029DF.png

    2、实现思路与代码

    XBAlertView是作为显示弹出框的入口,在初始化XBAlertView示例时,会将弹出框除了按钮部分全都设置好。而按钮部分采用UICollectionView来实现(因为有可能有多个按钮,这样方便扩展)。

    - (void)setupContentView{
        //title
        self.alertTitleLabel = [[UILabel alloc] init];
        self.alertTitleLabel.font = [UIFont boldSystemFontOfSize:17.0f];
        self.alertTitleLabel.textAlignment = NSTextAlignmentCenter;
        self.alertTitleLabel.frame = CGRectMake(TitleHorizontalOffset, TitleMarginTop, SelfWidth - TitleHorizontalOffset * 2, self.alertTitleLabel.font.lineHeight);
        [self addSubview:self.alertTitleLabel];
        
        //content
        CGFloat contentLabelWidth = SelfWidth - ContentHorizontalOffset * 2;
        CGFloat contentH = [self heightWithContent:_content byWidth:contentLabelWidth andFontSize:13 andLineSpacing:3];
        self.alertContentLabel = [[UILabel alloc] initWithFrame:CGRectMake(ContentHorizontalOffset, CGRectGetMaxY(self.alertTitleLabel.frame) + ContentMarginTop, contentLabelWidth, contentH)];
        self.alertContentLabel.numberOfLines = 0;
        self.alertContentLabel.textAlignment = NSTextAlignmentCenter;
        self.alertContentLabel.font = [UIFont systemFontOfSize:13.0f];
        [self addSubview:self.alertContentLabel];
        
        //self
        CGFloat selfHeight = TitleMarginTop + self.alertTitleLabel.font.lineHeight + ContentMarginTop + contentH + BtnMarginTop + kButtonHeight;
        CGFloat selfMarginLeft = (ScreenWidth - SelfWidth) / 2;
        self.frame = CGRectMake(selfMarginLeft, (ScreenHeight - selfHeight) / 2, SelfWidth, selfHeight);
        self.clipsToBounds = YES;
        self.layer.cornerRadius = 10.0;
        self.backgroundColor = [UIColor whiteColor];
        
        //collectionView
        [self addSubview:self.collectionView];
        _collectionView.delegate = self;
        _collectionView.dataSource = self;
        [_collectionView registerNib:[UINib nibWithNibName:@"XBAlertBtnCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:btnCellOneID];
        [_collectionView registerNib:[UINib nibWithNibName:@"XBAlertBtnCellTwo" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:btnCellTwoID];
        
        //X按钮
        UIButton *xButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [xButton setImage:[UIImage imageNamed:@"btn_close_normal.png"] forState:UIControlStateNormal];
        [xButton setImage:[UIImage imageNamed:@"btn_close_selected.png"] forState:UIControlStateHighlighted];
        xButton.frame = CGRectMake(self.frame.size.width - 32, 0, 32, 32);
        [self addSubview:xButton];
        [xButton addTarget:self action:@selector(dismissAlert) forControlEvents:UIControlEventTouchUpInside];
    }

    为了能够切合原生方式的调用,提供了-(void)addAction:(dispatch_block_t)actionBlock withTitle:(NSString*)title方法,该方法用于向XBAlertView添加按钮以及对应的响应block。

    -(void)addAction:(dispatch_block_t)actionBlock withTitle:(NSString*)title{
        if(actionBlock && ![self isBlankString:title]){
            [self.blockArray addObject:actionBlock];
            [self.btnTitleArray addObject:title];
        }
    }

    调用后会先保存到数组当中。

    在这之后,调用方调用XBAlertView的show方法进行展示。

    - (void)show
    {
        if(self.btnTitleArray.count == 0 || self.btnTitleArray.count > 2){
            //更新view的frame
            [self updateFrame];
        }
        [self.collectionView reloadData];
        UIViewController *topVC = [self appRootViewController];
        [topVC.view addSubview:self];
    }

    show方法首先会根据两个数组是否有值来决定是否更新collectionView的frame。之后调用collectionView的reloadData,数据源就是这两个数组。这样加载后collectionView就有了需要展示的按钮。

    然后获取[UIApplication sharedApplication].keyWindow.rootViewController,在这个控制器的view上添加上已经布局好的XBAlertView。

    但是为了营造阴影效果,在XBAlertView被添加到父view之前,会调用以下方法创建一个遮罩层。这样就能达到显示的要求。

    - (void)willMoveToSuperview:(UIView *)newSuperview
    {
        if (newSuperview == nil) {
            return;
        }
        UIViewController *topVC = [self appRootViewController];
    
        if (!self.backImageView) {
            self.backImageView = [[UIView alloc] initWithFrame:topVC.view.bounds];
            self.backImageView.backgroundColor = [UIColor blackColor];
            self.backImageView.alpha = 0.6f;
            self.backImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        }
        [topVC.view addSubview:self.backImageView];
        CGRect afterFrame = CGRectMake((CGRectGetWidth(topVC.view.bounds) - self.frame.size.width) * 0.5, (CGRectGetHeight(topVC.view.bounds) - self.frame.size.height) * 0.5, self.frame.size.width, self.frame.size.height);
        self.frame = afterFrame;
        [super willMoveToSuperview:newSuperview];
    }

    那么接下来就是点击响应了,因为每个按钮就是collectionView的一个cell,所以按钮的点击就转为了cell的didSelectItemAtIndexPath方法。在该方法中根据索引从前面保存好的数组取出相对应的block,并调用

    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
        dispatch_block_t block = self.blockArray[indexPath.row];
        block();
        [self dismissAlert];
    }

    那么为了将隐藏弹出框封装到里面,会主动调用dismissAlert方法隐藏弹出框。

    二、运行效果

    下载解压后,直接用xcode打开,即可运行

    4191AA2D-B0B8-4879-95E0-EF8016871A7B.png

    19815664-01D6-4B66-896F-042BD5977F36.png

    77C09C15-0105-4067-A237-CEACCD03CEFB.png

    注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

  • 相关阅读:
    反射创建对象
    DevExpress 日期输入框
    SsdlToSql10.tt文件内容
    ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
    DevExpress XtraCharts 图表导出PDF/XLS/JPEG
    Java中堆内存和栈内存详解(转)
    批量合并word文档
    java内部类总结(转)
    Java 之工厂方法和抽象工厂模式(转)
    Java GC 、引用
  • 原文地址:https://www.cnblogs.com/demodashi/p/8486527.html
Copyright © 2020-2023  润新知