需求:實現(xiàn)一個日歷顯示頁面如下:
左側(cè)刻度從早上9點開始周伦,到晚上9點結(jié)束份招。以分鐘為單位娃胆。動態(tài)給時間塊定位并分配空間褥实。
測試數(shù)據(jù)一:
var events = [
{start: 30, end: 150},
{start: 540, end: 600},
{start: 560, end: 620},
{start: 610, end: 670}
];
測試數(shù)據(jù)二:
var events = [
{start: 30, end: 150},
{start: 540, end: 600},
{start: 550, end: 620},
{start: 560, end: 650},
{start: 630, end: 690},
];
測試數(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)每一個待辦事項都是一個區(qū)間呀狼,而我們首先要確定的是事情最多的那一分鐘處于多少個區(qū)間內(nèi),以此來計算最小的時間塊寬度损离。
(2)確定了寬度最小的時間塊以后哥艇,剩下的時間塊平分剩下的寬度。
(3)首先想到的是遍歷從9:00--21:00
的每一分鐘內(nèi)有幾個待辦事項僻澎,需要遍歷12*60=720
次貌踏,顯然這種做法太蠢了,我們只需要遍歷每個待辦事項開始時間點就行了窟勃。
步驟
(1)我們將每一個時間塊看成一個區(qū)間對象region祖乳,用一個數(shù)組regionArr
讀入存放它們。
(2)再建立一個數(shù)組beginArr
拳恋,存放每一個時間塊開始的時間點凡资,去掉重復(fù)的元素
(3)遍歷beginArr
里的元素(開始時間點),得出包含該時間點的所有時間塊谬运,放入數(shù)組隙赁,按照開始時間排序。最后將所有數(shù)組放入一個大數(shù)組crossRegionArr
梆暖,按照數(shù)組內(nèi)的元素個數(shù)排序伞访。
(4)遍歷crossRegionArr
,取出數(shù)組crossRegionArr[0]
,畫出crossRegionArr[0]
內(nèi)的所有時間塊轰驳。時間塊寬度均為屏幕寬度除以crossRegionArr[0]
的count厚掷,添加到屏幕上弟灼,標(biāo)記為已添加。取出數(shù)組crossRegionArr[1]
冒黑,遍歷crossRegionArr[1]
的元素田绑。如果crossRegionArr[1]
中包含已添加到屏幕上的時間塊,那么應(yīng)該去掉該時間塊的所占的寬度抡爹。剩余的未添加的時間塊平分寬度掩驱。
以測試數(shù)據(jù)一為例
得到排序后的大數(shù)組以后,開始繪制時間塊冬竟。
(1)首先畫[540,600)欧穴,[560,620)
,畫出兩個綠色的時間塊
(2)畫[560,620)泵殴,[610,670)
涮帘。[560,620)
已在屏幕上。減去[560,620)
的寬度笑诅,[610,670)
平分剩余寬度调缨。
(3)畫[540,600)
,已存在苟鸯,跳過
(4)畫[30,150)
代碼實現(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; //被平分的矩形個數(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;//計算將要被平分的距離
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對象
@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