iOS筆記-自定義控件(OC)

隨機配圖

導(dǎo)讀:

iOS開發(fā)中,很多時候系統(tǒng)提供的控件并不能很好的滿足我們的需求,因此,自定義控件便成為搭建UI界面中必不可少的一部分。本篇博文以筆記的形式,總結(jié)了自定義控件的兩種方式以及每種方式的實現(xiàn)步驟,雖簡略卻不簡單,因此希望留給讀者更多的思考空間。作為入門的編程學(xué)習(xí)者,獨立思考能力和動手編程能力都是至關(guān)重要的。在此,希望大家學(xué)習(xí)愉快,共同進(jìn)步。

自定義控件之xib方式

  • xib與storyboard

    • 共同點:
      • 都用來描述軟件界面
      • 都用Interface Builder工具來編輯
      • 本質(zhì)都是轉(zhuǎn)換成代碼去創(chuàng)建控件
    • 不同點:
      • Xib是輕量級的,用來描述局部的UI界面
      • Storyboard是重量級的,用來描述整個軟件的多個界面,并且能展示多個界面之間的跳轉(zhuǎn)關(guān)系
  • Xib的加載方式

    • 方式一:通過mainBundel loadNibNamed:加載
    NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib文件名" owner:nil options:nil]`
- 方式二:通過`UINib`    `nibWithNibName`加載
UINib *nib = [UINib nibWithNibName:@"xib文件名" bundle:nil];
NSArray *views = [nib instantiateWithOwner:nil options:nil];
  • 通過xib創(chuàng)建自定義控件步驟:

    • 新建一個繼承UIView的類
    • 新建一個xib文件(xib的文件名最好跟控件類名一樣)
      • 添加子控件、設(shè)置子控件屬性
      • 修改最外面那個控件的class為控件類名
      • 將子控件進(jìn)行連線
    • 提供模型屬性,重寫模型的set方法
      • 在set方法中給子控件設(shè)置數(shù)據(jù)
  • 示例代碼:

- (void)viewDidLoad {
    //1.通過mainbundel獲取xib文件,返回組件數(shù)組
    NSArray * viewArr = [[NSBundle mainBundle] loadNibNamed:@"CYXView" owner:nil options:nil];
    //2.取出數(shù)組中需要的控件
    CYXView * myView = (CYXView *)[viewArr lastObject];
    //3.設(shè)置控件的Frame
    myView.frame = CGRectMake(100, 100, 10, 200);
    //4.控件添加到self.View中
    [self.view addSubview:myView];

}

  • 補充:
    • initWithcoder

      • 只要是從storyboard/xib中加載就會調(diào)用這個方法;
        這個方法一般是初始化的操作
    • awakeFromNib

      • storyboard/xib中加載完畢的時候調(diào)用,想做一些在xib加載完畢的操作,就在這個方法中操作(建議在這個方法中寫初始化代碼)

自定義控件之純代碼方式

  • 何為自定義控件?

    • 繼承自系統(tǒng)自帶的控件,寫一個屬于自己的控件
  • 目的:封裝控件內(nèi)部的細(xì)節(jié)

  • 為什么要封裝?

    • 封裝的話,下次直接將封裝好的類,直接拿去使用
      封裝以后,沒有重復(fù)代碼
  • 自定義控件封裝步驟:

    • 創(chuàng)建一個自定義控件,建議直接繼承自UIView,也可以繼承自其他組件
  • 封裝的用途

    • 以后需要封裝一些框架給外界使用的時候
      對于項目擴展性大大提高
  • 示例代碼思路:

    • 在新建的CYXShopView視圖類(View)中代碼思路如下

      • 1.定義子控件。在init方法內(nèi)只管控件內(nèi)部的創(chuàng)建,但不管frame的初始化,因為外界調(diào)用的init方法不一定馬上給frame賦值,所以第一次initframe的值可能為nil
      • 2.定義位置尺寸(Frame)。重寫系統(tǒng)的-(void)layoutSubviews方法,這個方法方法專門用來布局子控件,一般在這里設(shè)置子控件的frame,當(dāng)控件本身的尺寸發(fā)生改變的時候,系統(tǒng)會自動調(diào)用這個方法。重寫此方法內(nèi)一定要調(diào)用[super layoutSubviews]
      • 3.設(shè)置數(shù)據(jù)。提供一個模型屬性,重寫模型屬性的set方法,在set方法中取出模型屬性,給對應(yīng)的子控件賦值
    • 在自定義控件內(nèi)還可以添加其他更方便的初始化方法,可以參照apple官方的UIView等主要控件,還可以更高層次的封裝,這個等以后再談及。

//重寫-(instancetype)initWithFrame:(CGRect)frame方法
//init方法內(nèi)部會自動調(diào)用-(instancetype)initWithFrame:(CGRect)frame  方法,因此建議寫這個方法,用于替代-(instancetype)init 方法

-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super init]) {

        //添加圖片
        UIImageView * iconView = [[UIImageView alloc]init];
        iconView.backgroundColor = [UIColor grayColor];
        [self addSubview:iconView];

        //添加文字
        UILabel * name = [[UILabel alloc]init];
        name.backgroundColor = [UIColor greenColor];
        name.font = [UIFont systemFontOfSize:15];
        name.textAlignment = NSTextAlignmentCenter;

        [self addSubview:name];

    }

    return self;
}
/**
 * 這個方法專門用來布局子控件,一般在這里設(shè)置子控件的frame
 * 當(dāng)控件本身的尺寸發(fā)生改變的時候,系統(tǒng)會自動調(diào)用這個方
 */
-(void)layoutSubviews{
    // 一定要調(diào)用super方法
    [super layoutSubviews];

    CGFloat shopW = self.frame.size.width;
    CGFloat shopH = self.frame.size.height;

    self.iconView.frame = CGRectMake(0, 0, shopW, shopW);
    self.name.frame  = CGRectMake(0, shopW, shopW, shopH-shopW);
}
-(void)setShop:(CYXShop *)shop{
    //賦值
    _shop = shop;
    self.name.text = self.shop.name;
    self.iconView.image = [UIImage imageNamed:self.shop.icon];
}

  • 補充:
    • initinitWithFrame(一般在使用代碼創(chuàng)建的時候調(diào)用
      • 在調(diào)用init的時候,系統(tǒng)會默認(rèn)調(diào)用一次initWithFrame;但在調(diào)用initWithFrame不會調(diào)用init;所以一般初始化自己的子控件一般都是放在initWithFrame

給封裝View設(shè)置數(shù)據(jù)的幾種方式

  • (1)直接將屬性暴漏在.h文件中:不好,影響封裝性,不應(yīng)該將自己的子控件暴漏在頭文件中

  • (2)提供一個初始化方法

  • (3)根據(jù)tag設(shè)置子控件數(shù)據(jù)

    • 因為子控件較少,所以設(shè)置比較方便。
    • 控制器做的的太多了
  • (4)提供一個設(shè)置模型的方法,將模型傳遞過去(直接傳遞一個模型對象給View自己設(shè)置值)

  • (5)提供一個屬性,直接使用點語法賦值(最終采取的方法)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,703評論 2 380

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