You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
445 lines
15 KiB
445 lines
15 KiB
1 year ago
|
//
|
||
|
// GWPCourseListView.m
|
||
|
// CourseList
|
||
|
//
|
||
|
// Created by GanWenPeng on 15/12/3.
|
||
|
// Copyright © 2015年 GanWenPeng. All rights reserved.
|
||
|
//
|
||
|
|
||
|
#import "GWPCourseListView.h"
|
||
|
|
||
|
#define MaxDay 7
|
||
|
|
||
|
|
||
|
@protocol CourseSort <Course>
|
||
|
@property (nonatomic, assign) NSUInteger sortIndex;
|
||
|
@end
|
||
|
|
||
|
@interface CourseCell : UITableViewCell
|
||
|
@property (nonatomic, strong) id<Course> course;
|
||
|
/** 分割线 */
|
||
|
@property (nonatomic, weak) UIView *sepLine;
|
||
|
@end
|
||
|
|
||
|
@implementation CourseCell
|
||
|
- (id)initWithCoder:(NSCoder *)aDecoder{
|
||
|
if (self = [super initWithCoder:aDecoder]) {
|
||
|
[self setup];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (instancetype)initWithFrame:(CGRect)frame{
|
||
|
if (self = [super initWithFrame:frame]) {
|
||
|
[self setup];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
|
||
|
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||
|
[self setup];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (void)setup{
|
||
|
UIView *sep = [[UIView alloc] init];
|
||
|
[self addSubview:sep];
|
||
|
sep.backgroundColor = RGBA(0, 0, 0, 0.07);
|
||
|
self.sepLine = sep;
|
||
|
|
||
|
self.backgroundColor = [UIColor clearColor];
|
||
|
self.textLabel.textAlignment = NSTextAlignmentCenter;
|
||
|
self.textLabel.font = [UIFont systemFontOfSize:12];
|
||
|
self.textLabel.numberOfLines = 0;
|
||
|
self.backgroundColor = [UIColor clearColor];
|
||
|
|
||
|
}
|
||
|
|
||
|
- (void)setCourse:(id<Course>)course{
|
||
|
_course = course;
|
||
|
if ([course nameAttribute] && [course courseName].length) {
|
||
|
self.textLabel.attributedText = [[NSAttributedString alloc] initWithString:[course courseName] attributes:[course nameAttribute]];
|
||
|
} else {
|
||
|
self.textLabel.text = course.courseName;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)layoutSubviews{
|
||
|
[super layoutSubviews];
|
||
|
self.sepLine.frame = CGRectMake(0, self.frame.size.height-1, self.frame.size.width, 1);
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
@interface GWPCourseListView ()<UITableViewDataSource, UITableViewDelegate>
|
||
|
/** 顶部选项卡 */
|
||
|
@property (nonatomic, weak) UIView *topBar;
|
||
|
/** 顶部选项卡的ContentView */
|
||
|
@property (nonatomic, weak) UIView *topBarContentView;
|
||
|
/** 顶部选项卡中的按钮 */
|
||
|
@property (nonatomic, strong) NSArray *topBarBtnArr;
|
||
|
|
||
|
/** 时间TableView */
|
||
|
@property (nonatomic, weak) UITableView *timeTableView;
|
||
|
|
||
|
/** 上下滚动的ScrollView */
|
||
|
@property (nonatomic, weak) UIScrollView *upDownScrollView;
|
||
|
|
||
|
/** 左右滚动的ScrollView */
|
||
|
@property (nonatomic, weak) UIScrollView *leftRightScrollView;
|
||
|
|
||
|
/** 课程Table列表 */
|
||
|
@property (nonatomic, strong) NSArray *courseTableArr;
|
||
|
|
||
|
/** 亮色集合 */
|
||
|
@property (nonatomic, strong) NSArray *lightColorArr;
|
||
|
|
||
|
/** 课程数据 */
|
||
|
@property (nonatomic, strong) NSArray<id<Course>> *courseDataArr;
|
||
|
@end
|
||
|
|
||
|
@implementation GWPCourseListView
|
||
|
#pragma mark - lazy
|
||
|
- (NSArray *)lightColorArr{
|
||
|
if (!_lightColorArr) {
|
||
|
_lightColorArr = @[
|
||
|
RGBA(39, 201, 155, 1),
|
||
|
RGBA(146, 196, 40, 1),
|
||
|
RGBA(253, 185, 46, 1),
|
||
|
RGBA(112, 161, 246, 1),
|
||
|
RGBA(246, 126, 140, 1),
|
||
|
RGBA(185, 140, 221, 1),
|
||
|
RGBA(30, 180, 235, 1),
|
||
|
RGBA(226, 112, 194, 1),
|
||
|
];
|
||
|
}
|
||
|
return _lightColorArr;
|
||
|
}
|
||
|
|
||
|
#pragma mark - init system
|
||
|
- (id)initWithCoder:(NSCoder *)aDecoder{
|
||
|
if (self = [super initWithCoder:aDecoder]) {
|
||
|
[self setup];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (instancetype)initWithFrame:(CGRect)frame{
|
||
|
if (self = [super initWithFrame:frame]) {
|
||
|
[self setup];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (void)setup{
|
||
|
/*=============================== 初始化变量 ==============================*/
|
||
|
_itemHeight = 50;
|
||
|
_timeTableWidth = 50;
|
||
|
_courseListWidth = 0;
|
||
|
_maxCourseCount = 8;
|
||
|
_selectedIndex = 0; // 1-->0
|
||
|
_topBarBgColor = [UIColor whiteColor];
|
||
|
self.backgroundColor = RGBA(245, 245, 245, 1);
|
||
|
|
||
|
/*=============================== 添加控件 ==============================*/
|
||
|
NSMutableArray *temp;
|
||
|
|
||
|
/** topBar */
|
||
|
UIView *topBar = [[UIView alloc] init];
|
||
|
topBar.backgroundColor = _topBarBgColor;
|
||
|
[self addSubview:topBar];
|
||
|
self.topBar = topBar;
|
||
|
|
||
|
/** topBarContentView */
|
||
|
UIView *topBarContentView = [[UIView alloc] init];
|
||
|
topBarContentView.backgroundColor = [UIColor clearColor];
|
||
|
topBarContentView.clipsToBounds = YES;
|
||
|
[topBar addSubview:topBarContentView];
|
||
|
self.topBarContentView = topBarContentView;
|
||
|
|
||
|
/** tabBarBtnArr */
|
||
|
temp = [NSMutableArray array];
|
||
|
for (int i=0; i<MaxDay; i++) {
|
||
|
UIButton *btn = [[UIButton alloc] init];
|
||
|
[btn addTarget:self action:@selector(topBarItemClick:) forControlEvents:UIControlEventTouchUpInside];
|
||
|
[btn setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
|
||
|
btn.titleLabel.font = [UIFont systemFontOfSize:14];
|
||
|
btn.tag = i+1;
|
||
|
[topBarContentView addSubview:btn];
|
||
|
[temp addObject:btn];
|
||
|
}
|
||
|
_topBarBtnArr = temp;
|
||
|
|
||
|
/** upDownScrollView */
|
||
|
UIScrollView *upDownScrollView = [[UIScrollView alloc] init];
|
||
|
upDownScrollView.showsVerticalScrollIndicator = NO;
|
||
|
upDownScrollView.bounces = NO;
|
||
|
[self addSubview:upDownScrollView];
|
||
|
self.upDownScrollView = upDownScrollView;
|
||
|
|
||
|
/** timeTableView */
|
||
|
UITableView *timeTableView = [[UITableView alloc] init];
|
||
|
timeTableView.backgroundColor = [UIColor clearColor];
|
||
|
[timeTableView registerClass:[CourseCell class] forCellReuseIdentifier:NSStringFromClass([CourseCell class])];
|
||
|
timeTableView.scrollEnabled = NO;
|
||
|
timeTableView.delegate = self;
|
||
|
timeTableView.dataSource = self;
|
||
|
[upDownScrollView addSubview:timeTableView];
|
||
|
self.timeTableView = timeTableView;
|
||
|
|
||
|
/** leftRightScrollView */
|
||
|
UIScrollView *leftRightScrollView = [[UIScrollView alloc] init];
|
||
|
leftRightScrollView.bounces = NO;
|
||
|
leftRightScrollView.showsHorizontalScrollIndicator = NO;
|
||
|
leftRightScrollView.delegate = self;
|
||
|
[upDownScrollView addSubview:leftRightScrollView];
|
||
|
self.leftRightScrollView = leftRightScrollView;
|
||
|
|
||
|
/** courseTableArr */
|
||
|
temp = [NSMutableArray array];
|
||
|
for (int i=0; i<MaxDay; i++) {
|
||
|
UITableView *table = [[UITableView alloc] init];
|
||
|
table.backgroundColor = [UIColor clearColor];
|
||
|
[table registerClass:[CourseCell class] forCellReuseIdentifier:NSStringFromClass([CourseCell class])];
|
||
|
table.delegate = self;
|
||
|
table.dataSource = self;
|
||
|
table.scrollEnabled = NO;
|
||
|
table.tag = i+1;
|
||
|
[leftRightScrollView addSubview:table];
|
||
|
[temp addObject:table];
|
||
|
}
|
||
|
_courseTableArr = [NSArray arrayWithArray:temp];
|
||
|
}
|
||
|
|
||
|
- (void)layoutSubviews{
|
||
|
[super layoutSubviews];
|
||
|
|
||
|
CGFloat width = self.frame.size.width;
|
||
|
CGFloat height = self.frame.size.height;
|
||
|
CGFloat courseW = _courseListWidth ? _courseListWidth : (width-_timeTableWidth)/(MaxDay+0.5-2);
|
||
|
CGFloat x,y,w,h;
|
||
|
|
||
|
_topBar.frame = CGRectMake(0, 0, courseW*(MaxDay+0.5)+_timeTableWidth, 30);
|
||
|
_topBarContentView.frame = CGRectMake(_timeTableWidth, 0, courseW*(MaxDay+0.5), 30);
|
||
|
|
||
|
for (int i=0; i<self.topBarBtnArr.count; i++) {
|
||
|
UIButton *btn = self.topBarBtnArr[i];
|
||
|
if (i>0) {
|
||
|
UIButton *preBtn = self.topBarBtnArr[i-1];
|
||
|
x = CGRectGetMaxX(preBtn.frame);
|
||
|
} else {
|
||
|
x = -_leftRightScrollView.contentOffset.x;
|
||
|
}
|
||
|
y=0;
|
||
|
if (btn.tag==_selectedIndex) {
|
||
|
w = 1.5*courseW;
|
||
|
} else {
|
||
|
w = courseW;
|
||
|
}
|
||
|
h = _topBarContentView.frame.size.height;
|
||
|
btn.frame = CGRectMake(x, y, w, h);
|
||
|
}
|
||
|
|
||
|
_upDownScrollView.frame = CGRectMake(0, CGRectGetMaxY(_topBar.frame), width, height-_topBar.frame.size.height);
|
||
|
_upDownScrollView.contentSize = CGSizeMake(0, _maxCourseCount*_itemHeight);
|
||
|
|
||
|
_timeTableView.frame = CGRectMake(0, 0, _timeTableWidth, _itemHeight*_maxCourseCount);
|
||
|
|
||
|
_leftRightScrollView.frame = CGRectMake(_timeTableWidth, 0, width-_timeTableWidth, _timeTableView.frame.size.height);
|
||
|
_leftRightScrollView.contentSize = CGSizeMake(courseW*(MaxDay+0.5), 0);
|
||
|
|
||
|
for (int i=0; i<self.courseTableArr.count; i++) {
|
||
|
UITableView *table = self.courseTableArr[i];
|
||
|
if (i>0) {
|
||
|
UITableView *preTable = self.courseTableArr[i-1];
|
||
|
x = CGRectGetMaxX(preTable.frame);
|
||
|
} else {
|
||
|
x = 0;
|
||
|
}
|
||
|
y=0;
|
||
|
if (table.tag==_selectedIndex) {
|
||
|
w = 1.5*courseW;
|
||
|
} else {
|
||
|
w = courseW;
|
||
|
}
|
||
|
h = _timeTableWidth*_itemHeight;
|
||
|
table.frame = CGRectMake(x, y, w, h);
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#pragma mark - setter
|
||
|
- (void)setCourseDataArr:(NSArray<id<Course>> *)courseDataArr{
|
||
|
__block NSUInteger cha = 0;
|
||
|
|
||
|
for (int i=0; i<=MaxDay; i++) {
|
||
|
NSPredicate *pre = [NSPredicate predicateWithBlock:^BOOL(id<Course> _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||
|
return evaluatedObject.dayIndex==i;
|
||
|
}];
|
||
|
NSArray<id<Course>> *enumCourses = [courseDataArr filteredArrayUsingPredicate:pre];
|
||
|
[enumCourses enumerateObjectsUsingBlock:^(id<Course> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||
|
obj.sortIndex = obj.startCourseIndex-cha;
|
||
|
cha = cha + obj.endCourseIndex - obj.startCourseIndex;
|
||
|
}];
|
||
|
cha = 0;
|
||
|
}
|
||
|
|
||
|
_courseDataArr = courseDataArr;
|
||
|
}
|
||
|
- (void)setDataSource:(id<GWPCourseListViewDataSource>)dataSource{
|
||
|
_dataSource = dataSource;
|
||
|
|
||
|
[self loadData];
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
- (void)setTopBarBgColor:(UIColor *)topBarBgColor{
|
||
|
_topBarBgColor = topBarBgColor;
|
||
|
|
||
|
self.topBar.backgroundColor = topBarBgColor;
|
||
|
|
||
|
}
|
||
|
|
||
|
#pragma mark - public
|
||
|
- (void)reloadData{
|
||
|
[self loadData];
|
||
|
}
|
||
|
|
||
|
#pragma mark - private
|
||
|
- (void)topBarItemClick:(UIButton *)btn{
|
||
|
_selectedIndex = btn.tag;
|
||
|
|
||
|
[self layoutSubviews];
|
||
|
}
|
||
|
|
||
|
- (void)loadData{
|
||
|
/*=============================== topBar ==============================*/
|
||
|
NSArray *temp = @[
|
||
|
@"周一",
|
||
|
@"周二",
|
||
|
@"周三",
|
||
|
@"周四",
|
||
|
@"周五",
|
||
|
@"周六",
|
||
|
@"周日"
|
||
|
];
|
||
|
for (int i=0; i<self.topBarBtnArr.count; i++) {
|
||
|
|
||
|
UIButton *btn = self.topBarBtnArr[i];
|
||
|
NSString *str = @"";
|
||
|
|
||
|
if ([_dataSource respondsToSelector:@selector(courseListView:titleInTopbarAtIndex:)]) {
|
||
|
str = [_dataSource courseListView:self titleInTopbarAtIndex:i];
|
||
|
} else {
|
||
|
str = temp[i];
|
||
|
}
|
||
|
|
||
|
NSDictionary *attr;
|
||
|
if ([_dataSource respondsToSelector:@selector(courseListView:titleAttributesInTopbarAtIndex:)]) {
|
||
|
attr = [_dataSource courseListView:self titleAttributesInTopbarAtIndex:i];
|
||
|
}
|
||
|
if (attr) {
|
||
|
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:str attributes:attr];
|
||
|
[btn setAttributedTitle:attrStr forState:UIControlStateNormal];
|
||
|
} else {
|
||
|
[btn setTitle:str forState:UIControlStateNormal];
|
||
|
}
|
||
|
|
||
|
UIColor *bgColor;
|
||
|
|
||
|
if ([_dataSource respondsToSelector:@selector(courseListView:titleBackgroundColorInTopbarAtIndex:)]) {
|
||
|
bgColor = [_dataSource courseListView:self titleBackgroundColorInTopbarAtIndex:i];
|
||
|
}
|
||
|
if (bgColor) {
|
||
|
btn.backgroundColor = bgColor;
|
||
|
} else {
|
||
|
btn.backgroundColor = [UIColor whiteColor];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*=============================== course ==============================*/
|
||
|
// for (UITableView *table in self.courseTableArr) {
|
||
|
// [table reloadData];
|
||
|
// }
|
||
|
NSString *msg = [NSString stringWithFormat:@"使用 %@ 必须实现“courseForCourseListView:”方法", self.class];
|
||
|
NSAssert([_dataSource respondsToSelector:@selector(courseForCourseListView:)], msg);
|
||
|
self.courseDataArr = [_dataSource courseForCourseListView:self];
|
||
|
[self.courseTableArr makeObjectsPerformSelector:@selector(reloadData)];
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma mark - UITableViewDataSource、Delegate
|
||
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
|
||
|
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||
|
tableView.backgroundColor = [UIColor clearColor];
|
||
|
return [tableView isEqual:self.timeTableView] ? _maxCourseCount :20;
|
||
|
}
|
||
|
|
||
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
|
||
|
CourseCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CourseCell class])];
|
||
|
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||
|
if ([tableView isEqual:self.timeTableView]) {
|
||
|
cell.textLabel.text = [NSString stringWithFormat:@"%zd", indexPath.row+1];
|
||
|
cell.backgroundColor = [UIColor clearColor];
|
||
|
cell.textLabel.textColor = [UIColor darkGrayColor];
|
||
|
return cell;
|
||
|
}
|
||
|
|
||
|
NSPredicate *pre = [NSPredicate predicateWithBlock:^BOOL(id<Course> _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||
|
return (tableView.tag==evaluatedObject.dayIndex) && (indexPath.row+1==evaluatedObject.sortIndex);
|
||
|
}];
|
||
|
id<Course> course = [[self.courseDataArr filteredArrayUsingPredicate:pre] firstObject];
|
||
|
|
||
|
cell.textLabel.textColor = [UIColor whiteColor];
|
||
|
cell.course = course;
|
||
|
UIColor *bgColor = [_dataSource courseListView:self courseTitleBackgroundColorForCourse:course];
|
||
|
cell.backgroundColor = course ? (bgColor ? bgColor : self.lightColorArr[arc4random_uniform((u_int32_t)self.lightColorArr.count)]) : [UIColor clearColor];
|
||
|
|
||
|
return cell;
|
||
|
}
|
||
|
|
||
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
|
||
|
if ([tableView isEqual:self.timeTableView]) return _itemHeight;
|
||
|
|
||
|
NSPredicate *pre = [NSPredicate predicateWithBlock:^BOOL(id<Course> _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||
|
return (tableView.tag==evaluatedObject.dayIndex) && (indexPath.row+1==evaluatedObject.sortIndex);
|
||
|
}];
|
||
|
id<Course> course = [[self.courseDataArr filteredArrayUsingPredicate:pre] firstObject];
|
||
|
|
||
|
if (course) {
|
||
|
return (course.endCourseIndex-course.startCourseIndex+1)*_itemHeight;
|
||
|
} else {
|
||
|
return _itemHeight;
|
||
|
}
|
||
|
// return _itemHeight*2;
|
||
|
// return course ? (course.endCourseIndex-course.startCourseIndex)*_itemHeight : _itemHeight;
|
||
|
}
|
||
|
|
||
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
|
||
|
if ([tableView isEqual:self.timeTableView]) return;
|
||
|
_selectedIndex = tableView.tag;
|
||
|
_selectedRow = indexPath.row+1;
|
||
|
|
||
|
//NSLog(@"%ld----%ld", _selectedIndex, _selectedRow);
|
||
|
|
||
|
[self layoutSubviews];
|
||
|
|
||
|
if ([_delegate respondsToSelector:@selector(courseListView:didSelectedCourse:)]) {
|
||
|
CourseCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
||
|
[_delegate courseListView:self didSelectedCourse:cell.course];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma mark - UIScrollViewDelegate
|
||
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
|
||
|
[self layoutSubviews];
|
||
|
}
|
||
|
|
||
|
@end
|