2016-07-29 4 views
1

이미지를 가리고 호의 아래쪽 가장자리에 테두리를 그려주는 사용자 정의 헤더보기를 디자인했습니다. 그것은 다음과 같습니다UIView.animateWithDuration이이 사용자 정의보기에 영향을주지 않는 이유는 무엇입니까?

:

이 같은
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() 
    } 
} 

뭔가가 점차 프레임을 변경하지 않고 새로운 크기로 단지 스냅하게됩니다 : 여기

enter image description here

클래스에 대한 코드입니다
UIView.animate(withDuration: 1.0) 
{ 
    self.headerView.arcHeight  = self.new_headerView_arcHeight 
    self.headerView.frame   = self.new_headerView_frame 
} 

내가 CALayers를 사용한다는 사실과 관련이 있어야한다는 것을 알았지 만, 그 뒤에있는 일에 대해 충분히 알지 못합니다. nes.

편집 :

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; 
    } 

보너스

: 없는 흰색 라인 0 결과에 arcHeight 속성을 설정이 그려지는 가 여기에 내가 아크 경로를 만들 때 사용하는 기능입니다. 왜?

답변

0

Path 속성에는 애니메이션을 적용 할 수 없습니다. 문제에 다르게 접근해야합니다. 'arc'를 호 (arc)를 그리면 수동으로 애니메이션을 처리해야한다는 것을 알 수 있습니다. 전체 드로잉 프로세스가 3 초라고 가정하면 프로세스를 1000 개로 분할하고 0.3 밀리 초마다 1000 번 그리기 함수를 호출하여 처음부터 현재 점까지 다시 호를 그릴 수 있습니다.

0

self.headerView.arcHeight는 (는) 애니메이션 가능한 속성이 아닙니다. 자신의 속성이

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() 
    } 
} 
같은 뭔가를 할 수

애니메이트 UIView의 전용

관련 문제