【转】iOS笔记-自定义控件(OC)
原文网址:http://www.jianshu.com/p/f23862eb7b8a
导读:
iOS开发中,很多时候系统提供的控件并不能很好的满足我们的需求,因此,自定义控件便成为搭建UI界面中必不可少的一部分。本篇博文以笔记的形式,总结了自定义控件的两种方式以及每种方式的实现步骤,虽简略却不简单,因此希望留给读者更多的思考空间。作为入门的编程学习者,独立思考能力和动手编程能力都是至关重要的。在此,希望大家学习愉快,共同进步。
自定义控件之xib方式
xib与storyboard
- 共同点:
- 都用来描述软件界面
- 都用Interface Builder工具来编辑
- 本质都是转换成代码去创建控件
- 不同点:
- Xib是轻量级的,用来描述局部的UI界面
- Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
- 共同点:
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创建自定义控件步骤:
- 新建一个继承
UIView
的类 - 新建一个xib文件(xib的文件名最好跟控件类名一样)
- 添加子控件、设置子控件属性
- 修改最外面那个控件的class为控件类名
- 将子控件进行连线
- 提供模型属性,重写模型的set方法
- 在set方法中给子控件设置数据
- 新建一个继承
示例代码:
- (void)viewDidLoad {
//1.通过mainbundel获取xib文件,返回组件数组
NSArray * viewArr = [[NSBundle mainBundle] loadNibNamed:@"CYXView" owner:nil options:nil];
//2.取出数组中需要的控件
CYXView * myView = (CYXView *)[viewArr lastObject];
//3.设置控件的Frame
myView.frame = CGRectMake(100, 100, 10, 200);
//4.控件添加到self.View中
[self.view addSubview:myView];
}
补充:
initWithcoder
- 只要是从storyboard/xib中加载就会调用这个方法;
这个方法一般是初始化的操作
- 只要是从storyboard/xib中加载就会调用这个方法;
awakeFromNib
storyboard/xib
中加载完毕的时候调用,想做一些在xib加载完毕的操作,就在这个方法中操作(建议在这个方法中写初始化代码)
自定义控件之纯代码方式
- 何为自定义控件?
- 继承自系统自带的控件,写一个属于自己的控件
目的:封装控件内部的细节
为什么要封装?
- 封装的话,下次直接将封装好的类,直接拿去使用
封装以后,没有重复代码
- 封装的话,下次直接将封装好的类,直接拿去使用
- 自定义控件封装步骤:
- 创建一个自定义控件,建议直接继承自UIView,也可以继承自其他组件
封装的用途
- 以后需要封装一些框架给外界使用的时候
对于项目扩展性大大提高
- 以后需要封装一些框架给外界使用的时候
示例代码思路:
在新建的
CYXShopView
视图类(View)中代码思路如下- 1.定义子控件。在
init
方法内只管控件内部的创建,但不管frame
的初始化,因为外界调用的init方法不一定马上给frame
赋值,所以第一次init
是frame
的值可能为nil
- 2.定义位置尺寸(Frame)。重写系统的
-(void)layoutSubviews
方法,这个方法方法专门用来布局子控件,一般在这里设置子控件的frame
,当控件本身的尺寸发生改变的时候,系统会自动调用这个方法。重写此方法内一定要调用[super layoutSubviews]
- 3.设置数据。提供一个模型属性,重写模型属性的set方法,在set方法中取出模型属性,给对应的子控件赋值
- 1.定义子控件。在
在自定义控件内还可以添加其他更方便的初始化方法,可以参照apple官方的
UIView
等主要控件,还可以更高层次的封装,这个等以后再谈及。
//重写-(instancetype)initWithFrame:(CGRect)frame方法
//init方法内部会自动调用-(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;
}
/**
* 这个方法专门用来布局子控件,一般在这里设置子控件的frame
* 当控件本身的尺寸发生改变的时候,系统会自动调用这个方
*/
-(void)layoutSubviews{
// 一定要调用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];
}
- 补充:
init
和initWithFrame
(一般在使用代码创建的时候调用- 在调用
init
的时候,系统会默认调用一次initWithFrame
;但在调用initWithFrame
不会调用init
;所以一般初始化自己的子控件一般都是放在initWithFrame
- 在调用
给封装View设置数据的几种方式
(1)直接将属性暴漏在.h文件中:不好,影响封装性,不应该将自己的子控件暴漏在头文件中
(2)提供一个初始化方法
(3)根据tag设置子控件数据
- 因为子控件较少,所以设置比较方便。
- 控制器做的的太多了
(4)提供一个设置模型的方法,将模型传递过去(直接传递一个模型对象给View自己设置值)
(5)提供一个属性,直接使用点语法赋值(最终采取的方法)
【转】iOS笔记-自定义控件(OC)的更多相关文章
- iOS开发(OC)中的命名规范
开小差:最近发现自己有一个经验主义的毛病,不太容易接受新的知识,这对从事技术研发的人来说不太合理,需要改之. 正文:通过读写大量代码我有自己的一套编程思路和习惯,自认为自己的编码习惯还是不错的,代码结 ...
- iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)
iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController) 前面我们介绍了StoryBoard这个新技术,和纯技术 ...
- iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController)
iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController) 这里我们就直接上实例: 一:新建一个项目singleV ...
- iOS谋职之OC面试题
iOS谋职之OC面试题 iOS求职之OC面试题 IOS求职之OC面试题 1.Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议. 2.#import和 ...
- IOS开发-OC学习-常用功能代码片段整理
IOS开发-OC学习-常用功能代码片段整理 IOS开发中会频繁用到一些代码段,用来实现一些固定的功能.比如在文本框中输入完后要让键盘收回,这个需要用一个简单的让文本框失去第一响应者的身份来完成.或者是 ...
- 【iOS系列】-oc中特有的语法
[iOS系列]-oc中特有的语法 oc数据类型: 1,基本类型 2,对象类型 3,id 4,BOOL 5,block 6,SEL 1:category 使用继承关系来扩充一个类,有一个弊病,高耦合性 ...
- Android笔记--自定义控件仿遥控器的圆形上下左右OK圆盘按钮
原文:Android笔记--自定义控件仿遥控器的圆形上下左右OK圆盘按钮 上面就是几张预览图!代码在最底下 主要就两个步骤,画图.监听点击 1.整个控件基本上是一步步画出来的,重写onDraw方法开始 ...
- 荼菜的iOS笔记--UIView的几个Block动画
前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...
- iOS 阶段学习第11天笔记(OC基础知识)
iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import 用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...
随机推荐
- PTA 01-复杂度2 Maximum Subsequence Sum (25分)
题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/663 5-1 Maximum Subsequence Sum (25分) Given ...
- Centos6.5安装Oracle11.2.0.4 RAC(完整版)
环境参数:Linux:Centos6.5 Grid和Oracle:11.2.0.4 一.环境配置 1.配置Node1和Node2两个节点之间的网卡 Node1: [root@rac1 network- ...
- hdu1160简单dp最长下降子序列
/* 简单dp,要记录顺序 解:先排序,然后是一个最长下降子序列 ,中间需记录顺序 dp[i]=Max(dp[i],dp[j]+1); */ #include<stdio.h> #incl ...
- Java SSH框架系列:用户登录模块的设计与实现思路
1.简介用户登录模块,指的是根据用户输入的用户名和密码,对用户的身份进行验证等.如果用户没有登录,用户就无法访问其他的一些jsp页面,甚至是action都不能访问.二.简单设计及实现本程序是基于Jav ...
- BZOJ1704: [Usaco2007 Mar]Face The Right Way 自动转身机
n<=5000个数0或1,每次可以连续对固定长度区间取反,目标把所有1变0,求一个取反区间的固定长度K使取反次数最少. 答案关于K不单调,因此枚举K,对每个K扫一遍区间,遇到1就把连续K个数反转 ...
- redis连接数据库进行操作
该项目需要的类目录 1.首先我们需要创建我们的实体类 2.放置我们的dao层,在里面写入方法 3.配置类Appconfig需要加入我们的JdbcTemplate方法,因为我们用的是spring,所以需 ...
- java自动识别用户上传的文本文件编码
原文:http://www.open-open.com/code/view/1420514359234 经常碰到用户上传的部分数据文本文件乱码问题,又不能限制用户的上传的文件编码格式(这样对客户的要求 ...
- Office WORD如何去掉目录的背景灰色
有人说鼠标点击空白的地方灰色就自动散掉了,但是我点击并没有散掉 鼠标选中有灰色背景的文字,点击格式-边框和底纹,点击无填充颜色,并应用于文字. O了
- 用Lazarus编写第一个程序Pascal版的hello world
安装 Lazarus的过程不用多说,都是傻瓜式的. 打开Lazarus.Lazarus会自己主动新建一个窗体形式的应用程序. 你会看到五个窗体. 主窗体 这个窗体显示有标题栏.菜单条和工具栏. 对象视 ...
- Windows 上通过本地搭建 Jekyll环境
一 准备Ruby环境 1 我们首先须要安装Ruby.从站点下载Ruby 上下载Ruby最新版和对应的DevKit. 我下载的是Ruby 2.1.4 (x64)和DevKit-mingw64-6 .注意 ...