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

来源:互联网 发布:mac error 1045 28000 编辑:程序博客网 时间:2024/05/24 05:36

先说几个方法:

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

layer.isGeometryFlipped =true

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

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

layer.convert(CGPoint, to:CALayer)

这个方法一会有demo。

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.zPosition1

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


二、Hit Testing

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

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



代码如下:

class ViewController:UIViewController,CALayerDelegate {

    

 

    var blueView:UIView!

    var greenLayer:CALayer!

    

    overridefunc 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)

    }

   

    overridefunc touchesBegan(_ touches:Set<UITouch>, with event:UIEvent?) {

        //需要两步转换

        let allTouches = touchesasNSSet

        let touch = allTouches.anyObject()as!UITouch

        

        //得到touchpoint,注意是相对于touchview

        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足够远而不在blueViewbounds里,下面的条件判断就为false,试试点屏幕下方的白色)

       

        ifblueView.layer.contains(point) {

            

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

            print("in the View")

            

            ifgreenLayer.contains(point) {

                print(" in green")

                

            }else{

                print("in blue")

            }       

        }

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

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

    }   

}


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

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

    overridefunc touchesBegan(_ touches:Set<UITouch>, with event:UIEvent?) {

        let allTouches = touchesasNSSet

        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)

        }elseif layer ==greenLayer {

            print(2)

        }

 //1和2 有一个肯定不会打印的。由定义猜打印谁

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

    }