zoukankan      html  css  js  c++  java
  • iOS CALayer使用

    CALayer使用

         iOS的设备中,我们之所以能看到各种各样的控件、文字、图片,都是Core Animation框架的功劳。它通过图层的合成,最终显示在屏幕上。而今天这篇文章讲的就是Core Animation使用的图层— CALayer。每一个UIView都有一个对应的一个CALayer,这个CALayer可能是一个图层,也可能是多个图层的叠加。事实上,在很多复杂的页面中,我们应该使用图层的叠加来显示,这样做的好处是保证显示的逻辑结构清晰。这篇文章主要介绍CALayer的一些属性以及它的使用,同时写一份Demo演示如何自定义的创建一个自定义的CALayer。

    一、CALayer的属性

        和UIView类似,CALayer也包括frame、backgroundColor等属性。 这些属性在被设置的时候直接对UIView有效。同时CALayer还有一些UIView没有的属性,比如圆角、阴影等等。先看下面CALayer的一个属性表:

     
    属性名 描述
    CGRect bounds; 描述了CALayer的位置信息
    CGPoint position; 描述CALayer的坐标   
    CGFloat zPosition; 描述CALAayer的层级  比如想将某个图层放在最上面,可以将它的层级设置到更高
    CGPoint anchorPoint; 描点,默认情况的描点是 (0.5,0.5),也即是中心的位置。 
    CGFloat anchorPointZ; 不明白
    CATransform3D transform; 3D的形变  包括缩放、旋转
    BOOL hidden; 是否隐藏
    BOOL geometryFlipped; 直到OS X 10.8才出现了geometryFlipped属性,该属性可以改变默认图层y坐标的方向。当翻转变换被调用时,使用该属性来调整图层的方向有的时候是必需的。如果父视图使用了翻转变换,它的子视图内容(以及它对应的图层)将经常被颠倒。在这种情况下,设置子图层的geometryFlipped属性为YES是一种修正该问题最简单的方法。在OS X 10.8及以上版本,AppKit负责管理该属性,你不应该更改它。对于iOS app,不推荐使用geometryFlipped属性。表示坐标系是否翻转
    CALayer *mask; 蒙版
    BOOL masksToBounds; 设置YES 使得在layer上的子视图显示圆角有效
    id contents; layer上的内容面,如图片
    CGRect contentsRect; 显示的内容的区域 
    NSString *contentsGravity; 跟UIView的ContentModel类似,显示的类型,是一个字符串。
    CGFloat contentsScale 内容的缩放。 
    CGRect contentsCenter; 显示内容的中心
    NSString *contentsFormat 内容的格式
    BOOL opaque; 是否不透明。默认是YES,也就是不透明的
    float minificationFilterBias; 减小大小的因子
    rasterizationScale 光栅化
    @property(copy) NSString *minificationFilter;@property(copy) NSString *magnificationFilter; 缩小和放大时的描绘方式。

    shadowColor

    shadowOpacity

    shadowOffset

    shadowRadius

    shadowPath

    阴影的颜色

    阴影透明度

    阴影的偏移量

    阴影的半径

    阴影路径 。比如:可以画一个三角形的区域作为layer的路径,那显示的阴影就是三角形的。

     

    needsDisplayOnBoundsChange

    drawsAsynchronously

    edgeAntialiasingMask

    allowsEdgeAntialiasing

    位置改变是否刷新

    异步绘制

    抗锯齿

    大之后是否允许抗锯齿 

    backgroundColor

    borderWidth

    borderColor

    opacity

    背景颜色

    边框宽度

    边框颜色

    透明度设置

           PS: 在设置layer 的阴影的时候,如果设置了layer的圆角的话,那么设置的阴影效果将不会显示出来。 一个解决办法是:在控件的下方添加一个相同的frame的底层控件,在底层空间上设置阴影,原控件可以设置圆角。

    二、CALayer的使用

          (1). 使用CALayer作出阴影效果

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let testVC:UIImageView  = UIImageView.init(frame: CGRect.init(x: 10, y: 100,  screenWidth-20, height: screenWidth-20))
            testVC.image = #imageLiteral(resourceName: "timg.jpeg")
            self.view.addSubview(testVC)
            
            //添加圆角  
    //        testV.layer.cornerRadius = 30
    //        testV.layer.masksToBounds = true
            
            
            //添加阴影  注意:如果有圆角的话,阴影效果添加将会无效
            testV.layer.shadowColor = UIColor.black.cgColor
            testV.layer.shadowOpacity = 0.8
            testV.layer.shadowRadius = 30;
            testV.layer.shadowOffset = CGSize.init( 0, height: -1)
            
            
            //上述方式将使用离屏渲染,在性能上的消耗很大,为了加快渲染,我们添加下面的代码。
            testVC.layer.shadowPath = UIBezierPath.init(rect: testVC.bounds).cgPath
    
        }
    

          (2). 使用CALayer的子类CAShapeLayer绘制彩色的圆环

          CAShapeLayer的特点是必须依赖路径才能显示,这样有助于我们绘制不同的形状用CAShapeLayer来显示。

     //使用CAShperlayer
        func userShaper(){
            
            //创建一个底色  
            let BgView:UIView = UIView.init(frame: CGRect.init(x: 0, y: 0,  200, height: 200))
            BgView.center = self.view.center
            BgView.backgroundColor = UIColor.black
            self.view.addSubview(BgView)
            
            let leftG : CAGradientLayer = CAGradientLayer.init()
            leftG.colors = [UIColor.red.cgColor,UIColor.orange.cgColor,UIColor.yellow.cgColor]
            leftG.locations = [0,0.5,0.9]
            leftG.startPoint = CGPoint.init(x: 0, y: 0)
            leftG.endPoint = CGPoint.init(x: 0, y: 1.0)
            leftG.frame = CGRect.init(x: 0, y: 0,  100, height: 200)
            
            let rightG : CAGradientLayer = CAGradientLayer.init()
            rightG.colors = [UIColor.blue.cgColor,UIColor.init(red: 50/255.0, green: 1.0, blue: 163/255.0, alpha: 1.0).cgColor,UIColor.green.cgColor,UIColor.yellow.cgColor]
            rightG.locations = [0,0.35,0.7,0.9]
            rightG.startPoint = CGPoint.init(x: 0, y: 0)
            rightG.endPoint = CGPoint.init(x: 0, y: 1.0)
            rightG.frame = CGRect.init(x: 100, y: 0,  100, height: 200)
            
            BgView.layer.addSublayer(leftG)
            BgView.layer.addSublayer(rightG)
            
            let lineWidth:CGFloat = 10.0  //线宽
            let CASharp:CAShapeLayer = CAShapeLayer.init()
            CASharp.lineWidth = lineWidth
            CASharp.lineCap = "round"
            CASharp.lineJoin = "round"  //包角为圆形
    
            //创建路径
    //        let path : UIBezierPath = UIBezierPath.init(roundedRect: BgView.bounds, cornerRadius: 10.0)
    //        let rect:CGRect = CGRect.init(x: BgView.bounds.origin.x+width/2.0, y:BgView.bounds.origin.y+width/2.0,   BgView.bounds.size.width-width, height: BgView.bounds.size.height-width)
    ////        let path : UIBezierPath = UIBezierPath.init(ovalIn: rect)
    //        
            //起始角度
            let path1:UIBezierPath = UIBezierPath.init(arcCenter:CGPoint.init(x: 100, y: 100), radius: BgView.frame.width/2.0 - lineWidth, startAngle: -(CGFloat(Double.pi/2.0)), endAngle: CGFloat(Double.pi), clockwise: true)
            
            
            CASharp.strokeColor = UIColor.blue.cgColor
            CASharp.path = path1.cgPath
            CASharp.fillColor = UIColor.clear.cgColor
            
            BgView.layer.mask = CASharp
            
            print("完成")
        }

        下面是彩色环形的样子。  我们可以通过控制圆的起始位置来控制圆环的长度,如果做起动画就可以形成彩色环形控制条的效果。

    三、UIView的绘制方法

         我们在开发过程中,经常会涉及到修改控件上的显示内容。实际上,在修改内容之后,不会立即在屏幕上作出反应,而是等待一个runloop周期之后进行刷新。不过这个频率很快,我们肉眼认为几乎是即时修改的。有时候我们会主动的通过- (void)drawRect:(CGRect)rect来对UIView做一些修改,在上下文中绘制一些内容,但是这些内容不会自动显示,我们需要调用以下方法才可实现:

        - (void)setNeedsDisPlay

      调用此方法通知系统view需要重新绘制,会异步自动调用drawRect方法。

      - (void)setNeedsDisplayInRect:(CGRect)rect

       同样异步调用drawRect方法。在一次运行循环(run loop)中无论调用setNeedsDisplay或setNeedsDisplayInRect多少次,只调用drawRect一次。也是从减少资源开销的角度考虑的。

      - (void)drawRect:(CGRect)rect

      此方法的缺省实现是空。子类使用原生的绘制技术(Core Graphics and UIKit)绘制内容时应该重写此方法,在方法里面写出自己的drawing code。如果view设置自己的内容用其他的方法,则不需要去重写此方法。如果直接从UIView对象继承,实现此方法不需要call super。然而如果从其他的UIView对象继承,则应该调用super。当view 第一次显示或者当view的可视的一部分无效时,此方法会调用。此方法不能直接被调用。调用setNeedsDisplay 或者 setNeedsDisplayInRect: 方法会触发重新绘制。

         UIView的绘制实际上就是对CALayer内容的修改。

  • 相关阅读:
    iOS 发送位置消息
    集成 jpush-react-native 常见问题汇总 (iOS 篇)
    RESTful API 最佳实践
    RESTful API 设计指南
    理解RESTful架构
    PHP 调用 shell
    Laravel Model updating&updated 事件使用注意事项
    sudo 命令报 unable to resolve host 导致反应速度变慢
    Nginx设置禁止通过IP访问服务器并且只能通过指定域名访问
    Homestead can not mount nfs on macos catalina
  • 原文地址:https://www.cnblogs.com/FBiOSBlog/p/6900534.html
Copyright © 2011-2022 走看看