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

隨機(jī)配圖

導(dǎo)讀:

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

自定義控件之xib方式

  • xib與storyboard

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

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

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

- (void)viewDidLoad {
    //1.通過(guò)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];

}

  • 補(bǔ)充:
    • initWithcoder

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

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

自定義控件之純代碼方式

  • 何為自定義控件?

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

  • 為什么要封裝?

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

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

    • 以后需要封裝一些框架給外界使用的時(shí)候
      對(duì)于項(xiàng)目擴(kuò)展性大大提高
  • 示例代碼思路:

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

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

//重寫(xiě)-(instancetype)initWithFrame:(CGRect)frame方法
//init方法內(nèi)部會(huì)自動(dòng)調(diào)用-(instancetype)initWithFrame:(CGRect)frame  方法,因此建議寫(xiě)這個(gè)方法,用于替代-(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;
}
/**
 * 這個(gè)方法專(zhuān)門(mén)用來(lái)布局子控件,一般在這里設(shè)置子控件的frame
 * 當(dāng)控件本身的尺寸發(fā)生改變的時(shí)候,系統(tǒng)會(huì)自動(dòng)調(diào)用這個(gè)方
 */
-(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];
}

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

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

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

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

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

    • 因?yàn)樽涌丶^少,所以設(shè)置比較方便。
    • 控制器做的的太多了
  • (4)提供一個(gè)設(shè)置模型的方法,將模型傳遞過(guò)去(直接傳遞一個(gè)模型對(duì)象給View自己設(shè)置值)

  • (5)提供一個(gè)屬性,直接使用點(diǎn)語(yǔ)法賦值(最終采取的方法)

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,036評(píng)論 25 709
  • 使用純代碼的方式 一般來(lái)說(shuō)我們的自定義類(lèi)繼承自UIView,首先在initWithFrame:方法中將需要的子控件...
    ForeverYoung21閱讀 22,083評(píng)論 26 103
  • 掌握 UIView的常見(jiàn)屬性和方法 九宮格計(jì)算方法 字典轉(zhuǎn)模型 Xib的使用 自定義view(view的封裝) 簡(jiǎn)...
    JonesCxy閱讀 1,522評(píng)論 1 3
  • 【感恩相遇】 2017-04-24學(xué)習(xí)力五期踐行Day34 今天又是很悲催,娃的同學(xué)玩到很晚才回家!踐行的時(shí)間和效...
    人生之過(guò)客閱讀 149評(píng)論 0 1
  • 《好好學(xué)習(xí)》成甲老師出品,中信出版集團(tuán) 閱讀時(shí)間1小時(shí) Q1:什么是低水平勤奮? A1:在原始方法的基礎(chǔ)上進(jìn)行努力...
    鄭珍容閱讀 286評(píng)論 0 0

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