// 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
// 将像素point从view中转换到当前视图中,返回在当前视图中的像素值
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
// 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
// 将rect从view中转换到当前视图中,返回在当前视图中的rect
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;
举例:
//默认情况下,frame是以父控件左上角为坐标原点
// 转换坐标系
CGRect newFrame = [fromconvertRect:from.boundstoView:window]; //计算frame这个控件在window中的位置和尺寸
// 或者: CGRect newFrame = [from.superview convertRect:from.frame toView:window];
举例:
void)viewDidLoad
{
[superviewDidLoad];
// 蓝色
UIView *blue = [[UIViewalloc]init];
blue.backgroundColor = [UIColorblueColor];
frame = CGRectMake(0,50,200,200);
self.viewaddSubview:blue];
self.blue
// 红色
UIView *red = [[UIViewalloc]init];
red.backgroundColor = [UIColorredColor];
frame = CGRectMake(50,60,100,100);
addSubview:red];
self.red
// 黄色
UIView *yellow = [[UIViewalloc]init];
yellow.backgroundColor = [UIColoryellowColor];
frame = CGRectMake(10, 10, 50, 50);
addSubview:yellow];
self.yellow
// 紫色
UIView *purple = [[UIViewalloc]init];
purple.backgroundColor = [UIColorpurpleColor];
frame = CGRectMake(150, 350, 100, 100);
self.viewaddSubview:purple];
self.purple
}
void)touchesBegan:(NSSet *)touches withEvent:(UIEvent
{
// NSLog(@"%@", NSStringFromCGRect(self.yellow.bounds));
// NSLog(@"%@", NSStringFromCGRect(self.yellow.frame));
// 计算self.yellow在self.blue中的位置和尺寸
// CGRect newRect = [self.yellow convertRect:self.yellow.bounds toView:self.blue];
// 计算self.yellow在self.purple中的位置和尺寸
// CGRect newRect = [self.yellow.superview convertRect:self.yellow.frame toView:self.purple];
// 计算self.red在self.yellow中的位置和尺寸
// CGRect newRect = [self.red convertRect:self.red.bounds toView:self.yellow];
// 计算self.red在self.yellow中的位置和尺寸
// CGRect newRect = [self.yellow convertRect:self.red.bounds fromView:self.red];
// 计算self.red在屏幕中的位置和尺寸(nil代表屏幕)
CGRect newRect = [self.redconvertRect:self.red.boundstoView:nil];
NSLog(@"%@",NSStringFromCGRect(newRect));
}
addSubview:
添加一个子视图到接收者并让它在最上面显示出来。
- (void)addSubview:(UIView *)view
讨论
这方法同样设置了接收者为下一个视图响应对象。接收者保留视图。如果你使用removeFromSuperview方法用来把视图移除他的显示列表,那么视图将会被释放。如果你想要在视图移除显示列表後保留并使用这个视图(如果,举个例子,你想要交换一些视图的位置。),你不许保留那个视图在他调用removeFromSuperview前。
bringSubviewToFront:
把指定的子视图移动到顶层
- (void)bringSubviewToFront:(UIView *)view
参数
view
需要移到顶层的视图
convertPoint:fromView:
把一个点从一个坐标系转换到接收者的坐标系
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view
参数
point
一个视图中坐标系上的点
view
一个视图包含了点和他自身坐标系。如果是图是nil,那么这个方法将尝试转换基于窗口的坐标系。否则视图和那个接收者必须属于同一个UIWindow对象。
返回值
一个转换到接收者坐标系的点
convertPoint:toView:
转换一个点从接收者坐标系到给定的视图坐标系
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
参数
point
一个在调用者坐标系中的点
view
一个包含了需要被转换的点的视图。如果视图是nil,那么这个方法将会转换成基于窗口的坐标。否则视图和接收者都要属于同一个UIWindow对象。
返回值
基于视图的坐标系转换过的点
convertRect:fromView:
转换一个矩形从其他视图坐标系到接收者坐标系。
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view
参数
rect
一个在视图坐标系中的矩形
view
一个视图内部有矩形在他的坐标系中。如果视图是nil,那么这个方法将会基于窗口来转换。否则视图和接收者必须都属于同一个UIWindow对象
返回值
The converted rectangle
转换过的矩形
convertRect:toView:
转换接收者坐标系中的矩形到其他视图
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view
参数
rect
一个在接收者坐标系中的矩形
view
要转换过去的目标视图对象。如果这个是视图是nil,这个方法将会基于窗口坐标系来转换。否者视图和接收者必须属于同一个UIwindow对象
返回值
一个转换过的矩形
didAddSubview:
告诉视图当子视图已经添加
- (void)didAddSubview:(UIView *)subview
参数
subview
被添加做子视图的视图对象
讨论
被子类重写用来执行额外的命令当子视图添加到接收者。这个方法被addSubview调用
didMoveToSuperview
通知接收者父视图已经改变(nil是允许的)
- (void)didMoveToSuperview
讨论
默认不做任何事情;子类可以重写这方法来作为特定的实现
didMoveToWindow
通知接收者它一斤给添加到窗口中
- (void)didMoveToWindow
讨论
默认实现不做任何事情;子类可以重写这个方法来做特殊的实现
窗口的属性有可能是nil当这个方法调用的时候,这表明接收者并不属于当然任何一个窗口。这个只发生在接收者从它的父视图上移除或者接收者添加到父视图中而不是添加到window中。重写这个方法可以用来选择忽略一些他们不关心的对象
drawRect:
在接收者视图中绘制矩形
- (void)drawRect:(CGRect)rect
参数
rect
一个定义的需要绘制的矩形
讨论
子类重写这个方法如果他们确实要绘制他们自定义的视图。如果子类是其他视图的容器那么它不需要重写这个方法。默认的实现不做任何事情。如果你自定义的视图是一个UIView子类,你不需要去调用它的父类实现。注意如果它的父类实现绘制并且不透明属性为YES那么每一个子类都需要填充矩形。
当这个方法被调用,接收者可以假定他的帧在坐标上已经转换,边界矩形已经应用;所有他要做的就是绘制自定义的方法。使用UIGraphicsGetCurrentContext方法去获取当前图形内容用来绘制,坐标原点在左上角。不要保留图片内容当他可以被drawRect:这个方法调用。
exchangeSubviewAtIndex:withSubviewAtIndex:
交换接收者的子视图和给定的索引视图
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2
参数
index1
一个需要取代索引2的子视图
index2
一个需要取代索引1的子视图
hitTest:withEvent:
返回接收者视图层次中最远的派生(包括它本身)的特定的点。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
参数
point
接收者坐标系中的点
event
触发这个方法的事件或者是如果这个方法被预调用就返回nil
返回值
一个视图对象最远的派生点。如果这个点位于接收者之外就返回nil
讨论
这个方法贯穿视图的层次发送pointInside:withEvent: 消息到每一个子视图用来决定那个子视图需要接收触摸事件。如果pointInside:withEvent: 返回YES,那么视图的层次全部贯穿;否则视图层次的分支是被否定的。你不太需要调用这个方法,但是你需要重写它用来隐藏子视图的触摸事件。
如果视图是隐藏的,禁止用户交互的或者透明值小于01那么这个方法不可用
initWithFrame:
初始化并返回一个新的拥有特定帧矩形的视图对象
- (id)initWithFrame:(CGRect)aRect
参数
aRect
一个帧矩形用来创建视图对象。原始的帧在它的父视图的坐标系中。设置这个属性用来改变中心和边界属性。
返回值
一个初始化的视图对象,如果没有被创建那就返回nil
讨论
一个新的视图对象必须添加到视图链中才能使用。这个方法为UIView类指出初始化对象。
insertSubview:aboveSubview:
在视图层次顶层插入一个视图
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview
参数
view
一个插入被用来放在顶层的视图。它将会从父视图中移除如果它不是相邻视图
siblingSubview
一个相邻视图用来放在插入视图的後面
insertSubview:atIndex:
插入视图到指定的索引
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index
参数
view
插入的视图,这个值不能是nil
index
子视图索引从0开始并且不能大于子视图的数量
insertSubview:belowSubview:
插入视图到显示链的底层
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview
参数
view
一个需要插入到其他视图底部的视图。它将从它的父视图移除如果它不与相邻视图的相邻
siblingSubview
一个相邻视图将会在插入的视图之上
isDescendantOfView:
返回一个布尔值指出接收者是否是给定视图的子视图或者指向那个视图
- (BOOL)isDescendantOfView:(UIView *)view
参数
view
一个视图用来测试子视图在视图层次中的关系
返回值
如果接收者是视图的子视图就返回YES,或者视图就是接收者;否则就是NO
layoutIfNeeded
排列子视图如果需要的话
- (void)layoutIfNeeded
讨论
使用这个方法来关注子视图的排列在绘制前
layoutSubviews
排列子视图
- (void)layoutSubviews
讨论
当layoutIfNeeded被调用是子类用来重写这个方法来排列子视图。默认实现这个方法不做任何事情。
pointInside:withEvent:
返回一个布尔值指出接收者是否包含特定的点
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
参数
point
一个在接收者坐标系内的点
event
这个方法的目标事件或者如果这个方法被预调用返回nil
返回值
如果点在接收者边界内返回YES,否则返回NO
removeFromSuperview
把接收者从它的父视图或者窗口移除,并在响应链中移除。
- (void)removeFromSuperview
讨论
接收者同时释放;如果你计划重用它,要确定在发送消息前保持它并在添加到其他UIView对象作为子视图後移除。 不要在显示的时候调用
sendSubviewToBack:
移动指定的子视图到它相邻视图的後面
- (void)sendSubviewToBack:(UIView *)view
参数
view
一个子视图用来移动到它後面去
setNeedsDisplay
控制接收者的边界矩形被标记为需要显示
-(void)setNeedsDisplay
讨论
默认情况下,视图几何图形的改变自动重绘而不需要调用drawRect:方法。因此,你需要去请求视图重绘当视图的数据或者状态改变的时候。从这个意义上来说,向视图发送setNeedsDisplay消息。任何UIView对象标记为需要显示後将会在应用程序循环中自动重新绘制。
setNeedsDisplayInRect:
标记接收者中的特定的矩形区域为需要显示,或者添加接收者现有的其他无效区域
- (void)setNeedsDisplayInRect:(CGRect)invalidRect
参数
invalidRect
标记接收者的矩形区域为无效的;他需要在接收者坐标系中定义。
讨论
默认情况下,视图几何图形的改变自动重绘而不需要调用drawRect:方法。因此,你需要去请求视图重绘当视图的数据或者状态改变的时候。使用这个方法或者用setNeedsDisplay方法来标记视图需要显示的地方。
setNeedsLayout
设置当子视图显示的时候需要重新排列
- (void)setNeedsLayout
讨论
如果你调用这个方法在下一个显示方法之间,那么layoutIfNeeded排列子视图;否则将不会做任何事情
sizeThatFits:
计算并返回一个最好的适应接收者子视图的大小
- (CGSize)sizeThatFits:(CGSize)size
参数
size
接收者首选的尺寸
返回值
一个新的大小用来适应接收者子视图
讨论
默认的实现返回大小参数 子类重写这个方法用来返回特定视图的大小。举个粒子,UISwitch返回一个修正过的大小,UIImageView返回图片的大小 这个方法并没有改变接收者的大小
sizeToFit
调整大小并移动接收者视图大小所以他包含了他的子视图
- (void)sizeToFit
讨论
这个方法使用sizeThatFits: 方法来决定大小。子类需要重写sizeThatFits:用来计算正确的尺寸大小。默认的实现不做任何事情。
viewWithTag:
返回视图的特定的标签
- (UIView *)viewWithTag:(NSInteger)tag
参数
tag
一个用来在视图中搜索的标签
返回值
视图在接收者层次中符合的标签,接收者也包含在搜索中。
willMoveToSuperview:
通知接收者他的父视图将会改变到特定的父视图(也有可能是nil)
- (void)willMoveToSuperview:(UIView *)newSuperview
参数
newSuperview
新的视图对象将会是接收者新的父视图
讨论
子类可以重写这个方法来做一些特定的行为
willMoveToWindow:
通知接收者它已经被添加到特定的窗口对戏那个的视图层次中(也有可能是nil)
- (void)willMoveToWindow:(UIWindow *)newWindow
参数
newWindow
一个窗口对象将会成为接收者新的视图层次的根视图
讨论
子类可以重写这个方法来提供一些特定的必要实现
willRemoveSubview:
由子类重写用来在子视图从接收者视图中移除前执行一些特定的方法。
- (void)willRemoveSubview:(UIView *)subview
参数
subview
子视图将会被移除
讨论
这个方法被调用当子视图接收到removeFromSuperview消息或者子视图从接收者视图层次中移除因为它要被添加到其他视图了
setNeedsDisplay和setNeedsLayout方法
1,UIView的setNeedsDisplay和setNeedsLayout方法
首先两个方法都是异步执行的。而setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到 UIGraphicsGetCurrentContext,就可以画画了。而setNeedsLayout会默认调用layoutSubViews,
就可以 处理子视图中的一些数据。
综上所诉,setNeedsDisplay方便绘图,而layoutSubViews方便出来数据。
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实时刷新屏幕