iOS 仿微信 AlertSheet

效果图:


image.png

废话不多 直接上代码
.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN


@interface SheetViewController : UIViewController

+ (instancetype)new __attribute__((unavailable));
+ (instancetype)alloc __attribute__((unavailable));
- (instancetype)init __attribute__((unavailable));

+ (void)showSheetViewControllerWith:(NSArray<NSString *> *)items
                 selectItemCallBack:(void(^)(NSInteger index))selectCallBack
                     showController:(UIViewController *)controller;

@end

NS_ASSUME_NONNULL_END

.m

#import "SheetViewController.h"

#define width [UIScreen mainScreen].bounds.size.width
#define height [UIScreen mainScreen].bounds.size.height
#define cellHeight 50
#define cellFooterHeight 10
#define duration 0.3

typedef void(^SelectItemCallBack)(NSInteger index);

@interface SheetViewController ()<UITableViewDelegate,UITableViewDataSource>

@property (weak, nonatomic) IBOutlet UIView *backgrundView;  /**xib 上面的view 就是个遮罩*/
@property (strong, nonatomic)UIView *bottomView;
@property (nonatomic,strong) UITableView *tableView;
@property (nonatomic,strong) NSMutableArray<NSArray *> *dataArray;
@property (nonatomic,assign) CGFloat bottomViewHeight;
@property (nonatomic,copy) NSArray<NSString *> *items;

@property (nonatomic,copy) SelectItemCallBack selectItemCallBack;

@end

@implementation SheetViewController

+ (void)showSheetViewControllerWith:(NSArray<NSString *> *)items
                 selectItemCallBack:(void (^)(NSInteger))selectCallBack
                     showController:(UIViewController *)controller {
  SheetViewController *sheetViewController = [[SheetViewController alloc] init];
  sheetViewController.selectItemCallBack = selectCallBack;
  sheetViewController.items = items;
  sheetViewController.modalPresentationStyle = UIModalPresentationCustom;
  sheetViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
  [controller presentViewController:sheetViewController animated:YES completion:nil];
}

- (NSMutableArray<NSArray *> *)dataArray {
    if (_dataArray == nil) {
        _dataArray = [NSMutableArray array];
    }
    return _dataArray;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    [self.dataArray addObject:self.items];
    [self.dataArray addObject:@[@"取消"]];
    
    if ([self isIPhoneXAndLater]) {
        self.bottomViewHeight = cellFooterHeight + cellHeight * (self.items.count + 1) + 34;
    }else {
        self.bottomViewHeight = cellFooterHeight + cellHeight * (self.items.count + 1);
    }
    
    [self setUpSubViews];
    
    [self configController];
}

- (void)configController {
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchesBegan)];
    [self.backgrundView addGestureRecognizer:tap];
}

- (void)touchesBegan {
    [self dismiss];
}

- (void)setUpSubViews {
   self.bottomView = [[UIView alloc] init];
   self.bottomView.backgroundColor = [UIColor whiteColor];
   self.bottomView.frame = CGRectMake(0, height, width, self.bottomViewHeight);
   [self.view addSubview:self.bottomView];
    
    [self shapeLayerWith:self.bottomView];
    CGFloat tableViewHeight = [self isIPhoneXAndLater] ? self.bottomViewHeight - 34 : self.bottomViewHeight;
    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, width, tableViewHeight)
                                                  style:UITableViewStylePlain];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.bounces = NO;
    self.tableView.rowHeight = cellHeight;
   [self.bottomView addSubview:self.tableView];
    
    if ([self isIPhoneXAndLater]) {
        UIView *tableViewBottomView = [[UIView alloc] initWithFrame:CGRectMake(0, tableViewHeight, width, 34)];
        tableViewBottomView.backgroundColor = [UIColor whiteColor];
        [self.bottomView addSubview:tableViewBottomView];
    }
   
   __weak typeof(self) weakSelf = self;
   dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC);
   dispatch_after(timer, dispatch_get_main_queue(), ^(void){
       [weakSelf show];
   });
}

- (BOOL)isIPhoneXAndLater {
    if (@available(iOS 11.0, *)) {
        if ([[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0){
            return YES;
        }else {
            return NO;
        }
    } else {
        // Fallback on earlier versions
        return NO;
    }
}

- (void)dismiss {
    __weak typeof(self) weakSelf = self;
   [UIView animateWithDuration:duration
                    animations:^{
        weakSelf.bottomView.frame = CGRectMake(0, height, width, weakSelf.bottomViewHeight);
   } completion:^(BOOL finished) {
       [self dismissViewControllerAnimated:YES completion:nil];
   }];
}

- (void)show {
    __weak typeof(self) weakSelf = self;
  [UIView animateWithDuration:duration
                      animations:^{
       __block typeof(weakSelf) blokSelf = weakSelf;
       blokSelf.bottomView.frame = CGRectMake(0, height - blokSelf.bottomViewHeight, width, blokSelf.bottomViewHeight);
       [blokSelf.bottomView layoutIfNeeded];
     } completion:nil];
}

- (void)shapeLayerWith:(UIView *)view {
    UIBezierPath *maskPath =[UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(10,10)];
    CAShapeLayer *maskLayer =[[CAShapeLayer alloc] init];
    maskLayer.path = maskPath.CGPath;
    view.layer.mask = maskLayer;
}

#pragma mark - UITableViewDelegate,UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.dataArray.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataArray[section].count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellName"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellName"];
    }
    cell.textLabel.text = self.dataArray[indexPath.section][indexPath.row];
    cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
    cell.textLabel.textAlignment = NSTextAlignmentCenter;
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    if (self.selectItemCallBack) {
        if (indexPath.section == 0) {
            self.selectItemCallBack(indexPath.row);
        }else {
            self.selectItemCallBack(self.items.count);
        }
    }
    [self dismiss];
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    if (section == 0) {
        return 10;
    }else {
        return 0.01;
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 0.01;
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    if (section == 0) {
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 10)];
        view.backgroundColor = [UIColor colorWithRed:225/255.f green:225/255.f blue:225/255.f alpha:1.f];
        return view;
    }else {
        return [[UIView alloc] initWithFrame:CGRectZero];
    }
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

使用方法

 [SheetViewController showSheetViewControllerWith:@[@"1111",@"2222",@"3333",@"4444",@"5555",@"6666"]
                                  selectItemCallBack:^(NSInteger index) {
        NSLog(@"%ld",index);
    } showController:self];
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,892评论 0 13
  • BiuBiu,今天猎得一树黄毛丫头,柔柔的,暖暖的,把手机拿在手上卡嚓一刻,就像猎人瞄准抢咔嚓掉一树小黄“鸟”,嘻...
    几米2017阅读 211评论 0 0
  • 也不记得是哪一日了,总之,那次冬天的傍晚,我看到了夕阳,让我感触颇深的夕阳。 说起夕阳,我曾经听到过这样一...
    Luminous夜光君阅读 541评论 0 0
  • 再练习一遍丸子头少女,不知道这回中线有没有找对?现在越来越不会直接用秀丽笔画了,草图越来越详细,这个悖论如何破解?...
    莹莹微光阅读 163评论 0 0