IT@程序员猿媛移动开发干货店码农的世界

IOS集合视图UICollectionView之王朝Demo

2019-04-20  本文已影响1人  星辰_入海

从本回开始,我们介绍集合视图的使用,以及对应的数据源和协议的使用,在本次Demo中将网页和表格视图一起回顾--本次的案例与之前的案例分析中都有使用网页的载入「直接载入网页,会使得线程阻塞,我们会在下一回文章中重点分析多线程的相关概念,并完善多线程处理网页的问题」

一.表格视图

- 单元格

IBook中每一本书都可以看做一个单元格,每个单元格中都含有一个imageView

- 节

节充分的体现集合视图的行数
二.表格视图的数据源协议和委托协议
提供每个节中的列数
提供节的个数「行数」
为某个单元格提供显示数据
为补充视图提供数据
选择单元格之后触发
取消选择单元格之后触发

案例「王朝」

效果图


图2--运行效果图
项目图

代码实现

分析:观察效果图,我们不难发现,总共有九个单元格,其中每一个节含有三个列,总共有三个节,同时每一个单元格都是有相应的图片设置,以及每个单元格下方都有标签的标志

首先,我们要创建一个通用的集合视图--创建一个新的viewController文件,在头文件中,我们定义一个公共的API,根据分析,每一个单元格就是一个UI视图,其中包含了UIImageView和UILabel两部分组成
@interface EventCollectionViewCell : UICollectionViewCell

@property (nonatomic,strong) UIImageView *imageView; //单元格图需要图片视图
@property (nonatomic,strong) UILabel *label; //还有标签

@end
接下来,我们需要初始化单元格中的图片视图,刚才提及每一个单元格视图都是一个单独的视图,但是它们不是UIView,因此没有ViewDidVIew()方法进行初始化,因此,我们采用initWithFrame进行初始化单元格视图
//因为集合视图没有viewDidView();
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //创建一个单元格
        CGFloat cellWidth = self.frame.size.width;
        
        CGFloat imageViewWidth = 101;
        CGFloat imageViewHeight = 101;
        CGFloat imageViewTopView = 15;
        
        //1.创建imageView
        self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake((cellWidth-imageViewWidth)/2, imageViewTopView, imageViewWidth, imageViewHeight)];
        [self addSubview:self.imageView];
        
        //2.创建一个标签
        CGFloat labelWidth = 101;
        CGFloat labelHeight = 16;
        CGFloat labelViewTopView = 120;
        
        self.label = [[UILabel alloc] initWithFrame:CGRectMake((cellWidth-labelWidth)/2, labelViewTopView, labelWidth, labelHeight)];
        self.label.textAlignment = NSTextAlignmentCenter;
        self.label.font = [UIFont systemFontOfSize:13];
        self.label.textColor = [UIColor whiteColor];
        [self addSubview:self.label];
    }
    return self;
}

分析:通过父类的构造方法来创建自己的构造方法,并返回,在构造方法当中,我们初始化了单元格以及标签,我们通过self.frame.size.width设置宽度是整个屏幕的宽度

通用的类封装后,我们需要导入自己制作好的属性列表plist文件 图3--属性列表文件

此处我们通过数组来存储plist文件的信息,并设置集合视图

@interface ViewController () <UICollectionViewDelegate,UICollectionViewDataSource,WKNavigationDelegate>
@property (nonatomic,strong) NSArray *events; //存储plist信息
@property (nonatomic,strong) UICollectionView *collectionView; //集合视图
@property (nonatomic,strong) WKWebView *webView;
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    //获取plist属性文件的内容
    NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"events" ofType:@"plist"];
    self.events = [[NSArray alloc] initWithContentsOfFile:plistPath];
    [self setupCollectionView]; //建立集合视图
}
- (void)setupCollectionView{
    //创建流式布局
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    //设置每个格子的大小
    layout.itemSize = CGSizeMake(80, 80);
    //设置整个collectionView的内边距
    layout.sectionInset = UIEdgeInsetsMake(15, 15, 30, 15);
    layout.headerReferenceSize = CGSizeMake(15, 15);
    layout.footerReferenceSize = CGSizeMake(10, 10);
    //当手机屏幕大于560时候则,重新绘制内边距sectionInset和每个格子的大小itemSize
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    if (screenSize.height > 568) {
        layout.itemSize = CGSizeMake(100, 100);
        layout.sectionInset = UIEdgeInsetsMake(15, 15, 20, 15);
        layout.headerReferenceSize = CGSizeMake(80, 80);
         layout.footerReferenceSize = CGSizeMake(20, 20);
    }
    //设置单元格之间的间距
    layout.minimumLineSpacing = 5;
    
    self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
    [self.collectionView registerClass:[EventCollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
    //设置屏幕背景
    UIImageView *imageBackgroundView=[[UIImageView alloc] initWithFrame:UIScreen.mainScreen.bounds];
    imageBackgroundView.image=[UIImage imageNamed:@"backImage"];
    self.collectionView.backgroundView = imageBackgroundView;
    self.collectionView.delegate = self; //协议
    self.collectionView.dataSource = self; //数据源
    
    [self.view addSubview:self.collectionView];
}

分析:我们通过创建集合视图中的流式布局进行初始化,定义了每个单元格的大小,以及上下宽度的大小,同时对于大屏设备提供了不同数值参数的转换,最后将设置好的流式布局添加到集合视图中。

最后,实现数据源协议和委托协议
#pragma mark -- 实现数据源
#define COL_NUM 3

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    //设置单元格的个数
    int num = [self.events count] % COL_NUM;
    
    if(num == 0){
        //奇数
        return [self.events count] / COL_NUM;
    }else{
        //偶数
        return [self.events count] / COL_NUM + 1;
    }
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    //section --> 节
    return COL_NUM;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    EventCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
    
    //计算events集合的下标索引
    NSInteger idx = indexPath.section * COL_NUM + indexPath.row;
    
    if (self.events.count <= idx) {
        return cell;
    }
    
    //利用字典存储属性列表
    NSDictionary *event = self.events[idx];
    cell.label.text = event[@"name"];
    cell.imageView.image = [UIImage imageNamed:event[@"image"]];
    return cell;
}

#pragma mark -- 协议
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    NSDictionary *event = self.events[indexPath.section * COL_NUM + indexPath.row];
    NSLog(@"select the collectionView is %@",event);
    [self setWebViewSetting:[event objectForKey:@"name"]];
}

- (void)setWebViewSetting:(NSString *)name{
    self.webView = [[WKWebView alloc] initWithFrame:CGRectMake((UIScreen.mainScreen.bounds.origin.x), (UIScreen.mainScreen.bounds.origin.y+20), UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height)];
    [self setURL:name];
    [self closeTheWebView];
    self.webView.navigationDelegate = self;
    [self.collectionView addSubview:self.webView];
}

- (void)closeTheWebView{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(0, UIScreen.mainScreen.bounds.origin.y+5, 50, 5);
    [button setTitle:@"Back" forState:UIControlStateNormal];
    [button addTarget:self
               action:@selector(closeTheWebViewButton:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.webView addSubview:button];
}

- (void)closeTheWebViewButton:(id)sender{
    [self.webView removeFromSuperview];
}
- (void)setURL:(NSString *)name{
    if ([name isEqualToString:@"秦朝"]) {
        NSString *urlPath = @"http://www.qulishi.com/qinchao/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"汉朝"]){
        NSString *urlPath = @"http://www.qulishi.com/hanchao/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"隋朝"]){
        NSString *urlPath = @"http://www.qulishi.com/suichao/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"唐朝"]){
        NSString *urlPath = @"http://www.qulishi.com/tangchao/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"元朝"]){
        NSString *urlPath = @"http://www.qulishi.com/yuanchao/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"明朝"]){
        NSString *urlPath = @"http://www.qulishi.com/mingchao/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"清朝"]){
        NSString *urlPath = @"http://www.qulishi.com/qingchao/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"民国"]){
        NSString *urlPath = @"http://www.qulishi.com/minguo/";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }else if([name isEqualToString:@"中华人民共和国"]){
        NSString *urlPath = @"http://www.gov.cn";
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }
}

- (void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
}

#pragma mark -- 网页协议
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
    NSLog(@"start.....");
    [self.webView configuration];
    [self.webView allowsBackForwardNavigationGestures];
    [self.webView backForwardList];
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
    NSLog(@"commit.....");
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    NSLog(@"finished.....");
}

- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{
    NSLog(@"error.....");
    if (error) {
        [self.collectionView willRemoveSubview:self.webView];
    }
}

分析:不关注网页设置部分,我们来看集合视图的协议部分

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    //设置集合视图节的个数
    int num = [self.events count] % COL_NUM;
    
    if(num == 0){
        //奇数
        return [self.events count] / COL_NUM;
    }else{
        //偶数
        return [self.events count] / COL_NUM + 1;
    }
}

此处,我们设置了集合视图节的个数,当与3进行取模运算时候,如果整除则为奇数,否则为偶数

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    //section --> 节
    return COL_NUM;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    EventCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
    
    //计算events集合的下标索引
    NSInteger idx = indexPath.section * COL_NUM + indexPath.row;
    
    if (self.events.count <= idx) {
        return cell;
    }
    
    //利用字典存储属性列表
    NSDictionary *event = self.events[idx];
    cell.label.text = event[@"name"];
    cell.imageView.image = [UIImage imageNamed:event[@"image"]];
    return cell;
}
图4--点击单元格运行结果

通过,返回COL_NUM设置一个节中含有单元格的数目,并且,通过下标的数据从刚才已经存储好的plist文件的数组中提取对应图片以及文本信息并设置给了self.imageView.image,使得单元格视图具有图片

总结:

在本次demo中,我们设置了网页导入,但是会阻碍进程的运行,使得设备运行时候会卡顿,因此,下一章节将会介绍多线程问题来解决UI更新和网络下载分别在主线程和子线程之间运行的多线程机制

上一篇下一篇

猜你喜欢

热点阅读