参考:http://blog.sina.com.cn/s/blog_7b9d64af0101edqf.html

回忆一下,这么个场景。
我们在一个界面上,要排列多个相同的元素。你马上就可以想到:
1.如果要用按钮,可以使用来UIButton布局。
如:
 

- (void) showSectionListbyCount:(float)totalCount everyColCount:(float)paramColCount{

int curNum=1;

int TotalRow= ceilf(totalCount/paramColCount);// 总行数

for (int curRow=0; curRow

for (int curCol=0; curCol// 列数

if (totalCount

return;

}

UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];

[btn setFrame:CGRectMake(10+(67+10)*curCol, (30+10)*curRow, 67, 30)];

[btn setTitle:[NSString stringWithFormat:@"%d",curNum]forState:UIControlStateNormal];

[btn setBackgroundImage:[UIImage imageNamed:@"btn_tv_n"]forState:UIControlStateNormal];

[btn setBackgroundImage:[UIImage imageNamed:@"btn_tv_h"]forState:UIControlStateHighlighted];

[btn setTitleColor:[UIColor blackColor]forState:UIControlStateNormal];

[btn setTitleColor:[UIColor whiteColor]forState:UIControlStateHighlighted];

[btn addTarget:self action:@selector(ClickControlAction:)forControlEvents:UIControlEventTouchUpInside];

[btn setTag:curNum];

[self.view addSubview:btn];

curNum++;

}

}

}

如果,我们想用表格,那么每个元素可以使用UITableViewCell来定义相近的项。

很简单是吧,因为,xCode,为我们提供了这些UI控件供我们使用!所以,我们只需要用!

那么,今天的问题也就来了!如果,我想搞一个能够满足自己的一些UI元素。别急,也就是这样:

比如,我要搞这么一个界面!

我想,首先可以肯定,苹果不可能为我量身定制了这么一个控件。并且,如果,我用苹果的默认控件来写,那么我肯定会崩溃的。。

也就是说,我们将每一项,写成单独的一个UI控件。那么,可以根据数据进行填充!那就酷毙了!

绕了,一大圈,也就是要引用出来今天要学习的,东西!

自定义UI!!!

说起来,很牛X。其实很简单,说白了,就是子类化(重写)UIView。

我们常常重写,UIButton,UIImageView,UITableView 等等。因为,可能我们用到的跟这些已有控件很相似,稍微修改一些就能够满足我们。

但是,出入大的时候,我们就不能简单的继承于一个已有控件了!

那就是完全重写!就是子类化UIView

开始动手吧!!!

1.定义一UIView个的子类。

这个不解释!

2.重写drawRect方法。或者重写layoutSubviews方法、

1. drawRect方法:

- (void)drawRect:(CGRect)rect

{

// Drawing code

for (int i=0; i<<span style="color: #2f2fd0">10; i++) {

UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];

[btn setFrame:CGRectMake(10, 10+i*40, 67, 30)];

[btn setBackgroundImage:[UIImage imageNamed:@"btn_n"] forState:UIControlStateNormal];

[btn setBackgroundImage:[UIImage imageNamed:@"btn_h"] forState:UIControlStateHighlighted];

[btn addTarget:self action:@selector(ClickControlAction:)forControlEvents:UIControlEventTouchUpInside];

[btn setTag:i];

[self addSubview:btn];

}

}

2. layoutSubviews 方法

- (void)layoutSubviews{

[super layoutSubviews];

[self setBackgroundColor:[UIColor clearColor]];

[_imgPic setFrame:CGRectMake(7, 6, 86, 108)];

[_imgPic setImage:[UIImage imageNamed:[self.dictData objectForKey:@"img_content"]]];

[_imgPic.layer setShouldRasterize:NO];

[_imgPic.layer setBorderColor: [[UIColor whiteColor] CGColor]];

[_imgPic.layer setBorderWidth: 1.0];

[[_imgPic layer] setShadowRadius:2];

[[_imgPic layer] setShadowOpacity:1];

[[_imgPic layer] setShadowColor:[UIColor blackColor].CGColor];

[[_imgPic layer] setShadowOffset:CGSizeMake(0, 1)];

[self addSubview:self.imgPic];

}

可见,这两种方法都可以的。具体的区别,就是drawRect方法和layoutSubviews方法之间的区别了。

但是,经过测试,我发现,应该使用drawRect方法,来完成界面的绘制。因为,如果我们使用的是layoutSubviews方法,那么每一次改变frame的时候,layoutSubviews都将重新执行。显然不科学。

在网上,我看到,大部分例子使用的是drawRect方法,来重绘界面。(绘制界面)

我使用了layoutSubviews方法。在frame改变时,会自动调用。(重定向子视图)

根据需要选择使用哪一种方法!

关于两种方法,在网上搜了一下,总结如下:

layoutSubviews在以下情况下会被调用:

1、init初始化不会触发layoutSubviews。

2、addSubview会触发layoutSubviews。

3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。

4、滚动一个UIScrollView会触发layoutSubviews。

5、旋转Screen会触发父UIView上的layoutSubviews事件。

6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。

7、直接调用setLayoutSubviews。

drawRect在以下情况下会被调用:

1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).

2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。

3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。

4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。

以上1,2推荐;而3,4不提倡

drawRect方法使用注意点:

1、 若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或 者 setNeedsDisplayInRect,让系统自动调该方法。

2、若使用calayer绘图,只能在drawInContext: 中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法

3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕

3.自定义UIView的初始化方法。

我们常常在UIViewController中,看到initWithNibName方法:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if (self) {

// coding

}

return self;

}

这是xCode给我们定义好的初始化方法。

既然,我们要自定义UIView,那么最好,根据自己的业务逻辑,来完成子类化UIView的初始化方法:

#pragma mark - Initialization 根据业务逻辑,传入数据,初始化自己

- (id)initItemWithFram:(CGRect)frame andData:(NSMutableDictionary *)paramData{

self = [super initWithFrame:frame];

if (self) {

// Initialization code

_dictData=[[NSMutableDictionary alloc] init];

_imgPic=[[UIImageView alloc] init];

_imgCover=[[UIImageView alloc] init];

_btnClick=[[UIButton alloc] init];

_btnDel=[[UIButton alloc] init];

_lblTips=[[UILabel alloc] init];

_lblName=[[UILabel alloc] init];

}

self.dictData=paramData;

return self;

}

+ (id) initItemWithFrame:(CGRect)frame andData:(NSMutableDictionary *)paramData{

WTVTVCollectionItem *tmpInstance=[[WTVTVCollectionItem alloc] initItemWithFram:frameandData:paramData];

return tmpInstance;

}

这样,就可以初始化:

NSMutableArray *items = [NSMutableArray array];

[items addObject:[WTVTVCollectionItem initItemWithFrame:CGRectMake(10, 10, 100, 150)andData:dict]];

[items addObject:[WTVTVCollectionItem initItemWithFrame:CGRectMake(10, 10, 100, 150)andData:dict]];

[items addObject:[WTVTVCollectionItem initItemWithFrame:CGRectMake(10, 10, 100, 150)andData:dict]];

4.为UIView加入一些动画

动画是UI操作的灵魂!给予动画效果,就看上去有神了。

添加动画,一般也用2种方法:

1.重写UIView的方法,在调用时,进行动画操作。

# pragma mark - 重写父类的removeFromSuperview方法,在删除时,使用相应的动画效果

- (void) removeFromSuperview {

[UIView animateWithDuration:0.2 animations:^{

self.alpha = 0.0;

[self setFrame:CGRectMake(self.frame.origin.x+50, self.frame.origin.y+50, 0, 0)];

[_btnDel setFrame:CGRectMake(0, 0, 0, 0)];

}completion:^(BOOL finished) {

[super removeFromSuperview];

}];

}

2.直接在UIView元素上,进行动画对象的添加

- (void) enableEditing {

if (self.isInEditingMode == YES)

return;

// 设置为编辑状态

self.isInEditingMode = YES;

[_btnDel setHidden:NO];

// 开始晃动动画

CATransform3D transform;

// 获取0到x-1之间的整数

if (arc4random() % 2 == 1)

transform = CATransform3DMakeRotation(-0.08, 0, 0, 1.0);

else

transform = CATransform3DMakeRotation(0.08, 0, 0, 1.0);

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];

animation.toValue = [NSValue valueWithCATransform3D:transform];

animation.autoreverses = YES;

animation.duration = 0.1;

animation.repeatCount = 10000;

animation.delegate = self;

[[self layer] addAnimation:animation forKey:@"wiggleAnimation"];

[(WTVTVSprintBoard*)self.delegate enableEditingMode];

}

 

5.子类化UIView的交互

如何将操作链接起来!?就是说,在控件外,对我们自定义的控件进行操作?!

也有2种方法:

1.消息

2.代理

总结:

我想,我过多的将思路就可以了,因为业务需求不同,控件的自定义需求也不同,所以,不能用具体来固定!但是,思路是想通的,知道了原理,我们就可以发挥我们的聪明智慧,创造出千变万化的控件来!

希望对你有所帮助!!!

[ios]自定义UI的更多相关文章

  1. iOS开发UI篇—CAlayer(自定义layer)

    iOS开发UI篇—CAlayer(自定义layer) 一.第一种方式 1.简单说明 以前想要在view中画东西,需要自定义view,创建一个类与之关联,让这个类继承自UIView,然后重写它的Draw ...

  2. ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

    本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布 ...

  3. iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局

    iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 一.项目文件结构和plist文件 二.实现效果 三.代码示例 1.没有使用配套的类,而是直接使用xib文 ...

  4. iOS开发UI篇—Quartz2D(自定义UIImageView控件)

    iOS开发UI篇—Quartz2D(自定义UIImageView控件) 一.实现思路 Quartz2D最大的用途在于自定义View(自定义UI控件),当系统的View不能满足我们使用需求的时候,自定义 ...

  5. iOS(Swift)学习笔记之SnapKit+自定义UI组件

    本文为原创文章,转载请标明出处 1. 通过CocoaPods安装SnapKit platform :ios, '10.0' target '<Your Target Name>' do u ...

  6. iOS之UI组件整理

    作者:神兽gcc 授权本站转载. 最近把iOS里的UI组件重新整理了一遍,简单来看一下常用的组件以及它们的实现.其实现在这些组件都可以通过Storyboard很快的生成,只是要向这些组件能够变得生动起 ...

  7. iOS开发——UI进阶篇(十五)Quartz2D介绍

    一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘 ...

  8. iOS开发UI篇—手写控件,frame,center和bounds属性

    iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...

  9. iOS开发UI篇—transframe属性(形变)

    iOS开发UI篇—transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移.缩放比例和旋转角度 常用的创建transform结构体方法分两 ...

随机推荐

  1. SpringMyBatisDay02

    全篇概述:IOC    DI     参数值注入      注解依赖注入 1.Spring IOCIOC 全称Inversion Of Control,被翻译成控制反转控制反转指:程序中对象的获取方式 ...

  2. Twitter OA prepare: Equilibrium index of an array

    Equilibrium index of an array is an index such that the sum of elements at lower indexes is equal to ...

  3. linux phpize

    phpize是什么 1.phpize是用来扩展php扩展模块的,通过phpize可以建立php的外挂模块. 当php编译完后,在bin下面会有phpize这个脚本文件, 在编译你要添加的扩展模块之前, ...

  4. Django初级手册4-表单与通用视图

    表单的编写 1. detail.html模版的编写 <h1>{{ poll.question }}</h1> {% if error_message %}<p>&l ...

  5. python写一个密码生成器的类,要求有个类变量,统计一下一共生成过多少个密码。 要求有4个方法,1:构造方法 2 实例方法 3 类方法 4 静态方法

    生成指定长度的随机数字密码 生成指定长度的随机字母密码 生成指定长度的随机数字和字母的混合 #encoding=utf-8   import random import string class pa ...

  6. 基于Spring Cloud的微服务落地

    微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的微服务 ...

  7. 自动对比度的opencv实现

    在http://www.cnblogs.com/Imageshop/archive/2011/11/13/2247614.html 一文中,作者给出了“自动对比度”的实现方法,非常nice 实际实现过 ...

  8. 20145302张薇《课程设计》数据恢复——WinHex实践

    20145302张薇<课程设计>数据恢复--WinHex实践 实践内容 使用WinHex破损一个U盘 使用WinHex通过DBR备份数据来修复已损坏U盘 实践详细步骤 1.准备一个文件格式 ...

  9. 20145317彭垚《网络对抗》Exp9 Web安全基础实践

    20145317彭垚<网络对抗>Exp9 Web安全基础实践 基础问题回答 SQL注入攻击原理,如何防御? SQL注入攻击就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询 ...

  10. sqlite3 的一些整理和补充

    一,sqlite3数据库打开时的返回值及其所代表的含义 返回值 描述 返回值 描述 SQLITE_OK=0 返回成功 SQLITE_FULL=13 数据库满,插入失败 SQLITE_ERROR=1 S ...