上两章节:
这章对图层的几何学做个总结。
布局:UIView上3个重要的布局属性:
- frame
- bounds
- center
CALayer上对应的布局属性为:
- frame
- bounds
- position
-
- frame:图层外部坐标(即在父图层上占据的空间)
- bounds:内部坐标({0,0})图层左上角
- center与position:代表相对于父图层anchorPoint(锚点,默认中心点)所在的位置
操作UIView视图的frame属性实际上在改变该UIView的关联图层CALayer的对应属性,不能独立于CALayer之外改变视图的frame,亦即改变UIView的frame相关联的CALayer也会跟随改变
- frame:
- 是一个虚拟属性,根据bounds,position与transform计算而来(对图层变换时如旋转或缩放,frame实际上代表覆盖在图层旋转后整个轴对齐矩形区域,此时frame的宽高可能与bounds的宽高不一致了)
- 锚点anchorPoint:
- 用单位坐标来描述,默认坐标{0.5,0.5},可指定x和y值小于0或大于1;
- center与position属性指定anchorPoint相对于父图层的位置。
- 默认anchorPoint位于图层中点
- 视图UIView的anchorPoint属性没有被暴露,而图层CALayer的anchorPoint可以被移动
- 比如把anchorPoint置于frame左上角,那么相对于原来的frame,CALayer的内容将会向右下角方向移动,因为position指定anchorPoint,原来的frame的position还是在原来的位置并没有改变,但是anchorPoint改变了位置,所以frame内容也需要跟着anchorPoint改变位置;
坐标系:
- 一个图层的position依赖于父图层的bounds,父图层发生移动,所有子图层也会跟着移动。
- 如果想知道一个图层的绝对位置,或者是相对于另一个图层的位置,而不是它当前父图层的位置,可以使用以下坐标或rect转换方法获取
-
- -(CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer;
- -(CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer;
- -(CGRect)converRect:(CGRect)rect fromLayer:(CALayer *)layer;
- -(CGRect)converRect:(CGRect)rect toLayer:(CALayer *)layer;
- 以上方法可以把定义在一个图层坐标系下的点或者矩形转换到另一个图层坐标系下的点或者矩形,使用例子在下面
翻转的几何结构:
- CALayer的geometryFlipped属性设置为YES意味着子图层将会被垂直翻转,也就是沿着底部排版而不是通常的顶部
Z坐标轴:
- CALayer存在于一个三维空间中,除了position与anchorPoint属性外,还有在Z轴上描绘图层位置的zPosition和anchorPointz这另外两个属性
- zPosition最实用功能:
- 改变图层显示顺序(但不能改变图层在图层树上的图层顺序),通过该属性,可以把由子图层的sublayers出现的顺序决定的叠盖顺序改变
Hit Testing:
- 虽然CALayer不响应触摸事件,但是有一系列方法可以处理事件,如:-containsPoint:与-hitTest:
- -(BOOL)containsPoint:(CGPoint)point;
- 作用:判断该接收参数point是否在图层frame范围内
- 使用例子:
-(void)viewDidLoad{ [super viewDidLoad]; self.myLayer=[CALayer layer]; slef.myLayer.frame=CGRectMake(50.0f,50.0f,100.0f,100.0f); self.myLayer.backgroundColor=[UIColor blueColor].CGColor; [self.myView.layer addSublayer:self.myLayer]; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ CGPoint point=[[touches anyObject]locationInView:self.view]; point=[self.myView.layer convertPoint:point fromLayer:self.view.layer];//把fromLayer参数self.view.layer上的point点坐标转换为self.myView.layer上的坐标 if([self.myView.layer containsPoint:point]){ point=[self.myLayer convertPoint:point fromLayer:self.myView.layer]; if([self.myLayer containsPoint:point]){ [[[UIAlertView alloc] initWithTitle:@"Inside Blue Layer" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; }else{ [[[UIAlertView alloc] initWithTitle:@"Outside Blue Layer" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; } } }
- -(CALayer *)hitTest:(CGPoint)point;返回图层本身,或者包含point这个坐标点的叶子节点图层,意味着不需要像使用-containsPoint:那样人工转换测试点坐标
- 使用例子:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ CGPoint point=[[touches anyObject]locationInView:self.view]; CALayer *layer=[self.myView.layer hitTest:point]; if(layer == self.myLayer){ [[[UIAlertView alloc] initWithTitle:@"Inside Blue Layer" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; }else{ [[[UIAlertView alloc] initWithTitle:@"Outside Blue Layer" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; } }
- 调用图层CALayer的-hitTest:方法时,测算顺序严格依赖于图层树当中图层顺序,不会受zPosition属性改变在屏幕上的显示顺序而影响。