iOS开发造轮子 | Loading图

作者: Lol刀妹 | 来源:发表于2017-08-12 15:46 被阅读2360次
    solo歌手 iu

    造这个轮子的原因

    几乎每个app都有loading图,虽然有SVProgressHUDMBProgressHUD这些非常优秀的三方,但我还是觉得要自己会封装才是王道,毕竟:

    1. 直接拿来的不一定满足需求,尤其是产品迭代较快、需求比较奇葩的时候
    2. 万一哪天这个三方没人维护了怎么办?还是用自己的踏实

    效果演示

    效果演示.gif

    分析loading图

    一般说来,loading图就是一个覆盖全屏的自定义view,并且你不可能同时看到两个loading图,所以loading图是单例。用得最多的场景是请求数据的时候展示,请求数据完成就移除。
    根据我有限的经验,loading图往往需要满足这个需求:

    可控的用户交互。

    比如说,用户支付的时候,这个时候我们是不希望用户进行任何操作的。另一种情况,用户跳转到一个新页面,这个页面请求数据展示loading图,loading图挡住了返回按钮,从用户的角度来看,用户是希望可以随时点击返回按钮返回上一页的,而不是只能等着数据加载完成后才能进行操作。(类似于我demo演示的情况)

    功能实现

    1.文件说明

    CQLoadingView是对loading图的封装;
    CQHUD是对loading图的管理和控制。

    2.封装loading图view:CQLoadingView

    .h文件

    #import <UIKit/UIKit.h>
    
    @interface CQLoadingView : UIView
    
    /** loading信息 */
    @property (nonatomic, copy) NSString *loadingInfo;
    
    /** loading图单例 */
    + (instancetype)sharedInstance;
    
    @end
    

    .m文件

    #import "CQLoadingView.h"
    #import <Masonry.h>
    
    @implementation CQLoadingView{
        /** loading信息label */
        UILabel *_loadingInfoLabel;
    }
    
    static CQLoadingView *loadingView;
    
    #pragma mark - loading图单例
    /** loading图单例 */
    + (instancetype)sharedInstance {
        if (loadingView == nil) {
            loadingView = [[CQLoadingView alloc] init];
        }
        return loadingView;
    }
    
    #pragma mark - 构造方法
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            self.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.2];
            //------- loading imageView -------//
            UIImageView *loadingImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 45, 45)];
            [self addSubview:loadingImageView];
            loadingImageView.image = [UIImage imageNamed:@"loading_00000"];
            NSMutableArray *imageArray = [NSMutableArray array];
            for (int i = 0; i < 15; i ++) {
                NSString *imageName = [NSString stringWithFormat:@"loading_%05d",i];
                [imageArray addObject:[UIImage imageNamed:imageName]];
            }
            loadingImageView.animationImages = imageArray;
            loadingImageView.animationDuration = 0.5;
            loadingImageView.animationRepeatCount = 0;
            [loadingImageView startAnimating];
            [loadingImageView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.center.mas_equalTo(self);
                make.size.mas_equalTo(CGSizeMake(45, 45));
            }];
            
            //------- 说明文本 -------//
            _loadingInfoLabel = [[UILabel alloc] init];
            [self addSubview:_loadingInfoLabel];
            _loadingInfoLabel.textAlignment = NSTextAlignmentCenter;
            _loadingInfoLabel.font = [UIFont systemFontOfSize:14];
            _loadingInfoLabel.textColor = [UIColor redColor];
            [_loadingInfoLabel mas_makeConstraints:^(MASConstraintMaker *make) {
                make.centerX.mas_equalTo(loadingImageView);
                make.top.mas_equalTo(loadingImageView.mas_bottom).mas_offset(20);
                make.height.mas_equalTo(18);
            }];
        }
        return self;
    }
    
    #pragma mark - 赋值loading说明信息
    /** 赋值loading说明信息 */
    - (void)setLoadingInfo:(NSString *)loadingInfo{
        _loadingInfo = loadingInfo;
        _loadingInfoLabel.text = _loadingInfo;
    }
    
    @end
    

    封装loading图view很常规,根据产品需求搭建UI即可,建议用自动布局。

    3.对loading图的管理和控制:CQHUD

    .h文件

    #pragma mark - 展示loading图
    /** 展示loading图 */
    + (void)showLoading;
    
    
    #pragma mark - 展示带说明信息的loading图
    /**
     带说明信息loading图
     
     @param message 说明信息
     */
    + (void)showLoadingWithMessage:(NSString *)message;
    
    
    #pragma mark - 移除loading图
    /** 移除loading图 */
    + (void)dismiss;
    
    
    #pragma mark - loading期间,允许或禁止用户交互
    /**
     loading期间,允许或禁止用户交互
     
     @param isEnable YES:允许 NO:禁止
     */
    + (void)enableUserInteraction:(BOOL)isEnable;
    
    
    #pragma mark - 展示可控制用户交互的loading图
    /**
     展示可控制用户交互的loading图
     
     @param isEnable 是否允许用户交互
     */
    + (void)showLoadingWithEnableUserInteraction:(BOOL)isEnable;
    
    
    #pragma mark - 展示可控制用户交互并且带说明信息的loading图
    /**
     展示可控制用户交互并且带说明信息的loading图
     
     @param message 说明信息
     @param isEnable 是否允许用户交互
     */
    + (void)showLoadingWithMessage:(NSString *)message enableUserInteraction:(BOOL)isEnable;
    

    .m文件

    #pragma mark - 展示loading图
    /** 展示loading图 */
    + (void)showLoading {
        [CQHUD showLoadingWithMessage:nil];
    }
    
    #pragma mark - 展示带说明信息的loading图
    /**
     带说明信息loading图
    
     @param message 说明信息
     */
    + (void)showLoadingWithMessage:(NSString *)message {
        UIWindow * window = [[[UIApplication sharedApplication] delegate] window];
        [window addSubview:[CQLoadingView sharedInstance]];
        [CQLoadingView sharedInstance].loadingInfo = message;
        [[CQLoadingView sharedInstance] mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.mas_equalTo(UIEdgeInsetsMake(0, 0, 0, 0));
        }];
    }
    
    #pragma mark - 移除loading图
    /** 移除loading图 */
    + (void)dismiss {
        [[CQLoadingView sharedInstance] removeFromSuperview];
    }
    
    #pragma mark - loading期间,允许或禁止用户交互
    /**
     loading期间,允许或禁止用户交互
    
     @param isEnable YES:允许 NO:禁止
     */
    + (void)enableUserInteraction:(BOOL)isEnable {
        [CQLoadingView sharedInstance].userInteractionEnabled = !isEnable;
    }
    
    #pragma mark - 展示可控制用户交互的loading图
    /**
     展示可控制用户交互的loading图
    
     @param isEnable 是否允许用户交互
     */
    + (void)showLoadingWithEnableUserInteraction:(BOOL)isEnable {
        [CQHUD showLoading];
        [CQHUD enableUserInteraction:isEnable];
    }
    
    #pragma mark - 展示可控制用户交互并且带说明信息的loading图
    /**
     展示可控制用户交互并且带说明信息的loading图
    
     @param message 说明信息
     @param isEnable 是否允许用户交互
     */
    + (void)showLoadingWithMessage:(NSString *)message enableUserInteraction:(BOOL)isEnable {
        [CQHUD showLoadingWithMessage:message];
        [CQHUD enableUserInteraction:isEnable];
    }
    

    对loading图的管理和控制其实就是对那个单例对象进行处理。

    使用

    // 展示loading
    [CQHUD showLoading];
    // 禁止用户交互
    [CQHUD enableUserInteraction:NO];
    // 展示loading,说明信息:支付中
    [CQHUD showLoadingWithMessage:@"支付中"];
    // 展示loading并且允许用户交互
    [CQHUD showLoadingWithEnableUserInteraction:YES];
    // 展示loading提示“支付中”并且禁止用户交互
    [CQHUD showLoadingWithMessage:@"支付中" enableUserInteraction:NO];
    // 移除loading
    [CQHUD dismiss];
    

    demo

    实用小demo

    最后

    暂时还没有研究SVProgressHUDMBProgressHUD的源代码,等我练出6块腹肌就有时间研究了,希望有好心人可以打赏一元让我多买一个鸡蛋早日练出6块腹肌。

    相关文章

      网友评论

      • CampbellQi:SVP是单例的,MB不是单例的,各有利弊吧,如果你是加在window上的单例,如果在请求中返回页面,那此时你的loading依然存在,否则就得在所有页面消失处加dismiss方法。
      • 阿磁:单例是不是应该给manager啊?view不需要做单例吧?求指教。
        阿磁:@无夜之星辰 我的理由是我看别人的代码单例都是在manager里的:joy:
        我是个菜鸟,看到这儿跟别人不一样就问一问
        Lol刀妹:额,这个我倒没有考虑,当时我想的是确保loading图只有一个就可以了。想请教一下你把单例给manager的理由。
      • 小czy:iu 的演唱会上海 南京都看过了哟😘
        Lol刀妹:@小czy :sob:
        小czy: @无夜之星辰 这个不好说啊,往后几年的两国关系可能都不会太好
        Lol刀妹:@小czy 羡慕:unamused: IU下次来中国,还不知道要等多久。。。
      • VSCCW:美女不错。
        Lol刀妹:@VSCCW 她叫李知恩:smirk:
      • 迟明子:看了楼上各位的评论,还以为IU是个什么术语....特地百度了一下..
        Lol刀妹:@迟明子 怎么样?是不是瞬间心动了?:sunglasses:
      • Allan要做活神仙:我是来看图的~
        Lol刀妹:@Allan要做活神仙 可以的:smile:
      • 陆闪闪:IU大法好,作者厉害:smirk:
        Lol刀妹:@陆闪闪 IU大法,get
      • 我是一只攻城狮_ifYou:文不错.iu更不错:+1:
        Lol刀妹:@我是一只攻城狮_ifYou 都是冲着iu来的,看来我的眼光不错
      • Afer:师傅牛逼
      • 沙暴送葬:牛逼!我喜欢:heart_eyes:
        Lol刀妹:@沙暴送葬 有用就好:smile:
      • Lol刀妹:评论列表里面说666和牛逼的都是我的师傅:hamster:
      • CepheusSun:快健康师傅666
      • moonCoder:师傅牛逼
      • Joy___:图不错
        Lol刀妹:@Joy___ 一贯作风:sweat_smile:
        CepheusSun: @Joy___ 架构joy
      • 37e4dd6ddc60:星辰出品必非凡品,大佬带我飞

      本文标题:iOS开发造轮子 | Loading图

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