美文网首页
UITableView和UICollectionView 添加占

UITableView和UICollectionView 添加占

作者: 奋斗的遗忘人 | 来源:发表于2022-08-31 17:07 被阅读0次

    具体看代码: runtime实现
    只需一句代码搞定占位图, (占位图的显示需要调用 reloadData方法)

     self.tableView.setEmptyWith(UIImage.init(named: "nodata"), title: "暂无数据", offSet: 0) {[unowned self] in
                self.tableView.mj_header?.beginRefreshing()
            }
    

    创建scrollview 的category类如下图所示
    UIScrollView+Empty.h

    #import <UIKit/UIKit.h>
    NS_ASSUME_NONNULL_BEGIN
    /*
     1、使用时只需调用此方法,即可在调用SEL: reloadData 时自动判断是否展示空值界面
     2、更多定制可根据此实现方案进行相对应拓展  一般会对emptyView 进行定制操作
     
     exp:
     
     [_tableView setEmptyViewWithImage:[UIImage imageNamed:@"noresult"] title:@"某有数据啊,点击我再刷新一次看看?" eventBlock:^{
     NSLog(@"点击了,去刷新喽");
     }];
     
     */
    /**
     空值界面类型
    
     - EmptyImage: 只显示图片
     - EmptyTitle: 只显示文字
     - EmptyImageAndTitle: 显示图片和文字
     */
    typedef NS_ENUM(NSInteger,EmptyType) {
        EmptyImage,
        EmptyTitle,
        EmptyImageAndTitle
    };
    
    /**
     点击事件回调
     */
    typedef void(^EmptyEventBlock)(void);
    
    @interface UIScrollView (Empty)
    @property (nonatomic,strong)UIView *emptyView;
    @property (nonatomic,copy)EmptyEventBlock emptyEventBlock;
    /**
     设置空值界面
     根据传入内容决定展示风格:  图片、文字、文字和图片、是否添加点击事件
    
     @param image 展示图片 可为空
     @param title 展示文字 可为空
     @param block 点击事件block 可为空  为空则没有点击事件
     */
    - (void)setEmptyViewWithImage:(UIImage *_Nullable)image title:(NSString *_Nullable)title offSet:(CGFloat)offSet eventBlock:(EmptyEventBlock _Nullable)block;
    @end
    
    
    @interface UITableView (Empty)
    
    @end
    
    @interface UICollectionView (Empty)
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    UIScrollView+Empty.m

    #import "UIScrollView+Empty.h"
    #import <objc/runtime.h>
    #define BaseNavBarHeight ([[UIApplication sharedApplication] statusBarFrame].size.height+44)
    #define rgba(r,g,b,a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a]
    static NSString *kEmptyViewKey = @"EmptyViewKey";
    static NSString *kEmptyEventBlockKey = @"EmptyEventBlockKey";
    
    @implementation UIScrollView (Empty)
    
    - (void)setEmptyView:(UIView *)emptyView {
        objc_setAssociatedObject(self, &kEmptyViewKey, emptyView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    - (UIView *)emptyView {
        return objc_getAssociatedObject(self, &kEmptyViewKey);
    }
    
    - (void)setEmptyEventBlock:(EmptyEventBlock)emptyEventBlock {
        objc_setAssociatedObject(self, &kEmptyEventBlockKey, emptyEventBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    - (EmptyEventBlock)emptyEventBlock {
        return objc_getAssociatedObject(self, &kEmptyEventBlockKey);
    }
    
    - (void)setEmptyViewWithImage:(UIImage *_Nullable)image title:(NSString *_Nullable)title offSet:(CGFloat)offSet eventBlock:(EmptyEventBlock _Nullable)block {
        if (!self.emptyView) {
            
            EmptyType type;
            if (image && !title) {
                type = EmptyImage;
            }else if (!image && title) {
                type = EmptyTitle;
            }else if (image && title) {
                type = EmptyImageAndTitle;
            }else{
                NSLog(@"参数错误,不能使用此功能");
                return;
            }
            
            UIButton *emptyBtn = [UIButton buttonWithType:UIButtonTypeCustom];
            block ? (emptyBtn.enabled = YES) : (emptyBtn.enabled = NO);
            (emptyBtn.enabled = YES) ? [emptyBtn addTarget:self action:@selector(emptyClick:) forControlEvents:UIControlEventTouchUpInside]:nil;
            (emptyBtn.enabled = YES) ? (self.emptyEventBlock = block) : nil;
            
            CGFloat ksScreenWidth = [UIScreen mainScreen].bounds.size.width;
            CGFloat ksScreenHeight = [UIScreen mainScreen].bounds.size.height;
            switch (type) {
                case EmptyImage:
                {
                    emptyBtn.frame = CGRectMake((ksScreenWidth-image.size.width)/2, (ksScreenHeight - image.size.height)/2 - BaseNavBarHeight + offSet, image.size.width, image.size.height);
                    
                    [emptyBtn setImage:image forState:UIControlStateNormal];
                }
                    break;
                case EmptyTitle:
                {
                    CGRect titleRect = [title boundingRectWithSize:CGSizeMake(ksScreenWidth, 20) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:16.0f],NSFontAttributeName, nil] context:nil];
                    emptyBtn.frame = CGRectMake((ksScreenWidth-titleRect.size.width)/2, (ksScreenHeight-titleRect.size.height)/2 + offSet, titleRect.size.width, titleRect.size.height);
                    [emptyBtn setTitle:title forState:UIControlStateNormal];
                    [emptyBtn setTitleColor:rgba(143, 143, 143, 1) forState:UIControlStateNormal];
                }
                    break;
                case EmptyImageAndTitle:
                {
                    CGFloat btnWidth = 0;
                    CGFloat btnHeight = 0;
                    UIFont *titleFont = [UIFont systemFontOfSize:16.0f];
                    CGRect titleRect = [title boundingRectWithSize:CGSizeMake(ksScreenWidth, 20) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:[NSDictionary dictionaryWithObjectsAndKeys:titleFont,NSFontAttributeName, nil] context:nil];
                    titleRect.size.width <= image.size.width ? (btnWidth = image.size.width) : (btnWidth = titleRect.size.width);
                    btnHeight = image.size.height + titleRect.size.height + 10;
                    emptyBtn.frame = CGRectMake((ksScreenWidth-btnWidth)/2, (ksScreenHeight-btnHeight)/2 - BaseNavBarHeight + offSet, btnWidth, btnHeight);
                    [emptyBtn setImage:image forState:UIControlStateNormal];
                    [emptyBtn setTitle:title forState:UIControlStateNormal];
                    [emptyBtn setTitleColor:rgba(143, 143, 143, 1) forState:UIControlStateNormal];
                    [emptyBtn setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 30, -titleRect.size.width)];
                    [emptyBtn setTitleEdgeInsets:UIEdgeInsetsMake(btnHeight-20, -image.size.width, 0, 0)];
                    emptyBtn.titleLabel.font = titleFont;
                }
                    break;
                default:
                    break;
            }
            self.emptyView = emptyBtn;
            self.emptyView.hidden = YES;
            [self addSubview:self.emptyView];
        }
        [self bringSubviewToFront:self.emptyView];
    }
    
    /// 更新界面,是否展示空值视图
    - (void)refreshEmptyView {
        NSInteger section = 1;
        NSInteger rows = 0;
        if ([self isKindOfClass:[UITableView class]]) {
            
            UITableView *tableView = (UITableView *)self;
            if (tableView.dataSource != nil && [tableView.dataSource respondsToSelector:@selector(tableView:numberOfRowsInSection:)]) {
                
                if ([tableView.dataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) {
                    section = [tableView.dataSource numberOfSectionsInTableView:tableView];
                }
                for (int i = 0; i < section; i++) {
                    rows += [tableView.dataSource tableView:tableView numberOfRowsInSection:i];
                }
            }
        }else if ([self isKindOfClass:[UICollectionView class]]) {
            
            UICollectionView *collectionView = (UICollectionView *)self;
            if (collectionView.dataSource != nil && [collectionView.dataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) {
                
                if ([collectionView.dataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]) {
                    section = [collectionView.dataSource numberOfSectionsInCollectionView:collectionView];
                }
                for (int i = 0; i < section; i++) {
                    rows += [collectionView.dataSource collectionView:collectionView numberOfItemsInSection:i];
                }
            }
        }
        
        if (rows == 0) {
            self.emptyView.hidden = NO;
            [self bringSubviewToFront:self.emptyView];
        }else{
            self.emptyView.hidden = YES;
            return;
        }
    }
    
    #pragma mark -- action
    
    - (void)emptyClick:(UIButton *)sender {
        if (self.emptyEventBlock) {
            self.emptyEventBlock();
        }
    }
    
    #pragma mark -- swizzing
    + (void)hookClass:(Class)classObject originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
        Class class = classObject;
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        if (didAddMethod) {
            originalMethod = class_getInstanceMethod(class, originalSelector);
        }
        method_exchangeImplementations(swizzledMethod, originalMethod);
    }
    @end
    
    @implementation UITableView (Empty)
    // 加载完数据的标记属性名
    static NSString *const kRLTableViewPropertyInitFinish = @"kRLTableViewPropertyInitFinish";
    
    /**
     设置已经加载完成的数据
     */
    - (void)setIsInitFinish:(BOOL)finish{
        objc_setAssociatedObject(self, &kRLTableViewPropertyInitFinish, @(finish), OBJC_ASSOCIATION_ASSIGN);
    }
    
    /**
     是否已经加载完成数据
     */
    - (BOOL)isInitFinish{
        id obj = objc_getAssociatedObject(self, &kRLTableViewPropertyInitFinish);
        return [obj boolValue];
    }
    
    + (void)load {
        [super load];
        [self hookClass:[self class] originalSelector:@selector(reloadData) swizzledSelector:@selector(customReloadData)];
    }
    - (void)customReloadData {
        [self customReloadData];
        //忽略第一次加载
        if (![self isInitFinish]) {
            [self setIsInitFinish:YES];
            return;
        }
        [self refreshEmptyView];
    }
    
    @end
    
    @implementation UICollectionView (Empty)
    // 加载完数据的标记属性名
    static NSString *const kRLCollectionViewPropertyInitFinish = @"kRLCollectionViewPropertyInitFinish";
    /**
     设置已经加载完成的数据
     */
    - (void)setIsInitFinish:(BOOL)finish{
        objc_setAssociatedObject(self, &kRLCollectionViewPropertyInitFinish, @(finish), OBJC_ASSOCIATION_ASSIGN);
    }
    
    /**
     是否已经加载完成数据
     */
    - (BOOL)isInitFinish{
        id obj = objc_getAssociatedObject(self, &kRLCollectionViewPropertyInitFinish);
        return [obj boolValue];
    }
    
    + (void)load {
        [super load];
        [self hookClass:[self class] originalSelector:@selector(reloadData) swizzledSelector:@selector(customReloadData)];
    }
    
    - (void)customReloadData {
        [self customReloadData];
        
        //忽略第一次加载
        if (![self isInitFinish]) {
            return;
        }
        
        [self refreshEmptyView];
    }
    @end
    

    相关文章

      网友评论

          本文标题:UITableView和UICollectionView 添加占

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