Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用curveEaseOut设置UIView子类的动画_Ios_Swift_Uiviewanimation - Fatal编程技术网

Ios 使用curveEaseOut设置UIView子类的动画

Ios 使用curveEaseOut设置UIView子类的动画,ios,swift,uiviewanimation,Ios,Swift,Uiviewanimation,我有一个自定义绘制的进度条,我希望以一种比过渡可用选项更平滑的方式设置动画。但它不会像下面那样响应.curveEaseOut。如果我把它改为.transitionCrossSolve,它会工作,但我更喜欢曲线动画。我怎样才能让它工作 @IBOutlet var experienceProgress: experienceBar! func updateProgress() { experienceProgress.progress = 0.5 experienceProgre

我有一个自定义绘制的进度条,我希望以一种比过渡可用选项更平滑的方式设置动画。但它不会像下面那样响应
.curveEaseOut
。如果我把它改为
.transitionCrossSolve
,它会工作,但我更喜欢曲线动画。我怎样才能让它工作

@IBOutlet var experienceProgress: experienceBar!

func updateProgress() {
    experienceProgress.progress = 0.5

    experienceProgress.setNeedsDisplay()

    UIView.transition(with: experienceProgress, 
                      duration: 1.25, 
                      options: UIView.AnimationOptions.curveEaseOut, 
                      animations: {
        self.experienceProgress.layer.displayIfNeeded()
    })
}

@IBDesignable
class experienceBar: UIView {

    var progress:CGFloat = 0

    override func draw(_ rect: CGRect) {
        let color = UIColor(red: 220/255, green: 0, blue: 80/255, alpha: 1.000)

        let rectanglePath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: progress * 132, height: 8.5))
        color.setFill()
        rectanglePath.fill()
    }
}

基本问题是,您的
绘图(:)
是给定时间视图的快照,因此不容易设置动画。要设置
ui视图
对象的动画,如果可以使用可设置动画的属性,则始终是最简单的。作为
ui视图

对多个视图特性的更改可以设置动画,也就是说,更改该特性将创建一个从当前值开始并以指定的新值结束的动画。
UIView
类的以下属性是可设置动画的:

  • frame
  • bounds
  • center
  • 变换
  • alpha
  • backgroundColor
从技术上讲,理论上您可以自己手动制作动画,但通常最好先看看是否可以重构代码以使用这些
UIView
可设置动画的属性之一

幸运的是,在这种情况下,您可以消除
绘制(:)
,并用使用子视图的内容替换它,在子视图中,您可以对反映“完成百分比”部分的子视图的
(可设置动画的属性)设置动画

@IBDesignable
public class CustomProgressView: UIView {
    public var progress: CGFloat = 0 { didSet { updateProgress() } }

    private var progressView: UIView = {
        let progressView = UIView()
        progressView.backgroundColor = UIColor(red: 220/255, green: 0, blue: 80/255, alpha: 1)
        return progressView
    }()

    override public init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

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

    override public func layoutSubviews() {
        super.layoutSubviews()
        updateProgress()
    }

    override public func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        progress = 0.5
    }
}

private extension CustomProgressView {
    func configure() {
        addSubview(progressView)
    }

    func updateProgress() {
        var rect = bounds
        rect.size.width *= progress

        progressView.frame = rect
    }
}
然后你可以做:

UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut, animations: {
    self.progressView.progress = 0.75
}, completion: nil)

一些不相关的观察结果:

  • 我没有完全理解
    progress*132
    的意图。所以我只是假设
    进度
    是介于0.0和1.0之间的一个百分比,并且子视图将覆盖该百分比

  • 我在
    progress
    属性的
    didSet
    中自动更新了子视图。视图控制器(或其他)不应该手动说
    setNeedsDisplay
    或类似的话

  • 我将类名改为以大写字母开头。变量和方法名称以小写字母开头,但类型名称(如类、结构、枚举等)始终以大写字母开头

  • 我注意到您将此
    @IBDesignable
    。如果是这样的话,让
    prepareforPrinterFaceBuilder
    将该值设置为有趣的值通常是很好的,这样您就可以在IB中更好地查看进度视图


  • 感谢您提供非常详细的答案和有用的提示!这正是我想要的。