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

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

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

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

思路:

(1)每一個待辦事項都是一個區(qū)間呀狼,而我們首先要確定的是事情最多的那一分鐘處于多少個區(qū)間內(nèi),以此來計算最小的時間塊寬度损离。
(2)確定了寬度最小的時間塊以后哥艇,剩下的時間塊平分剩下的寬度。
(3)首先想到的是遍歷從9:00--21:00的每一分鐘內(nèi)有幾個待辦事項僻澎,需要遍歷12*60=720次貌踏,顯然這種做法太蠢了,我們只需要遍歷每個待辦事項開始時間點就行了窟勃。

image.png

步驟

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

image.png

得到排序后的大數(shù)組以后,開始繪制時間塊冬竟。

(1)首先畫[540,600)欧穴,[560,620),畫出兩個綠色的時間塊
(2)畫[560,620)泵殴,[610,670)涮帘。[560,620)已在屏幕上。減去[560,620)的寬度笑诅,[610,670)平分剩余寬度调缨。
(3)畫[540,600),已存在苟鸯,跳過
(4)畫[30,150)

image.png

代碼實現(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

運行結(jié)果

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市早处,隨后出現(xiàn)的幾起案子湾蔓,更是在濱河造成了極大的恐慌,老刑警劉巖砌梆,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件默责,死亡現(xiàn)場離奇詭異,居然都是意外死亡咸包,警方通過查閱死者的電腦和手機桃序,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烂瘫,“玉大人媒熊,你說我怎么就攤上這事》乇龋” “怎么了芦鳍?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長葛账。 經(jīng)常有香客問我柠衅,道長,這世上最難降的妖魔是什么籍琳? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任菲宴,我火速辦了婚禮贷祈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喝峦。我一直安慰自己势誊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布愈犹。 她就那樣靜靜地躺著键科,像睡著了一般闻丑。 火紅的嫁衣襯著肌膚如雪漩怎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天嗦嗡,我揣著相機與錄音勋锤,去河邊找鬼。 笑死侥祭,一個胖子當(dāng)著我的面吹牛叁执,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播矮冬,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼谈宛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胎署?” 一聲冷哼從身側(cè)響起吆录,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琼牧,沒想到半個月后恢筝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡巨坊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年撬槽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趾撵。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡侄柔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出占调,到底是詐尸還是另有隱情暂题,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布妈候,位于F島的核電站敢靡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏苦银。R本人自食惡果不足惜啸胧,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一赶站、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纺念,春花似錦贝椿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至烟逊,卻和暖如春渣窜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宪躯。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工泪姨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芒珠,地道東北人操软。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓遗嗽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親臣缀。 傳聞我的和親對象是個殘疾皇子坝橡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容