日歷時(shí)間塊布局實(shí)現(xiàn)

需求:實(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ù)一

測(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ù)二

測(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},
];
測(cè)試數(shù)據(jù)三

思路:

(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)就行了。

image.png

步驟

(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ù)一為例

image.png

得到排序后的大數(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)

image.png

代碼實(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é)果

三組測(cè)試數(shù)據(jù)運(yùn)行結(jié)果

github地址: https://github.com/liugangios/timeline.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載:http://www.cocoachina.com/swift/20161201/18198.html 前言...
    F麥子閱讀 4,513評(píng)論 2 8
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 30,286評(píng)論 8 265
  • 1,NSObject中description屬性的意義,它可以重寫嗎?答案:每當(dāng) NSLog(@"")函數(shù)中出現(xiàn) ...
    eightzg閱讀 4,351評(píng)論 2 19
  • 從早上睜開眼就是拿著手機(jī) 生怕錯(cuò)過一條信息 卻又不敢開聲音 渾渾噩噩的日子終要過去 開學(xué)了,好好學(xué)習(xí)
    戲精w閱讀 162評(píng)論 0 0
  • 1、我會(huì)用整個(gè)生命去愛你,卻也會(huì)屬于我自己 2、愛情真是一道難解的題,怕說錯(cuò),也怕錯(cuò)過 3、一生中有許多相遇,最快...
    碼字的黃小邪閱讀 597評(píng)論 0 1

友情鏈接更多精彩內(nèi)容