想法和思路
在翻阅了网上的关于课程表的想法,发现感觉都是很冗余,很繁琐,感觉可以借鉴的地方很少,因此自己不才,自己思考了一番,感觉实现效果还不错,性能还好。具体思路如下:
将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 文件夹里的整个模块