【问题标题】:Centre Align CAShape layer in a UIView在 UIView 中居中对齐 CAShape 层
【发布时间】:2016-06-04 01:04:55
【问题描述】:

以下是代码未对齐 UIView 中心的图片,白色。

CAShapeLayer *layer = [CAShapeLayer layer];
layer.anchorPoint=CGPointMake(0.5, 0.5);

layer.path=[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 75.0, 75.0)].CGPath;
layer.fillColor =[UIColor redColor].CGColor;

[self.shapeView.layer addSublayer:layer];

【问题讨论】:

    标签: ios cashapelayer


    【解决方案1】:

    anchorPoint 不用于设置 CAShapeLayer 的位置,请改用position

    let layer = CAShapeLayer()
    layer.borderColor = UIColor.blackColor().CGColor
    layer.borderWidth = 100
    
    layer.bounds = CGRectMake(0, 0, 50, 50)
    layer.position = myView.center
    layer.fillColor = UIColor.redColor().CGColor
    view.layer.addSublayer(layer)
    

    编辑

    抱歉之前这么粗略的回答,上面的代码可能无法如你所愿,这是我刚刚出来的正确答案。需要注意的重要一点是:您绘制椭圆路径的方式确实影响了您的 CAShapeLayer

    let layer = CAShapeLayer()
    myView.layer.addSublayer(layer)
    layer.fillColor = UIColor.redColor().CGColor
    layer.anchorPoint = CGPointMake(0.5, 0.5)
    layer.position = CGPointMake(myView.layer.bounds.midX, myView.layer.bounds.midY)
    layer.path = UIBezierPath(ovalInRect: CGRectMake(-75.0 / 2, -75.0 / 2, 75.0, 75.0)).CGPath
    

    来自 Apple 文档,

    椭圆路径是按顺时针方向创建的(相对于默认 坐标系)

    换句话说,椭圆路径是从边缘而不是中心绘制的,所以你必须考虑你正在绘制的椭圆的半径。在你的情况下,你需要这样做:

    layer.path = UIBezierPath(ovalInRect: CGRectMake(-75.0 / 2, -75.0 / 2, 75.0, 75.0)).CGPath 
    

    现在我们确保绘制路径的中心等于CAShapeLayer 的中心。然后我们可以使用position 属性来移动我们想要的CAShapeLayer。下图可以帮助你理解。

    【讨论】:

    • 这个答案有效,但我必须在viewDidLayoutSubviews 中添加它,并且在该方法中我必须在添加上述代码之前调用view.layoutIfNeeded()
    【解决方案2】:
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.anchorPoint=CGPointMake(0.5, 0.5);
    
    layer.path=[UIBezierPath bezierPathWithOvalInRect:CGRectMake((self.shapeView.frame.size.width/2)-37.5, (self.shapeView.frame.size.height/2)-37.5, 75.0, 75.0)].CGPath;
    //37.5 means width & height divided by 2
    layer.fillColor =[UIColor redColor].CGColor;
    
    [self.shapeView.layer addSublayer:layer];
    

    【讨论】:

      【解决方案3】:

      对于那些仍然有居中问题的人,这种方法对我有用:

      1- 设置形状层框架等于父视图框架。

      shapeLayer.frame = view.frame
      

      2- 移除形状层位置属性。

      // shapeLayer.position = CGPoint(x: ,y: )
      

      3- 将贝塞尔路径的 x 和 y 值设置为零。

      UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: self.width, height: 
      self.height))
      

      只有这些就足够了,剩下的就扔掉。

      ======

      如果这不起作用,那么试试这个:

      @IBDesignable class YourView: UIView {
      
      private var shapeLayer: CAShapeLayer!
      
      override func draw(_ rect: CGRect) {
          self.shapeLayer = CAShapeLayer()
          self.shapeLayer.path = bezierPath.cgPath
          self.shapeLayer.fillColor = UIColor.blue.cgColor
      
          let bezierPathHeight = self.bezierPath.cgPath.boundingBox.height
          let bezierPathWidth = self.bezierPath.cgPath.boundingBox.width
      
          self.shapeLayer.setAffineTransform(CGAffineTransform.init(translationX: self.bounds.width / bezierPathWidth, y: self.bounds.height / bezierPathHeight))
      
          self.shapeLayer.setAffineTransform(CGAffineTransform.init(scaleX: self.bounds.width / bezierPathHeight, y: self.bounds.height / bezierPathHeight))
      
          self.layer.addSublayer(self.shapeLayer)
      
      }
      

      【讨论】:

        【解决方案4】:

        我也遇到过这样的情况。最终分辨率为shapeLayer.needsDisplayOnBoundsChange = true,更新layoutSubviews中的CAShapeLayer框架,使用Auto Layout时可以调整CenteredAlignShapeView。

        class CenteredAlignShapeView: UIView {
            
            public let dot = CAShapeLayer()
         
            init() {
                super.init(frame: .zero)
                dot.needsDisplayOnBoundsChange = true
                layer.insertSublayer(dot, at: 0)
                dot.fillColor = UIColor.red.cgColor
            }
            
            override func layoutSubviews() {
                super.layoutSubviews()
                dot.frame = bounds
                let circlePath = UIBezierPath(arcCenter: CGPoint(x: bounds.width/2, y: bounds.height/2), radius: 4, startAngle: 0, endAngle: CGFloat.pi*2, clockwise: true)
                dot.path = circlePath.cgPath
            }
            
            required init?(coder: NSCoder) {
                fatalError("init(coder:) has not been implemented")
            }
            
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-30
          • 2015-07-25
          • 1970-01-01
          • 1970-01-01
          • 2021-06-01
          • 2011-03-13
          • 2016-08-17
          相关资源
          最近更新 更多