iOS开发——无网占位图的实现

作者: 无夜之星辰 | 来源:发表于2016-11-05 22:12 被阅读4233次
T-ara—孝敏

先来看一下实际效果:

效果.gif

为什么要使用无网占位图?

为了更好地用户体验。难道没网的时候展示一个空白模板?当然,无网占位图也是一个APP最基本的功能只一。

原理简介:

viewWillAppear时判断是否有网,如果没网,展示无网占位图。点击无网占位图上的重新查看按钮,判断是否有网,如果没网,toast提示。如果有网,移除无网占位图,重新加载数据。

详细讲解:

  • 首先按照设计师的UI图封装一个无网占位图view:CQNoNetworkView,在构造方法里完成
- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        // UI搭建
        [self setUpUI];
    }
    return self;
}
   /** UI搭建 */
  - (void)setUpUI{
    self.backgroundColor = [UIColor whiteColor];
    
    // 404图片放中间
    UIImageView *noNetworkImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 125, 125)];
    noNetworkImageView.center = CGPointMake(self.width / 2, self.height / 2);
    [self addSubview:noNetworkImageView];
    noNetworkImageView.image = [UIImage imageNamed:@"404notfound"];
    
    // 重新查看按钮
    UIButton *checkButton = [[UIButton alloc]initWithFrame:CGRectMake(0, noNetworkImageView.maxY + 24, 115, 30)];
    checkButton.centerX = self.width / 2;
    [self addSubview:checkButton];
    [checkButton.titleLabel setFont:[UIFont systemFontOfSize:15]];
    checkButton.backgroundColor = [UIColor colorWithRed:0.00 green:0.76 blue:0.66 alpha:1.00];
    [checkButton setTitle:@"重新查看" forState:UIControlStateNormal];
    [checkButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [checkButton addTarget:self action:@selector(checkNetworkButtonClicked) forControlEvents:UIControlEventTouchUpInside];
    
    // 图片上面的两个label
    UILabel *label1 = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 20)];
    label1.text = @"刷新一下返回店铺!";
    label1.font = [UIFont systemFontOfSize:14];
    label1.textColor = [UIColor colorWithRed:0.00 green:0.77 blue:0.68 alpha:1.00];
    label1.backgroundColor = [UIColor clearColor];
    label1.textAlignment = NSTextAlignmentCenter;
    [label1 sizeToFit];
    label1.centerX = self.width / 2;
    label1.maxY = noNetworkImageView.y - 21;
    [self addSubview:label1];
    
    UILabel *label2 = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 15)];
    label2.text = @"您似乎迷路了";
    label2.font = [UIFont systemFontOfSize:19];
    label2.textColor = [UIColor colorWithRed:0.00 green:0.77 blue:0.67 alpha:1.00];
    label2.backgroundColor = [UIColor clearColor];
    label2.textAlignment = NSTextAlignmentCenter;
    [label2 sizeToFit];
    label2.centerX = self.width / 2;
    label2.maxY = label1.y - 12;
    [self addSubview:label2];
}

  • 处理“重新查看”按钮的逻辑,基本思路是:点击此按钮时,判断是否有网,如果仍旧没网,弹出toast提示用户;如果有网,移除此view,并且,让代理方执行相应代理方法,比如说,重新加载数据。
 /** 重新查看按钮点击 */
  - (void)checkNetworkButtonClicked{
    if ([DateUtil isNetWorkRunning]) {
        // 如果有网,view消失,并且让代理方执行代理方法
        for (CQNoNetworkView *view in [self getCurrentViewController].view.subviews) {
            if ([view isMemberOfClass:[CQNoNetworkView class]]) {
                [view removeFromSuperview];
            }
        }
        
        // 重新加载数据
        if ([self.delegate respondsToSelector:@selector(reloadData)]) {
            [self.delegate reloadData];
        }
    }else{
        // 如果没网,toast提示
        [CQHud showToastWithMessage:@"请检查你的网络连接"];
    }
}

  • 确定代理方法(点击“重新加载”按钮时,代理方执行的方法),我的是重新加载数据。
@protocol CheckNetworkDelegate <NSObject>
@optional

  /** 重新加载数据 */
  - (void)reloadData;

@end

  /** 无网络时展示的view */
@interface CQNoNetworkView : UIView

@property (nonatomic,weak) id<CheckNetworkDelegate> delegate;

@end

  • 确定代理方。代理方就是执行“重新加载数据”的对象。由于每个viewController都需要在无网时展示无网占位图,所以代理方可以设置为项目的BaseViewController(不要告诉我,你的项目里没有基类😅)
@interface BaseViewController ()<CheckNetworkDelegate>

在基类里实现重新加载数据,当然,需要由子类重写,不过如果你的项目架构的比较好,所有viewcontroller的获取数据的方法的方法名都一样,那么就不需要再由子类重写了:

/** 重新加载数据,由子类重写 */
     (void)reloadData{
    
}

同样在基类里实现弹出无网占位图的方法:

/** 显示无网络view */
- (void)showNoNetworkView{
    // 将导航栏和tabbar留出来
    CQNoNetworkView *noNetworkView = [[CQNoNetworkView alloc]initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight - 49)];
    noNetworkView.delegate = self;
    [self.view addSubview:noNetworkView];
}
  • 在基类的viewWillAppear:里判断网络情况:
// 如果没网,加载无网占位图
    if (![DateUtil isNetWorkRunning]) {
        // 无网加载无网站位图
        [self showNoNetworkView];
    }else{
        // 有网移除所有无网展位图
        for (CQNoNetworkView *view in self.view.subviews) {
            if ([view isMemberOfClass:[CQNoNetworkView class]]) {
                [view removeFromSuperview];
            }
        }
    }
  • 最后,在你的子类里重写“重新加载数据”方法即可:
- (void)reloadData{
    [self getData];
}

总结

此功能主要是代理和基类的运用,合理使用基类能让你少些很多代码。当然有些APP可能不仅有一种网络占位图,这个时候在子类里重写基类里的showNoNetworkView方法即可。以上是我对此功能的一些个人看法,只是简单的实现了这个功能,具体项目中还是要根据项目需求进行必要修改和优化的。但是,思路基本上不变。欢迎各位看官提出意见或建议。

补充两个更加优雅和强大的Demo

UITableView空数据占位图
适用于任何场景的通用占位图

相关文章

网友评论

  • 我是C:多个界面怎么统一处理
    无夜之星辰:@嘴爷 可以,这个是对view的封装
    嘴爷:https://github.com/dzenbot/DZNEmptyDataSet
    无夜之星辰:每个界面继承基类,基类里面写好这个方法。
  • 爱阿爸的阿龙龙:码走 借用下 嘻嘻
    无夜之星辰:@爱阿爸的阿龙龙868 :sweat_smile:
  • 十一岁的加重:顶图好漂亮,还 有没有类似 的啊
    无夜之星辰:@十一岁的加重 去我的主页,你会看到很多类似的:smile:
  • Joy___:妹子可以
  • 柳骏:想要你这个小demo的源码,有提供github下载网址吗:blush:
    无夜之星辰:https://github.com/wyzxc/CQPlaceholderView
    https://github.com/wyzxc/TableViewNoContentView
    抱歉来晚了:sweat_smile:
  • humanff:[DateUtil isNetWorkRunning]这个方法能看下怎么写
    无夜之星辰:@humanff 在APPDelegate里面就把监控开启
    humanff:@无夜之星辰 这个Reachability类是异步的把
    无夜之星辰:@humanff 这就是一个判断是否有网络的。
    + (BOOL)isNetWorkRunning{
    BOOL isExistenceNetwork=YES;
    Reachability *r = [Reachability reachabilityWithHostName:@"www.apple.com"];//auto-view.cn/iphone
    switch ([r currentReachabilityStatus]) {
    case NotReachable:
    isExistenceNetwork=NO;
    break;
    case ReachableViaWWAN:
    //使用3G/GPRS网络
    isExistenceNetwork=YES;
    break;
    case ReachableViaWiFi:
    //使用WiFi网络
    isExistenceNetwork=YES;
    break;
    }
    return isExistenceNetwork;
    }
  • 向钱冲啊:直接判断数据源为空不也可以么?如果是tableview和collectionView的话直接backgroundview=自定义view占位图?
    无夜之星辰:@向钱冲啊 木有缓存:sweat_smile:
    向钱冲啊:@无夜之星辰 可是楼主大大,我觉得数据源为空才是标准啊。为什么要显示占位图,不就是界面没数据才显示占位图的么?就算没网,可以我有缓存,这时候没必要显示占位图啊。这才是正常套路吧。 :sweat:
    无夜之星辰:@向钱冲啊 数据源为空,不一定代表没网。建议还是按照正常的套路来。
  • qiongyong:图片可以的 :smile:
    无夜之星辰:@qiongyong 孝敏,必须可以:sunglasses:
  • 男人宫:兄弟,demo也整出来啊 :smiley:
    男人宫:@无夜之星辰 我也想做你这样的效果,但我项目中确实没用你说的基类,你所说的基类,就是所有的VC都要继承的这个类吧,所以有点懵逼,那我该怎么处理呢
    男人宫:@无夜之星辰 写的不错,必须支持,不过就是少个demo,再有个demo就堪称完美 :stuck_out_tongue_winking_eye:
    无夜之星辰:@ios小霸王 我记得你,你是第一个关注我的人:smile:
  • FR_Zhang:这个跟SDWebImage的placeholderImage有什么区别吗
    无夜之星辰:@FR_Zhang 我这个占位图实际上是一个带特定功能的自定义view,而不是图片:smile:
    FR_Zhang:@无夜之星辰 因为绝大多数的图片缓存采用sd。sd有个展位图的方法。我主要是想知道。这个展位图 和sd的展位图有何区别
    无夜之星辰:@FR_Zhang 我实在不清楚这个跟SD有什么联系:sweat_smile:
  • 七里小晴天:图片不错
    无夜之星辰:@七里小晴天 访问量+1:sweat_smile:
  • 超_iOS:还有这东西,一直没意识到
    无夜之星辰:@_超 这东西不能忽略掉哦:smile:
  • macfai:赞一个,楼主能把demo共享一下吗?多谢:smile:
    无夜之星辰:demo已添加:sweat_smile:
    macfai:@无夜之星辰 好吧,:smile:
    无夜之星辰:@macfai 汗,代码都那么详细咯:sweat_smile:
  • 钱刀为:好得很
    无夜之星辰:@南人在外 四川人:sweat_smile:

本文标题:iOS开发——无网占位图的实现

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