【转】iOS笔记-自定义控件(OC)
原文网址:http://www.jianshu.com/p/f23862eb7b8a
导读:
iOS开发中,很多时候系统提供的控件并不能很好的满足我们的需求,因此,自定义控件便成为搭建UI界面中必不可少的一部分。本篇博文以笔记的形式,总结了自定义控件的两种方式以及每种方式的实现步骤,虽简略却不简单,因此希望留给读者更多的思考空间。作为入门的编程学习者,独立思考能力和动手编程能力都是至关重要的。在此,希望大家学习愉快,共同进步。
自定义控件之xib方式
xib与storyboard
- 共同点:
- 都用来描述软件界面
- 都用Interface Builder工具来编辑
- 本质都是转换成代码去创建控件
- 不同点:
- Xib是轻量级的,用来描述局部的UI界面
- Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
- 共同点:
Xib的加载方式
- 方式一:通过
mainBundelloadNibNamed:加载NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib文件名" owner:nil options:nil]` - 方式二:通过
UINibnibWithNibName加载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中加载就会调用这个方法;
awakeFromNibstoryboard/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, ...
随机推荐
- poj 1579 简单dp由下往上
#include<stdio.h> #include<string.h> #define N 22 int dp[N][N][N]; int main() { int n,m, ...
- (在线工具)JSON字符串转换成Java实体类(POJO)
http://www.bejson.com/json2javapojo/ 付代码代码转换示例: public static FixMixedOrderResponse serialization(St ...
- Codeforces Round #297 (Div. 2) D. Arthur and Walls [ 思维 + bfs ]
传送门 D. Arthur and Walls time limit per test 2 seconds memory limit per test 512 megabytes input stan ...
- CodeForces 592C The Big Race
公倍数之间的情况都是一样的,有循环节. 注意min(a,b)>t的情况和最后一段的处理.C++写可能爆longlong,直接Java搞吧...... import java.io.Buffere ...
- Delphi接口使用实例介绍
对于Object Pascal语言来说,最近一段时间最有意义的改进就是从Delphi3开始支持接口(interface),接口定义了能够与一个对象进行交互操作的一组过程和函数.对一个接口进行定义包含两 ...
- 包装类Float中为什么有两个常量来表示最小值
1)问:包装类Float中为什么有两个常量来表示最小值:MIN_VALUE和MIN_NORMAL ① MIN_VALUE:最小正非零值常量,是非规格化浮点数所能表示的最小值.值为 3.4E-45 的常 ...
- how to read openstack code: request extension
We have learned resource extension and action extension. This post we will write a request extension ...
- 【APUE】vim常用命令
转自:http://coolshell.cn/articles/5426.html 基本命令: i → Insert 模式,按 ESC 回到 Normal 模式. x → 删当前光标所在的一个字符. ...
- 一个基于JBoss5.1+EJB3.0 登陆应用
花了几天的时间研究了一下EJB的使用,一直以来都主要是在写终端中的程序,对Java框架的相关的开发非常不熟悉,中间遇到了不少麻烦,还好总算都攻克了.写篇日志记录一下. 经验总结 为什么选择JBoss5 ...
- 运行计划中cost计算方法
概念: blevel:二元高度=索引高度-1 clustering_factor:集群因子,通过索引扫面得出的要查询table的blocks数量,clustering_factor接近table的bl ...