使用drawrect自定义UIView动画

Posted

技术标签:

【中文标题】使用drawrect自定义UIView动画【英文标题】:Custom UIView animation using drawrect 【发布时间】:2015-03-12 19:43:46 【问题描述】:

我在情节提要中创建了一个 UIView,并链接到一个名为“XXX”的自定义 UIView 类。在drawRect中我写了代码来填充XXX的颜色。从我的视图控制器我正在尝试为 UIView 设置动画。正在填充 XXX(UIView) 中的颜色,但没有动画。这是我的代码。

class XXX: UIView 

  override init(frame: CGRect) 
        super.init(frame: frame)
    

override func drawRect(rect: CGRect) 
var context: CGContextRef = UIGraphicsGetCurrentContext()!
CGContextClearRect(context, rect)
let color = UIColor.greenColor().CGColor
CGContextSetFillColorWithColor(context, color)
CGContextAddRect(context, rect)
CGContextFillPath(context)



myviewcontroller.swift
@IBOutlet var xxxView: XXX!

 override func viewDidLoad() 
        super.viewDidLoad()

        XXX.animateWithDuration(1.0, delay: 0, options:
            UIViewAnimationOptions.Repeat, animations:  () -> Void in
                XXX.setAnimationDuration(1.0)
                self.xxxView = XXX (frame: CGRectMake(0, 0, 100, 100))

            ,completion: nil);
    

我在视图控制器动画中犯了一些错误。想不通。那么,如何为自定义 UIView 设置动画?或者如何对drawrect的内容进行动画处理?

注意:drawRect 被调用并且 rect 被颜色填充但没有动画。 我之前的方法只是在控制器中创建一个 UIView 并通过动画增加宽度。但是,它没有被团队接受。像下面这样的东西,工作正常。

var xxxView = UIView()
xxxView.frame = CGRectMake(0, 10, startingPoint, 20)
xxxView.backgroundColor = UIColor.greenColor()

UIView.animateWithDuration(1.0, delay: 0, options:
            UIViewAnimationOptions.Repeat, animations:  () -> Void in
            UIView.setAnimationDuration(3.0)

            let totalWidth: CGFloat = 50
            let animationWidth: CGFloat = totalWidth - startingPoint

            var frame : CGRect = xxxView.frame;
            frame.size.width = (startingPoint + animationWidth)
            xxxView.frame = frame;
            ,completion: nil);

谢谢!

【问题讨论】:

【参考方案1】:

更新 我明白你现在在问什么,我一开始误解了。您希望在不实际为视图设置动画的情况下对 UIView 的填充进行动画处理(不知道为什么)。

在您的 drawRect 内部而不是使用提供的 rect 变量,使用值为 0 的自定义“currentHeight”变量创建您自己的变量,然后使用动画块或计时器增加您的“currentHeight”变量直到它已满.

您可以使用 CADisplayLink 调用函数来调用“setNeedsDisplay”以触发重绘,因为为自定义变量设置动画不会触发对绘图的更新(尽管也许您可以为另一个变量设置动画来触发它,但这是草率的但可能有效)。

抱歉,我无法提供更好的解释或示例,但我现在不在笔记本电脑旁。


问题是您在动画块内创建了一个全新的 xxxView 实例,而不是为现有实例设置动画。

如果你想让你的视图动画,你需要在你的动画块之外(使用故事板或代码)初始化你现有的 self.xxxView 到你的起点,在你的动画块内部调整你想要动画的值。例如:

 override func viewDidLoad() 
    super.viewDidLoad()
    self.xxxView = XXX(frame:CGRectMake(0,0,100,100) //set starting point here or set it in storyboard
    XXX.animateWithDuration(1.0, delay: 0, options:
        UIViewAnimationOptions.Repeat, animations:  () -> Void in
            XXX.setAnimationDuration(1.0)
            self.xxxView.alpha = 1

        ,completion: nil);

此代码将初始化一个 alpha 为 0 的视图,然后将其设置为 alpha 为 1 的动画,持续时间为 1 秒。

如果你想让它看起来好像被颜色填充了,你可以使用调整视图大小的技巧。这与在动画块中操作现有视图的属性的概念相同。

例子:

override func viewDidLoad() 
 super.viewDidLoad()
    self.xxxView = XXX(frame:CGRectMake(0,0,0,0) //set starting point here or set it in storyboard
    self.xxxView.alpha = 0 
    XXX.animateWithDuration(1.0, delay: 0, options:
        UIViewAnimationOptions.Repeat, animations:  () -> Void in
            XXX.setAnimationDuration(1.0)
            self.xxxView.frame = CGRectMake(0,0,100,100)

        ,completion: nil);

【讨论】:

在我的 drawRect 中,我正在为 uiview 填充颜色。这个填充操作应该是动画的。 我已经用另一个例子更新了答案,你可以操纵大小和位置来获得你想要的效果。我不在电脑前测试,但它应该可以工作,原理就在那里。 如果我按照你的建议去做,那么这就像我之前提到的作为我问题的一部分的方法。 啊,我明白了,对不起,我没有意识到这一点。我已经用一个建议更新了我的答案。 这种思维方式对不对? “在没有实际动画视图的情况下对 UIView 进行动画填充(不知道为什么)”.. 现在我认为这不是正确的方法。因此,在 drawrect 中绘制任何东西并在动画块中为某些东西设置动画。【参考方案2】:

我认为你的问题是当视图加载时,它已经加载了动画。当视图出现时,您希望它具有动画效果。试着把它放在 override func viewDidAppear() 中。

【讨论】:

如果我移动到 viewDidAppear()。 drawRect 已经在 UIView 中填充了颜色,然后尝试制作动画。因为,UIView 存在于故事板中,从那里链接到自定义视图(XXX)。【参考方案3】:

如果您只需要通过动画更改 UIView 的颜色,那么最简单的方法是使用 backgroundColor 属性并在动画块中进行更改,如下所示:

UIView.animateWithDuration(duration:1.0, animations: () -> Void in
    myView.backgroundColor = UIColor.greenColor();
)

请记住,animateWithDuration func 是一个类 func,因此您不会在 UIView 的实例上调用它,而是在类本身上调用它。

在动画drawRect: 方法方面,这更复杂,我无法给你一个明确的答案。一种选择是使用CAAnimation 对象并将其添加到视图的layer 中,用于属性backgroundColor,如下所示:

var animation : CABasicAnimation = CABasicAnimation(keyPath:"backgroundColor")
animation.fromValue = myView.backgroundColor
animation.toValue = UIColor.greenColor
animation.duration = 1.0

myView.layer.backgroundColor = UIColor.greenColor.CGColor

myView.layer.addAnimation(animation, forKey:"backgroundColor")

注意:以上代码未经测试,旨在给出一个不确定的想法。这也假设您想要从一种颜色到另一种颜色的漂亮淡入淡出动画。对于自定义动画,例如从上到下填充,您需要执行其他操作,例如添加子图层并为其大小变化设置动画。

【讨论】:

以上是关于使用drawrect自定义UIView动画的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 UIView 中动画 UIBezierPath 不起作用

如何在 UIView 内设置动画?

我真的需要在自定义 UIView 中使用 drawRect() 吗?

使用 CGAffineTransformScale 自定义 UIView 缩放

即使使用 UIViewContentModeScaleAspectFill 也会调用自定义 UIView drawRect

drawRect 绘制的内容是不是能够使用 UIView 动画制作动画?