首页 > 程序开发 > 移动开发 > IOS >

iOS CoreAnimation (五) convert方法,hitTest方法,contains,zPosition的使用

2017-06-08

iOS CoreAnimation (五) convert方法,hitTest方法,contains,zPosition的使用。

iOS CoreAnimation (五) convert方法,hitTest方法,contains,zPosition的使用。

先说几个方法:

1、翻转的几何结构:iOS中从左上角开始排版(0,0),一个方法让它垂直翻转:

layer.isGeometryFlipped =true

从底部排版,左下角是(0,0)

2、把某个图层坐标系下的 点或矩形 转换成另一个图层坐标系下的 点或矩形

layer.convert(CGPoint, to:CALayer)

这个方法看不懂没事,下面有示例。

3、判断图层CALayer是否包含某一个点CGPoint,返回Bool

Layer.contains(point)

方法是在CALayer里声明的,但是方法文档却写着 返回:layer的bounds是否包含该点。

而CGRect类里也有声明这个方法!俩方法是不是完全一样?实践表明是的。

所以用这个方法要小心:看着某个点不包含于某个layer,但是!!!它可能被layer的实际bounds 包含!!!

这里没看懂?一会有demo。

一、Z坐标轴

和 UIView严格的二维坐标系不同,CALayer存在于一个三维空间当中。CALayer还有另外两个属性

zPosition和anchorPointZ ,二者都是在Z轴上描述图层位置的浮点数。

书中以后会涉及三维空间移动和旋转图层用到zPosition,除了做变换之外, 其最实用的功能就是改变图层的显示顺序了。

通常,图层是根据子图层添加顺序绘制的,但是通过增加图层的zPosition,就可以让它可能在其他图层的前面显示

(只要设置被盖住的图层z大于另一个一像素就行:

view下.layer.zPosition =1

view下 就在所以view之上了(如果其他view是默认值 0 的话)

二、Hit Testing

说这个东西之前,看一个demo。我要做的是,如图所示,给你一个UIView,其layer(蓝色)有一个subLayer(绿色),我要实现功能是:

点击蓝色部分,打印 blue ,触摸 绿色部分,打印 green。

\

代码如下:

class ViewController: UIViewController,CALayerDelegate {

var blueView:UIView!

var greenLayer:CALayer!

override func viewDidLoad() {

super.viewDidLoad()

blueView = UIView(frame:CGRect(x:50, y:200, width:350, height:300))

blueView.backgroundColor = UIColor.blue

greenLayer = CALayer()

greenLayer.frame = CGRect(x: 50, y: 200, width: 200, height: 200)

greenLayer.backgroundColor = UIColor.green.cgColor

blueView.layer.addSublayer(greenLayer)

view.addSubview(blueView)

}

override func touchesBegan(_ touches: Set, with event: UIEvent?) {

//需要两步转换

let allTouches = touches as NSSet

let touch = allTouches.anyObject() as! UITouch

//得到touch的point,注意是相对于touch的view

var point = touch.location(in: touch.view)

//假设我们点击了 上面的白色区域, touch.view是 self.view,然后point,就是触摸位置在self.view中的位置。

//调用下面的方法:(convert方法的大体定义在最上面)

point = blueView.layer.convert(point, from: blueView.layer)

//point还是刚才的point(假设值为(50,50)),但是convert方法 不管这么多。它从(from)参数 blueView的坐标系出发,找到此坐标系!中的(50,50)点(point参数),然后方法调用者(receiver)用自己的坐标系衡量刚找到的点的位置,并return。所以上面那句调用,尽管我点的是左上角某白色区域,但仍会使下面的条件判断为true,因为,contains方法实际上仅仅判断 调用者的bounds是否包含某个点!(如果点的白色区域的point足够远而不在blueView的bounds里,下面的条件判断就为false,试试点屏幕下方的白色)

if blueView.layer.contains(point) {

point = greenLayer.convert(point, from: blueView.layer)

print("in the View")

if greenLayer.contains(point) {

print(" in green")

}else {

print("in blue")

}

}

// 至于如何解决这个问题,自己动脑想想加个条件判断吧(下手提示,touch.view)

//那么,下面突出来的那部分绿色怎么搞?这个我也没想,直接进入正题吧:hitTest

}

}

下面是另一种touchesBegan的写法,用 hitTest方法。

//方法接受一个 CGPoint 类型参数,它返回图层本身,或者包含这个坐标点的叶子节点图层。这意味着不再需要像使用 contains 那样,人工地在每个子图层变换或者测试点击的坐标。如果这个点在最外面图层的范围之外,则返回nil。看程序应该能理解这个方法砸用的==

override func touchesBegan(_ touches: Set, with event: UIEvent?) {

let allTouches = touches as NSSet

let touch = allTouches.anyObject() as! UITouch

let point = touch.location(in: touch.view)

let layer = blueView.layer.hitTest(point)

if layer == blueView.layer {

print(1)

}else if layer == greenLayer {

print(2)

}

//注意:当调用图层的 -hitTest: 方法时,测算的顺序严格依赖于图层树当中的图层 顺序(和UIView处理事件类似)。之前提到的 zPosition 属性可以明显改变屏幕 上图层的顺序,但不能改变事件传递的顺序。这意味着如果改变了图层的z轴顺序,你会发现将不能够检测到最前方的视图点击 事件,这是因为被另一个图层遮盖住了,虽然它的 zPosition 值较小,但是在图 层树中的顺序靠前。我们将在以后讨论这个问题。

}

//这个方法不理解不要紧,下篇文章还会补充一点。

相关文章
最新文章
热点推荐