需求:實(shí)現(xiàn)一個(gè)日歷顯示頁面如下:
左側(cè)刻度從早上9點(diǎn)開始,到晚上9點(diǎn)結(jié)束。以分鐘為單位。動(dòng)態(tài)給時(shí)間塊定位并分配空間。
測(cè)試數(shù)據(jù)一:
var events = [
{start: 30, end: 150},
{start: 540, end: 600},
{start: 560, end: 620},
{start: 610, end: 670}
];

測(cè)試數(shù)據(jù)二:
var events = [
{start: 30, end: 150},
{start: 540, end: 600},
{start: 550, end: 620},
{start: 560, end: 650},
{start: 630, end: 690},
];

測(cè)試數(shù)據(jù)三:
var events = [
{start:30,end:670},
{start:100,end:180},
{start:180,end:200},
{start:210,end:480},
{start:220,end:490},
{start:250,end:500},
{start:280,end:510},
{start:540,end:600},
{start:550,end:620},
{start:560,end:650},
{start:630,end:690},
{start:640,end:700},
];

思路:
(1)每一個(gè)待辦事項(xiàng)都是一個(gè)區(qū)間,而我們首先要確定的是事情最多的那一分鐘處于多少個(gè)區(qū)間內(nèi),以此來計(jì)算最小的時(shí)間塊寬度。
(2)確定了寬度最小的時(shí)間塊以后,剩下的時(shí)間塊平分剩下的寬度。
(3)首先想到的是遍歷從9:00--21:00的每一分鐘內(nèi)有幾個(gè)待辦事項(xiàng),需要遍歷12*60=720次,顯然這種做法太蠢了,我們只需要遍歷每個(gè)待辦事項(xiàng)開始時(shí)間點(diǎn)就行了。

步驟
(1)我們將每一個(gè)時(shí)間塊看成一個(gè)區(qū)間對(duì)象region,用一個(gè)數(shù)組regionArr讀入存放它們。
(2)再建立一個(gè)數(shù)組beginArr,存放每一個(gè)時(shí)間塊開始的時(shí)間點(diǎn),去掉重復(fù)的元素
(3)遍歷beginArr里的元素(開始時(shí)間點(diǎn)),得出包含該時(shí)間點(diǎn)的所有時(shí)間塊,放入數(shù)組,按照開始時(shí)間排序。最后將所有數(shù)組放入一個(gè)大數(shù)組crossRegionArr,按照數(shù)組內(nèi)的元素個(gè)數(shù)排序。
(4)遍歷crossRegionArr,取出數(shù)組crossRegionArr[0],畫出crossRegionArr[0]內(nèi)的所有時(shí)間塊。時(shí)間塊寬度均為屏幕寬度除以crossRegionArr[0]的count,添加到屏幕上,標(biāo)記為已添加。取出數(shù)組crossRegionArr[1],遍歷crossRegionArr[1]的元素。如果crossRegionArr[1]中包含已添加到屏幕上的時(shí)間塊,那么應(yīng)該去掉該時(shí)間塊的所占的寬度。剩余的未添加的時(shí)間塊平分寬度。
以測(cè)試數(shù)據(jù)一為例

得到排序后的大數(shù)組以后,開始繪制時(shí)間塊。
(1)首先畫[540,600),[560,620),畫出兩個(gè)綠色的時(shí)間塊
(2)畫[560,620),[610,670)。[560,620)已在屏幕上。減去[560,620)的寬度,[610,670)平分剩余寬度。
(3)畫[540,600),已存在,跳過
(4)畫[30,150)

代碼實(shí)現(xiàn):
- (void)drawTimeBlock {
NSArray *jsonArr = @[
@{@"start":@"30",@"end":@"670"},
@{@"start":@"100",@"end":@"180"},
@{@"start":@"180",@"end":@"200"},
@{@"start":@"210",@"end":@"480"},
@{@"start":@"220",@"end":@"490"},
@{@"start":@"250",@"end":@"500"},
@{@"start":@"280",@"end":@"510"},
@{@"start":@"540",@"end":@"600"},
@{@"start":@"550",@"end":@"620"},
@{@"start":@"560",@"end":@"650"},
@{@"start":@"630",@"end":@"690"},
@{@"start":@"640",@"end":@"700"},
];
NSMutableArray *regionArr = [NSMutableArray array];
NSMutableArray *beginArr = [NSMutableArray array];
for (int i=0; i<jsonArr.count; i++) {//將區(qū)間讀入數(shù)組
Region *region = [[Region alloc] init];
NSDictionary *dict = jsonArr[i];
NSString *start = dict[@"start"];
NSString *end = dict[@"end"];
region.minNum = start.floatValue;
region.maxNum = end.floatValue;
[regionArr addObject:region];
[beginArr addObject:[NSNumber numberWithFloat:start.floatValue]];
}
NSMutableArray *crossRegionArr = [NSMutableArray array];
for (int i=0; i<beginArr.count; i++) {//將區(qū)間按重疊區(qū)域分組
NSMutableArray *tempArr = [NSMutableArray array];
for (int j=0; j<regionArr.count; j++) {
Region *region = regionArr[j];
NSNumber *start = beginArr[i];
if ([region containNum:start.floatValue]) {
[tempArr addObject:region];
}
}
[tempArr sortUsingComparator:^NSComparisonResult(Region *obj1, Region *obj2) {//按照region起始y值排序
return obj1.minNum > obj2.minNum;
}];
[crossRegionArr addObject:tempArr];
}
[crossRegionArr sortUsingComparator:^NSComparisonResult(NSArray *obj1, NSArray *obj2) {//數(shù)組按照count排序
return obj1.count < obj2.count;
}];
for (int i=0; i<crossRegionArr.count; i++) {//遍歷排序后的大數(shù)組
NSMutableArray *sortRegionArr = crossRegionArr[i];
NSInteger devideCount = sortRegionArr.count; //被平分的矩形個(gè)數(shù)
CGFloat startX = 0;
CGFloat endX = self.view.frame.size.width;
for (int j=0; j<sortRegionArr.count; j++) {//遍歷一行region數(shù)組
Region *region = sortRegionArr[j];
if (!region.associatedView) {//view還沒有添加添加,創(chuàng)建view
CGFloat ditance = endX - startX;//計(jì)算將要被平分的距離
CGFloat regionX = startX+(j+devideCount-sortRegionArr.count)*ditance/devideCount;
CGFloat regionY = region.minNum;
CGFloat regionW = ditance/devideCount;
CGFloat regionH = region.maxNum - region.minNum;
UIView *addView = [[UIView alloc] initWithFrame:CGRectMake(regionX, regionY,regionW,regionH)];
addView.backgroundColor = RandColor;
region.associatedView = addView;
[self.view addSubview:addView];
}else{ //view已經(jīng)添加
if (region.associatedView.frame.origin.x == startX) {
startX += region.associatedView.frame.size.width;
}else {
endX = endX-region.associatedView.frame.size.width;
}
devideCount = devideCount - 1;
}
}
}
}
Region對(duì)象
@interface Region : NSObject
@property(nonatomic, assign)CGFloat minNum;
@property(nonatomic, assign)CGFloat maxNum;
@property(nonatomic, weak)UIView *associatedView;
- (BOOL)containNum:(CGFloat)num;
@end
@implementation Region
- (BOOL)containNum:(CGFloat)num {
return (num >= self.minNum && num < self.maxNum);
}
@end
運(yùn)行結(jié)果
