UIcollectionView实现类似于超级课程表界面

想法和思路

  在翻阅了网上的关于课程表的想法,发现感觉都是很冗余,很繁琐,感觉可以借鉴的地方很少,因此自己不才,自己思考了一番,感觉实现效果还不错,性能还好。具体思路如下:

  将UIcollectionView设置为横向滑动,使得每个cell尺寸都等于屏幕的尺寸。那么在左右滚动的时候就能进行界面复用,不会消耗太多的性能。那么考虑到一个界面的上下滑动而言,自然想到了采用UIScrollView进行滚动。那么此时观察到后端给出来的课程表数据为下:

为了能够实现课程信息能够一一显示在scrollview上面,那么观察到后台的数据中week starttime endtime,就可以确定出来课程的位置,然后进行显示即可。

实现效果如下:

具体代码的实现如下(只是大致列出相应的函数,没有很详细的代码,末尾给出完整代码):

设置UIcollectionView

因为本博客是从app开发中抽取出来的,因此当前Window的rootViewController并不是UIcollectionViewController,不过差的不是很多,所以没有进行修改,然后直接拿过来了。

-(void)setUpUIAndAddGesture {
//    调用category得到当前开学的周数
    self.currentWeek = ceil([NSDate distanceFromOneDayToNow:@"2019-02-25 00:00:00"]/7.0);
//    添加KVO进行监测当前周数发生改变,切换界面
    [self addObserver:self forKeyPath:@"currentWeek" options:NSKeyValueObservingOptionNew context:nil];
    //    添加collectionview
    UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init];
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    
    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, NAVA_MAXY, SCREEN_WIDTH, SCREEN_HEIGHT-NAVA_MAXY-self.tabBarController.tabBar.frame.size.height) collectionViewLayout:layout];
    self.collectionView.backgroundColor = [UIColor whiteColor];
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    self.collectionView.pagingEnabled = YES;
    [self.collectionView registerClass:[SWUCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
    self.collectionView.showsHorizontalScrollIndicator = NO;
    [self.view addSubview:self.collectionView];
}

设置UIcollectionViewController的数据源和代理

#pragma mark <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return WEEK_COUNTS;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    SWUCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
    [cell.scrollerView setData:self.dataArray[indexPath.row]];
    return cell;
}

#pragma mark ------ UICollectionViewDelegate ------
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    self.startContentOffsetX = self.collectionView.contentOffset.x;
}

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
//    用于判断左右滑动
    if  (self.collectionView.contentOffset.x > _startContentOffsetX) {
        //                NSLog(@"右滑");
        ++self.currentWeek;
    }else if (self.collectionView.contentOffset.x < _startContentOffsetX) {
        //                NSLog(@"左滑");
        --self.currentWeek;
    }else {
        //                NSLog(@"到达开头或者结尾");
    }
}

自定义UIcollectionViewCell类

此时的scollerview是自定义出来的scrollerview的类视图

@implementation SWUCollectionViewCell

-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        self.scrollerView = [[SWUScrollview alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        [self addSubview:_scrollerView];
    }
    return self;
}
//调整cell中dscrollerview的偏移
-(void)prepareForReuse {
    self.scrollerView.contentOffset = CGPointMake(0, 0);
}

此时已经设置好UIcollectionViewController了,然后考虑到下拉框问题,进行选择周数,那么此时还是在界面布局的函数中进行设置,如下:

编写选择周数的UISrollView

@interface SWUWeekSelectView ()
/** 选中的button  */
@property (nonatomic,strong) SWULabel * selectBtn;
@end

@implementation SWUWeekSelectView

-(instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor colorWithRed:245/255.0 green:245/255.0 blue:245/255.0 alpha:1.0];
        self.showsHorizontalScrollIndicator = NO;
        [self addSelectWeekButton];
    }
    return self;
}

-(void)addSelectWeekButton {
    self.contentSize = CGSizeMake(WEEK_COUNTS*WEEK_SCROLLERVIEW_HEIGHT, WEEK_SCROLLERVIEW_HEIGHT);
    for (int i = 0; i < WEEK_COUNTS; i++) {
        SWULabel * weekBtn = [[SWULabel alloc] initWithFrame:CGRectMake(i*WEEK_SCROLLERVIEW_HEIGHT+WEEK_SCROLLERVIEW_HEIGHT*0.2, WEEK_SCROLLERVIEW_HEIGHT*0.1, WEEK_SCROLLERVIEW_HEIGHT*0.8, WEEK_SCROLLERVIEW_HEIGHT*0.8)];
        weekBtn.layer.cornerRadius =  weekBtn.frame.size.width*0.5;
        weekBtn.backgroundColor = UNSELECT_COLOR;
        weekBtn.tag = i+1;
        weekBtn.userInteractionEnabled = YES;
        weekBtn.text = [NSString stringWithFormat:@"%d",i+1];
        [self addSubview:weekBtn];
    }
}

在Controller中设置选择周数视图

-(void)setUpUIAndAddGesture {
    //    添加修改周课表的scrollerview
    self.weekScrollerView = [[SWUWeekSelectView alloc] initWithFrame:CGRectMake(0, CGRectGetMinY(self.collectionView.frame)-WEEK_SCROLLERVIEW_HEIGHT, SCREEN_WIDTH, WEEK_SCROLLERVIEW_HEIGHT)];
    for (UIView * view in _weekScrollerView.subviews) {
        if ([view isKindOfClass:[SWULabel class]]) {
            SWULabel * weekBtn = (SWULabel *)view;
            UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(btnBackGroundSelected:)];
            [weekBtn addGestureRecognizer:tap];
        }
    }
    [self.view addSubview:_weekScrollerView];
    
    
    //    设置导航栏标题
    self.navTitleView = [[SWUNavTitleView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH-100, NAVA_HEIGHT)];
    self.navigationItem.titleView = _navTitleView;
    //    给导航栏的下拉图片添加点击手势
    UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showWeekSelectView)];
    [_navTitleView.weekDeirView addGestureRecognizer:tap];
}

设置课程表视图的课程显示

@interface SWUScrollview ()
/** 日期数组  */
@property (nonatomic,strong) NSArray * dateArray;
/** 数据数组  */
@property (nonatomic,strong) NSArray * dataArray;
/** 显示详细信息  */
@property (nonatomic,strong) SWUAlertViewController * alert;
/** 传递数据  */
@property (nonatomic,strong) Weekitem * weekitem;
/** 点击手势  */
@property (nonatomic,strong) UITapGestureRecognizer * tap;
/** data  */
@property (nonatomic,strong) Data * data;
@end

@implementation SWUScrollview

-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        self.contentSize = CGSizeMake(frame.size.width, CELL_HW*14);
    }
    return self;
}

-(NSArray *)dateArray {
    if (!_dateArray) {
        _dateArray = [NSArray arrayWithObjects:@"周一",@"周二",@"周三",@"周四",@"周五",@"周六",@"周日", nil];
    }
    return _dateArray;
}

-(void)layoutSubviews {
//    删除之前存在的视图,保证数据的更新
    for (UIView * view in self.subviews) {
        [view removeFromSuperview];
    }
    [super layoutSubviews];
    //    删除之前的视图
    for (UIView * view in self.subviews) {
        [view removeFromSuperview];
    }
    //    添加星期几
    for (int i = 0; i < 7; i++) {
        SWULabel * label = [[SWULabel alloc] initWithFrame:CGRectMake(TIME_HW+i*CELL_HW, 0, CELL_HW, TIME_HW)];
        label.text = self.dateArray[i];
        label.textColor = [UIColor blackColor];
        [self addSubview:label];
    }
    //    添加时间课程
    for (int i = 0; i < 14; i++) {
        SWULabel * label = [[SWULabel alloc] initWithFrame:CGRectMake(0, TIME_HW+i*CELL_HW, TIME_HW, CELL_HW)];
        label.textColor = [UIColor blackColor];
        label.text = [NSString stringWithFormat:@"%d",i+1];
        label.backgroundColor = [UIColor colorWithRed:245/255.0 green:245/255.0 blue:245/255.0 alpha:1.0];
        [self addSubview:label];
    }
    //        读取数据,然后布局
    CGFloat realCell_HW = CELL_HW - 4;
    for (int i = 0;i < self.data.weekitem.count;i++) {
        self.weekitem = _data.weekitem[i];
        NSInteger count = _weekitem.endTime.integerValue-_weekitem.startTime.integerValue+1;;
        SWULabel * label = [[SWULabel alloc] initWithFrame:CGRectMake(TIME_HW+(_weekitem.day.integerValue-1)*CELL_HW, (_weekitem.startTime.integerValue-1)*CELL_HW+TIME_HW+2, realCell_HW,(CELL_HW-2)*count)];
        _weekitem.scrollerViewCount = i;
        label.weekitem = _weekitem;
//        label.
        UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showDetailInfo:)];
        [label addGestureRecognizer:tapGesture];
        label.userInteractionEnabled = YES;
        [self addSubview:label];
    }
}
-(void)showDetailInfo:(UITapGestureRecognizer *)sender {
    self.alert = [SWUAlertViewController alertControllerWithSWULabel:(SWULabel*)sender.view];
    //    添加Windows手势   点击空白处消失
    self.tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handletapPressGesture:)];
    [[UIApplication sharedApplication].keyWindow addGestureRecognizer:_tap];
    [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:_alert animated:_alert completion:nil];
}
//点击空白消失
-(void)handletapPressGesture:(UITapGestureRecognizer*)sender {
    CGPoint location = [sender locationInView:self];
    if (!CGRectContainsPoint(_alert.view.frame, location)) {
        [_alert dismissViewControllerAnimated:YES completion:nil];
        [[UIApplication sharedApplication].keyWindow removeGestureRecognizer:_tap];
    }
}
-(void)setData:(Data * )data {
    _data = data;
//    去除重叠时候发生的数据不能够更新的问题
    [self layoutSubviews];
}
@end

声明一下:由于课程表数据量并不大,因此在进行网络请求下来后,直接写入到plist文件中,然后利用MJExtension框架进行字典转模型,将数据保存到数据中,然后传递给每一个UIcollectionViewCell的scrollview上,进行课程信息的显示。

 

具体的代码在GitHub中:https://github.com/canoejun/openswu-ios-ng 的 Schedule 文件夹里的整个模块

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值