年年有"余"

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2849|回复: 0

[SAFoundation] 自定义UIActionSheet实现分享功能,一行代码搞定!

[复制链接]
  • TA的每日心情
    奋斗
    2022-12-13 21:26
  • 签到天数: 371 天

    [LV.9]以坛为家II

    发表于 2016-3-11 17:34:26 | 显示全部楼层 |阅读模式
    本帖最后由 Sian 于 2016-3-13 17:36 编辑

    1、先上图,有图好说话
    Simulator-Screen-Shot-2016年3月13日-下午5.35.17.jpg
    2、设置思路
    2.1、我希望这是一个View,并非控制器,节省开支;
    2.2、 这个View包含一个背景,一个面板,若干个按钮或标签;
    2.3、我希望实现的功能是视图展示+事件响应;
    2.4、希望无偶合性,并且一行代码搞定(能一行代码搞定的必定包含block);
    2.5、这若干个按钮最好是外面传进来,要不我怎么知道需要什么样的按钮?传一组图片?那文字呢?再传一组文字?如何对应?
    2.6、我希望开始调用的时候只要传按钮给你,结束后告诉我用户点了哪个按钮,其他的我都不想管(高度无偶封装),呵呵!
    2.7、调用时还最好是类方法,我不喜欢alloc;
    2.8、例如:+ (instancetype)sheetWithItems:(NSArray<__kindof UIButton *> *)items actionWithBlock:(SAActionSheetBlock)block
    3、基本调用
    [Objective-C] 纯文本查看 复制代码
    //
    //  ViewController.m
    //  Test
    //
    //  Created by 余西安 on 16/3/11.
    //  Copyright &#169; 2016年 Sian. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "SAActionSheet.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    /// 弹出分享面板
    - (IBAction)action:(UIButton *)sender
    {
        [SAActionSheet sheetWithItems:[self shareItems] actionWithBlock:^(UIButton *item, NSInteger index) {
            switch (index) {
                case 1: [self show:@"微信好友"]; break;
                case 2: [self show:@"朋友圈"]; break;
                case 3: [self show:@"微信收藏"]; break;
                case 4: [self show:@"QQ好友"]; break;
                case 5: [self show:@"QQ空间"]; break;
                default: break;
            }
        }];
    }
    /// 创建按钮数组
    - (NSArray *)shareItems
    {
        UIImage *image1 = [UIImage imageNamed:@"Action_Share.png"];
        UIImage *image2 = [UIImage imageNamed:@"Action_Moments.png"];
        UIImage *image3 = [UIImage imageNamed:@"Action_MyFavAdd.png"];
        UIImage *image4 = [UIImage imageNamed:@"Action_QQ.png"];
        UIImage *image5 = [UIImage imageNamed:@"Action_qzone.png"];
        UIButton *button1 = [UIButton buttonWithType:UIButtonTypeSystem];
        UIButton *button2 = [UIButton buttonWithType:UIButtonTypeSystem];
        UIButton *button3 = [UIButton buttonWithType:UIButtonTypeSystem];
        UIButton *button4 = [UIButton buttonWithType:UIButtonTypeSystem];
        UIButton *button5 = [UIButton buttonWithType:UIButtonTypeSystem];
        [button1 setBackgroundImage:image1 forState:UIControlStateNormal];
        [button2 setBackgroundImage:image2 forState:UIControlStateNormal];
        [button3 setBackgroundImage:image3 forState:UIControlStateNormal];
        [button4 setBackgroundImage:image4 forState:UIControlStateNormal];
        [button5 setBackgroundImage:image5 forState:UIControlStateNormal];
        [button1 setTitle:@"微信好友" forState:UIControlStateNormal];
        [button2 setTitle:@"朋友圈" forState:UIControlStateNormal];
        [button3 setTitle:@"微信收藏" forState:UIControlStateNormal];
        [button4 setTitle:@"QQ好友" forState:UIControlStateNormal];
        [button5 setTitle:@"QQ空间" forState:UIControlStateNormal];
        return @[button1, button2, button3, button4, button5];
    }
    // 附属方法,显示结果
    - (void)show:(NSString *)string
    {
        [[[UIAlertView alloc] initWithTitle:nil message:string delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil] show];
    }
    @end
    
    4、代码实现
    [Objective-C] 纯文本查看 复制代码
    //
    //  SAActionSheet.m
    //  fisher
    //
    //  Created by 余西安 on 16/3/10.
    //  Copyright &#169; 2016年 Sian. All rights reserved.
    //
    #define kSAActionSheetItemColumns    3      // 每行按钮数(纵列数)
    #define kSAActionSheetItemWidth      60     // 单个按钮长宽
    #define kSAActionSheetItemSpace      25     // 按钮上下之间间隔
    #define kSAActionSheetLabelHeight    25     // 按钮标签文字高度
    #define kSAActionSheetCancelHeight   50     // 取消按钮高度
    #import "SAActionSheet.h"
    @interface SAActionSheet ()
    
    @property (nonatomic, strong) UIView    *baseView;      // 按钮基础板
    @property (nonatomic, strong) NSArray   *items;         // 按钮数组
    @property (nonatomic, strong) NSArray   *labels;        // 按钮标签
    @property (nonatomic, strong) UIButton  *cancel;        // 取消按钮
    @property (nonatomic, copy) SAActionSheetBlock  block;  // 完成Block
    
    @end
    
    @implementation SAActionSheet
    
    + (instancetype)sheetWithItems:(NSArray<__kindof UIButton *> *)items actionWithBlock:(SAActionSheetBlock)block
    {
        SAActionSheet *sheet = [[self alloc] initWithItems:items actionWithBlock:block];
        return [sheet show];
    }
    
    - (instancetype)initWithItems:(NSArray<__kindof UIButton *> *)items actionWithBlock:(SAActionSheetBlock)block
    {
        if (self = [super init]){
            // 1、接收变量
            self.block = block;
            self.items = items;
            // 2、创建基础面板视图(动画升上来的那个白色面板,用来放分享按钮、标签等)
            self.baseView = [[UIView alloc] init];
            self.baseView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.9];
            [self addSubview:self.baseView];
            // 3、创建分享按钮及对应标签
            NSMutableArray *labelArray = [NSMutableArray array];
            for (int i = 0; i < items.count; i++) {
                // 3.1、遍历传进来的按钮数组,将每个按钮添加到baseView上,并序号添加tag标记
                UIButton *button = [items objectAtIndex:i];
                [button setTag:i + 1];
                [self.baseView addSubview:button];
                // 3.2、创建按钮标签,取出标签后将按钮上的文字删除掉,避免重复
                UILabel *label = [[UILabel alloc] init];
                label.font = [UIFont systemFontOfSize:11];
                label.textAlignment = NSTextAlignmentCenter;
                label.text = [button titleForState:UIControlStateNormal];
                [labelArray addObject:label];
                [self.baseView addSubview:label];
                // 3.3、添加按钮事件统一处理方法
                [button  setTitle:nil forState:UIControlStateNormal];
                [button addTarget:self action:@selector(buttonEven:) forControlEvents:UIControlEventTouchUpInside];
            }
            self.labels = labelArray;
            // 4、取消按钮并绑定相关事件
            self.cancel = [UIButton buttonWithType:UIButtonTypeSystem];
            [self.cancel addTarget:self action:@selector(hidden) forControlEvents:UIControlEventTouchUpInside];
            [self.cancel setBackgroundColor:[UIColor whiteColor]];
            [self.cancel setTitle:@"取消" forState:UIControlStateNormal];
            [self.cancel.titleLabel setFont:[UIFont systemFontOfSize:20]];
            [self.baseView addSubview:self.cancel];
            // 5、点击空白区域响应取消事件
            [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hidden)]];
        }
        return self;
    }
    /// 视图调整
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        // SAActionSheet Frame:背景大小
        self.frame = [[UIScreen mainScreen] bounds];
        /* BaseView Frame:基础视图尺寸
         rows: 为按钮总行数
         h: baseView视图的高 = (上下间隔高度 + 按钮高度 + 标签高度) * 行数 + 上下间隔高度 + 取消按钮高度
         w: baseView视图的宽 = 屏幕宽度
         */
        NSInteger rows = (self.items.count - 1) / kSAActionSheetItemColumns + 1;
        CGFloat h = rows * (kSAActionSheetItemWidth + kSAActionSheetItemSpace + kSAActionSheetLabelHeight) + kSAActionSheetItemSpace + kSAActionSheetCancelHeight;
        CGFloat w = self.bounds.size.width;
        self.baseView.bounds = CGRectMake(0, 0, self.bounds.size.width, h);
        /* Items Frame:按钮尺寸
         bw:  按钮宽度
         bh:  按钮高度
         sp:  按钮间隔 = (总宽度 - 按钮个数 * 按钮宽度)/ 间隔数
         */
        CGFloat bw = kSAActionSheetItemWidth;
        CGFloat bh = kSAActionSheetItemWidth;
        CGFloat sp = (w - bw * kSAActionSheetItemColumns) / (kSAActionSheetItemColumns + 1);
        for (UIButton *button in self.items) {
            NSInteger index = button.tag;   // 按钮序号
            NSInteger row = (index - 1) / kSAActionSheetItemColumns + 1;    // 行序号
            NSInteger col = (index - 1) % kSAActionSheetItemColumns + 1;    // 列序号
            // 按钮x值、y值
            CGFloat x = (col - 1) * bw + col * sp;
            CGFloat y = (row - 1) * (bh + kSAActionSheetLabelHeight) + row * kSAActionSheetItemSpace;
            button.frame = CGRectMake(x, y, bw, bh);
            // 在按钮下方设置相对应的标签,宽度与按钮相同,高度为预设定值
            UILabel *label = [self.labels objectAtIndex:index - 1];
            label.frame = CGRectMake(x, y + bh, bw, kSAActionSheetLabelHeight);
        }
        // 取消按钮在最下方,高度为50
        self.cancel.frame = CGRectMake(0, h - 50, w, kSAActionSheetCancelHeight);
    }
    
    /// 显示视图(弹出动画)
    - (SAActionSheet *)show
    {
        // 1、调整视图大小,添加到当前Windows窗口
        [self layoutSubviews];
        [[[[UIApplication sharedApplication] delegate] window] addSubview:self];
        // 2、将基础视图调整到屏幕最下方、背景设置透明
        CGFloat height = self.bounds.size.height;
        CGFloat w = self.baseView.bounds.size.width;
        CGFloat h = self.baseView.bounds.size.height;
        self.backgroundColor = [UIColor clearColor];
        self.baseView.center = CGPointMake(w * 0.5, height + h * 0.5);
        // 3、执行自下至上的推出及背景变半透明黑的动画
        [UIView animateWithDuration:0.25 animations:^{
            self.baseView.center = CGPointMake(w * 0.5, height - h * 0.5);
            self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
        }];
        return self;
    }
    
    /// 隐藏视图(退出释放)
    - (void)hidden
    {
        // 按键视图块整体下移至超出屏幕动画,背景变透明,动画结束后将视图从窗口移除
        CGFloat height = self.bounds.size.height;
        CGFloat w = self.baseView.bounds.size.width;
        CGFloat h = self.baseView.bounds.size.height;
        [UIView animateWithDuration:0.35 animations:^{
            self.baseView.center = CGPointMake(w * 0.5, height + h * 0.5);
            self.backgroundColor = [UIColor clearColor];
        } completion:^(BOOL finished) {
            [self removeFromSuperview];
        }];
    }
    
    /// 按钮事件转交给Block处理
    - (void)buttonEven:(UIButton *)button
    {
        // 将事件及触发事件的按钮序号转交出去,并取消视图
        if (self.block) self.block(button, button.tag);
        [self hidden];
    }
    @end
    
    5、Demo下载:
    游客,如果您要查看本帖隐藏内容请回复
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    手机版|小黑屋|Archiver|iOS开发笔记 ( 湘ICP备14010846号 )

    GMT+8, 2024-3-29 23:38 , Processed in 0.051559 second(s), 21 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表