2016-07-29 93 views
1

我设计了一个自定义标题视图,用于遮罩图像并在底部边缘绘制边框,即弧线。它看起来像这样:为什么UIView.animateWithDuration不影响这个自定义视图?

enter image description here

下面是类代码:

class HeaderView: UIView 
{ 
    private let imageView = UIImageView() 
    private let dimmerView = UIView() 

    private let arcShape = CAShapeLayer() 
    private let maskShape = CAShapeLayer() // Masks the image and the dimmer 

    private let titleLabel = UILabel() 

    @IBInspectable var image: UIImage? { didSet { self.imageView.image = self.image } } 
    @IBInspectable var title: String? { didSet {self.titleLabel.text = self.title} } 

    @IBInspectable var arcHeight: CGFloat? { didSet {self.setupLayers()} } 

    // MARK: Initialization 

    override init(frame: CGRect) 
    { 
     super.init(frame:frame) 
     initMyStuff() 
    } 

    required init?(coder aDecoder: NSCoder) 
    { 
     super.init(coder:aDecoder) 
     initMyStuff() 
    } 

    override func prepareForInterfaceBuilder() 
    { 
     backgroundColor = UIColor.clear() 
    } 

    internal func initMyStuff() 
    { 
     backgroundColor = UIColor.clear() 

     titleLabel.font = Font.AvenirNext_Bold(24) 
     titleLabel.text = "TITLE" 
     titleLabel.textColor = UIColor.white() 
     titleLabel.layer.shadowColor = UIColor.black().cgColor 
     titleLabel.layer.shadowOffset = CGSize(width: 0.0, height: 2.0) 

     titleLabel.layer.shadowRadius = 0.0; 
     titleLabel.layer.shadowOpacity = 1.0; 

     titleLabel.layer.masksToBounds = false 
     titleLabel.layer.shouldRasterize = true 

     imageView.contentMode = UIViewContentMode.scaleAspectFill 
     addSubview(imageView) 

     dimmerView.frame = self.bounds 
     dimmerView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6) 
     addSubview(dimmerView) 
     addSubview(titleLabel) 

     // Add the shapes 
     self.layer.addSublayer(arcShape) 
     self.layer.addSublayer(maskShape) 
     self.layer.masksToBounds = true // This seems to be unneeded...test more 

     // Set constraints 
     imageView.translatesAutoresizingMaskIntoConstraints = false 
     imageView .autoPinEdgesToSuperviewEdges() 
     titleLabel.autoCenterInSuperview() 
    } 

    func setupLayers() 
    { 
     let aHeight = arcHeight ?? 10 

     // Create the arc shape 
     arcShape.path = AppocalypseUI.createHorizontalArcPath(CGPoint(x: 0, y: bounds.size.height), width: bounds.size.width, arcHeight: aHeight) 
     arcShape.strokeColor = UIColor.white().cgColor 
     arcShape.lineWidth = 1.0 
     arcShape.fillColor = UIColor.clear().cgColor 

     // Create the mask shape 
     let maskPath = AppocalypseUI.createHorizontalArcPath(CGPoint(x: 0, y: bounds.size.height), width: bounds.size.width, arcHeight: aHeight, closed: true) 
     maskPath.moveTo(nil, x: bounds.size.width, y: bounds.size.height) 
     maskPath.addLineTo(nil, x: bounds.size.width, y: 0) 
     maskPath.addLineTo(nil, x: 0, y: 0) 
     maskPath.addLineTo(nil, x: 0, y: bounds.size.height) 

     //let current = CGPathGetCurrentPoint(maskPath); 
     //print(current) 

     let mask_Dimmer = CAShapeLayer() 
     mask_Dimmer.path = maskPath.copy() 

     maskShape.fillColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1.0).cgColor 
     maskShape.path = maskPath 

     // Apply the masks 
     imageView.layer.mask = maskShape 
     dimmerView.layer.mask = mask_Dimmer 
    } 

    override func layoutSubviews() 
    { 
     super.layoutSubviews() 

     // Let's go old school here... 
     imageView.frame = self.bounds 
     dimmerView.frame = self.bounds 
     setupLayers() 
    } 
} 

像这样的事情会导致它只是捕捉到新的大小,而不逐渐改变它的框架:

UIView.animate(withDuration: 1.0) 
{ 
    self.headerView.arcHeight  = self.new_headerView_arcHeight 
    self.headerView.frame   = self.new_headerView_frame 
} 

我认为它必须与我使用CALayers的事实有关,但我对真正背后的情况并不十分了解网元。

编辑: 下面是我用它来创建ARC路径的功能:

class func createHorizontalArcPath(_ startPoint:CGPoint, width:CGFloat, arcHeight:CGFloat, closed:Bool = false) -> CGMutablePath 
    { 
     // http://www.raywenderlich.com/33193/core-graphics-tutorial-arcs-and-paths 

     let arcRect = CGRect(x: startPoint.x, y: startPoint.y-arcHeight, width: width, height: arcHeight) 

     let arcRadius = (arcRect.size.height/2) + (pow(arcRect.size.width, 2)/(8*arcRect.size.height)); 
     let arcCenter = CGPoint(x: arcRect.origin.x + arcRect.size.width/2, y: arcRect.origin.y + arcRadius); 

     let angle = acos(arcRect.size.width/(2*arcRadius)); 
     let startAngle = CGFloat(M_PI)+angle // (180 degrees + angle) 
     let endAngle = CGFloat(M_PI*2)-angle // (360 degrees - angle) 
     //  let startAngle = radians(180) + angle; 
     //  let endAngle = radians(360) - angle; 

     let path = CGMutablePath(); 
     path.addArc(nil, x: arcCenter.x, y: arcCenter.y, radius: arcRadius, startAngle: startAngle, endAngle: endAngle, clockwise: false); 
     if(closed == true) 
     {path.addLineTo(nil, x: startPoint.x, y: startPoint.y);} 
     return path; 
    } 

奖金: 设置arcHeight属性设置为0的结果中没有白线被绘制。为什么?

回答

0

Path属性不能动画。你必须以不同的方式解决问题。您可以立即绘制一条弧线,任何弧线,以便告诉我们需要手动处理动画。如果您预计整个绘制过程需要3秒钟,那么您可能需要将过程拆分为1000个部分,并且每0.3毫秒调用一次圆弧绘制函数1000次,以便从头到尾再次绘制圆弧。

0

self.headerView.arcHeight不是动画属性。它只是UIView的自有财产动画

你可以做这样的事情

let displayLink = CADisplayLink(target: self, selector: #selector(update)) 
displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode 

let expectedFramesPerSecond = 60 


var diff : CGFloat = 0 
func update() { 
    let diffUpdated = self.headerView.arcHeight - self.new_headerView_arcHeight 
    let done = (fabs(diffUpdated) < 0.1) 
    if(!done){ 
     self.headerView.arcHeight -= diffUpdated/(expectedFramesPerSecond*0.5) 
     self.setNeedsDisplay() 
    } 
} 
相关问题