XMDatePicker寫作思路

先上一張效果圖(原諒我還是這么無聊~~,我覺得動態(tài)的可能更能展示作品的特性)

0.gif

寫這個(gè)時(shí)間選擇器之前我還沒寫過相關(guān)的東西,沒寫過其實(shí)是瞎話瞧省,以前在項(xiàng)目中用過UIDatePicker,所以可自定義性不是很強(qiáng),也沒啥可說的,雖然在我們的項(xiàng)目中時(shí)間選擇器很常見该默,但是認(rèn)真研究的人就不知道了……,這次我也算是認(rèn)真的看了一下UIPickerView內(nèi)部的組成策彤。先說說內(nèi)部的組成吧栓袖。

1 UIPickerView內(nèi)部組成

在xcode的可視化工具中你可以看到UIPikerView的結(jié)構(gòu)如下:

1.png

當(dāng)然如果匣摘,你也可以打印一下UIPikerView的子空間,會發(fā)現(xiàn)裹刮,它有三個(gè)子空間音榜,其中兩個(gè)是一樣的,而且高度是0.67,所以我們可以猜測這個(gè)高度是0.67的view就是那兩條灰色的分割線捧弃。不信你可以試試,簡要做以下測試

 self.picker.subviews[1].hidden = YES;
 self.picker.subviews[2].hidden = YES;

此時(shí)赠叼,你會驚奇的發(fā)現(xiàn)兩條灰色的分割線不見了,那么證實(shí)了我們猜測的是正確的违霞,那么接下來往下走吧嘴办。再來看結(jié)構(gòu),如果說你嫌看結(jié)構(gòu)圖麻煩的話买鸽,你可以利用打印子控件的方式看查看其內(nèi)部的控件涧郊,我是采用后者的,不過這里為了更加形象癞谒,我采用圖形結(jié)合的方式來講底燎。如下圖:


2.png

請?jiān)徫业膽卸枞姓ィ@里我把結(jié)構(gòu)圖全部展開來講吧弹砚,不再一張一張的貼圖了,

  • UIPickerView的suviews 展開這個(gè)后我們看到里面又有3個(gè)UIPickerColumnView枢希,當(dāng)然你可以利用日志打印一下桌吃,會發(fā)現(xiàn)前三個(gè)是完全一樣的,我們可以猜測每一個(gè)代表著一列苞轿,不信你可以改變數(shù)據(jù)源試試茅诱,會發(fā)現(xiàn)猜測的正確性。
  • 接下來我們進(jìn)入到每一列UIPickerColumnView搬卒,發(fā)現(xiàn)有三個(gè)UIView(子控件)瑟俭,前兩個(gè)完全一樣,第三個(gè)不同契邀,我猜測摆寄,第三個(gè)是中間行,也就是選擇到日期的那一行
  • 以此類推坯门,你可以看到中間行里面有一個(gè)子控件微饥,名字是UIPickerTableView,這是蘋果內(nèi)部私有類,在UIKit框架中我們找不到它的頭文件古戴,但是依舊不影響我們獲取到它欠橘。
    快上代碼,不多啰嗦了

2 為時(shí)間選擇器自定義分割線

我們可以拿到UIPickerTableView然后利用runtime機(jī)制取出其內(nèi)部的屬性现恼,如果你有印象的話肃续,我說過每個(gè)UIPickerColumnView中有三個(gè)UIView控件,每個(gè)UIView控件中只有一個(gè)子控件UIPickerTableView黍檩,而三個(gè)UIView控件中的第3個(gè)才是我們選擇時(shí)間的那一行。

上述話的意思簡單翻譯為UIPickerColumnViewUIView控件數(shù) = UIPickerTableView數(shù)

我們可以拿到每一列component( 即每一UIPickerColumnView列)中UIPickerTableView的數(shù)目

 int pickerTableViewNum = (int)self.picker.subviews[0].subviews[component].subviews.count;

遍歷吧始锚,記住第3個(gè)是選擇日期的那一行

    for (int index = 0; index<pickerTableViewNum; index++) {
       //取出對應(yīng)的UIPickerTableView
      UIView *tableView = self.picker.subviews[0].subviews[component].subviews[index].subviews[0];

       //取出UIPickerTableView內(nèi)部的成員變量列表
        unsigned int count = 0;
        Ivar *array = class_copyIvarList([tableView class], &count);

        //遍歷所有屬性
        for (int i = 0; i<count; i++) {
            Ivar property = array[i];
            const char *string = ivar_getName(property);
            NSString *name = [[NSString alloc]initWithUTF8String:string];
            //找出名字為@"_referencingCells"的屬性,取出它的值
            if (![name isEqualToString:@"_referencingCells"]) continue;
            NSMutableArray * cells = object_getIvar(tableView, property);

            int count = (int)cells.count;
            if(!count) continue;
            //設(shè)置字體顏色
            UIColor *textColor = nil;
            //設(shè)置label背景色
            UIColor *labelBackgroundColor = nil;
            //遍歷UIPickerTableView 中的cell建炫,并取出每個(gè)cell中的textLabel進(jìn)行設(shè)置相關(guān)屬性
            for (int i = 0; i< count; i++) {
                //設(shè)置其他部分的文字顏色、大小以及l(fā)abel背景等
                if (index !=pickerTableViewNum -1) {
                    font = self.otherTextFont? self.otherTextFont:[UIFont systemFontOfSize:16];
                    textColor = self.otherTextColor ? self.otherTextColor : [UIColor grayColor];
                    labelBackgroundColor = self.otherLabelColor ?self.otherLabelColor : [UIColor clearColor];
                }else{
                    font = self.selectedTextFont ? self.selectedTextFont : [UIFont systemFontOfSize:16];
                    textColor = self.selectedTextColor ? self.selectedTextColor : [UIColor blackColor];
                    labelBackgroundColor = self.selectedLabelColor ? self.selectedLabelColor : [UIColor clearColor];
                
                }
                
                UILabel *textLabel = [cells[i] subviews][1];
                textLabel.textColor = textColor;
                textLabel.font = font;
                textLabel.backgroundColor = labelBackgroundColor;
                
                if (index != pickerTableViewNum - 1)
                    continue;
                
                if (textLabel.subviews.count>=1)
                    continue;
                
                //dynamic seperator(設(shè)置動態(tài)分割線)
                if (self.pickerViewType == PickerViewTypeDynamicSperator) {
                    UIView *line = [[UIView alloc]initWithFrame:CGRectMake((textLabel.frame.size.width - textWidth)/2, textLabel.frame.size.height - 1, textWidth, 1)];
                    line.backgroundColor = self.seperateLineColor;
                    [textLabel addSubview:line];
                }
            }
        }
    }
    
    //static operate line(設(shè)置靜態(tài)分割線)
    if (self.pickerViewType != PickerViewTypeStaticSperator) return;
//通過多次測試疼蛾,可以粗略計(jì)算出每列之間的間隔大概是4.75
    CGFloat spacing = 4.75f;
    NSInteger numberOfComponent = [self numberOfComponents];
    CGFloat margin = (self.width - self.componentWidth * numberOfComponent - (numberOfComponent - 1)*spacing)/2;
    CGFloat textLabelOffSet = 9.0f;
    CGFloat textOffSet = (self.componentWidth - textLabelOffSet - textWidth)/2;
    //取出`UIPickerColumnView`中的最后一個(gè) `UIView`控件
    UIView *view =  [self.picker.subviews[0].subviews[component].subviews lastObject];
    
   //UIView控件里面在修改前只有一個(gè)UIPickerTableView控件肛跌,我們需要添加靜態(tài)分割線
    if (view.subviews.count>=3) {//不能多加啊
    }else{
        CGFloat x = (spacing+self.componentWidth)*component + margin + textLabelOffSet+textOffSet;
        UIView *lineView1 = [[UIView alloc]initWithFrame:CGRectMake(x, view.height - 1, textWidth, 1)];
        UIView *lineView2 = [[UIView alloc]initWithFrame:CGRectMake(x, 0, textWidth, 1)];
        lineView1.backgroundColor = [UIColor blueColor];
        lineView2.backgroundColor = [UIColor blueColor];
        [view addSubview:lineView1];
        [view addSubview:lineView2];
    }

上述代碼基本是設(shè)置所有分割線部分的關(guān)鍵代碼

3 關(guān)于日期的處理

這部分就不多做闡述了,主要是對每月天數(shù)的處理稍微復(fù)雜點(diǎn)察郁,至于其他的基本好處理衍慎,我們只要知道1、3皮钠、5稳捆、7、8麦轰、10乔夯、12是31天,4款侵、6末荐、9、11是30天新锈,2月份又分為平年和閏年甲脏,閏年29天,平年28天即可妹笆,許多demo種也有相關(guān)的計(jì)算块请,我覺得我代碼中的書寫應(yīng)該也可以比較清晰的闡述,還有就是滑動的時(shí)的日期更新拳缠,我們需要注意一點(diǎn)兒小問題墩新,如果想看內(nèi)部實(shí)現(xiàn)的話歡迎大家看我的源碼https://github.com/DreamOfXM/XMDatePicker.git
相關(guān)使用我已經(jīng)在github
如果發(fā)現(xiàn)有什么問題,一定要給我提出來哦窟坐,當(dāng)然也歡迎交流相關(guān)技術(shù)問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末海渊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子狸涌,更是在濱河造成了極大的恐慌切省,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帕胆,死亡現(xiàn)場離奇詭異朝捆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)懒豹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進(jìn)店門芙盘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驯用,“玉大人,你說我怎么就攤上這事儒老『牵” “怎么了?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵驮樊,是天一觀的道長薇正。 經(jīng)常有香客問我,道長囚衔,這世上最難降的妖魔是什么挖腰? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮练湿,結(jié)果婚禮上猴仑,老公的妹妹穿的比我還像新娘。我一直安慰自己肥哎,他們只是感情好辽俗,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著篡诽,像睡著了一般崖飘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上霞捡,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天坐漏,我揣著相機(jī)與錄音,去河邊找鬼碧信。 笑死,一個(gè)胖子當(dāng)著我的面吹牛街夭,可吹牛的內(nèi)容都是我干的砰碴。 我是一名探鬼主播,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼板丽,長吁一口氣:“原來是場噩夢啊……” “哼呈枉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起埃碱,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤猖辫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后砚殿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啃憎,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年似炎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辛萍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悯姊。...
    茶點(diǎn)故事閱讀 40,989評論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贩毕,靈堂內(nèi)的尸體忽然破棺而出悯许,到底是詐尸還是另有隱情,我是刑警寧澤辉阶,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布先壕,位于F島的核電站,受9級特大地震影響谆甜,放射性物質(zhì)發(fā)生泄漏启上。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一店印、第九天 我趴在偏房一處隱蔽的房頂上張望冈在。 院中可真熱鬧,春花似錦按摘、人聲如沸包券。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溅固。三九已至,卻和暖如春兰珍,著一層夾襖步出監(jiān)牢的瞬間侍郭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工掠河, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亮元,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓唠摹,卻偏偏與公主長得像爆捞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子勾拉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評論 2 361

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