为什么UIView.animateWithDuration不会影响此自定义视图?

时间:2016-07-29 09:16:31

标签: swift animation uiview calayer uiviewanimation

我设计了一个自定义标题视图,用于屏蔽图像并在底部边缘绘制边框,这是一个弧形。它看起来像这样:

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这一事实有关,但我对幕后发生的事情并不是很了解。

编辑: 这是我用来创建弧形路径的函数:

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会导致不绘制白线。为什么呢?

2 个答案:

答案 0 :(得分:0)

Path属性无法设置动画。你必须以不同的方式解决问题。您可以立即绘制圆弧,任何圆弧,这样就告诉我们需要手动处理动画。如果您希望整个绘制过程花费3秒钟,那么您可能希望将过程分割为1000个零件,并且每0.3毫秒调用弧形绘制功能1000次,以便从开始到当前点再次绘制弧形。

答案 1 :(得分:0)

self.headerView.arcHeight不是可动画的属性。只有UIView自己的属性是可动画的

你可以做这样的事情

$(data).find(tagName).each(function(index) {

   var tagValue= $(this).attr("AttributeName");

   // perform your repalce login here unescape(tagValue)

})