Swift-颜色填充动画 [英] Swift - Color fill animation

查看:175
本文介绍了Swift-颜色填充动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对ios动画还比较陌生,我相信我为UIView设置动画的方法存在问题。

I'm relatively new to ios animations and I believe there's something wrong with the approach I took to animate UIView.

我将从绘制UI截图开始我的问题更确切地说:

I will start with a UI screenshot to picture my problem more precisely:

有一个带有两个标签和彩色实心圆的tableView单元格

There is a tableView cell with two labels and colorful filled circle

每当我向单元格引入新值时,我都希望对最左侧的灯泡进行动画处理,以使其看起来像是被红色填充。

Anytime I introduce new value to the cell, I'd like to animate this left-most bulb so it looks like it's getting filled with red color.

这是od BadgeView的实现,基本上是前面提到的最左侧的实心圆圈

This is the implementation od BadgeView, which is basically the aforementioned leftmost filled circle

class BadgeView: UIView {

var coeff:CGFloat = 0.5

override func drawRect(rect: CGRect) {
    let topRect:CGRect = CGRectMake(0, 0, rect.size.width, rect.size.height*(1.0 - self.coeff))
    UIColor(red: 249.0/255.0, green: 163.0/255.0, blue: 123.0/255.0, alpha: 1.0).setFill()
    UIRectFill(topRect)

    let bottomRect:CGRect = CGRectMake(0, rect.size.height*(1-coeff), rect.size.width, rect.size.height*coeff)
    UIColor(red: 252.0/255.0, green: 95.0/255.0, blue: 95.0/255.0, alpha: 1.0).setFill()
    UIRectFill(bottomRect)
            self.layer.cornerRadius = self.frame.height/2.0
    self.layer.masksToBounds = true
   }
}

这是我实现不均匀填充的方法-我引入了在viewController中修改的系数。

This is the way I achieve uneven fill - I introduced coefficient which I modify in viewController.

在我的cellForRowAtIndexPath方法内部,我尝试使用带有回调的自定义按钮为该形状制作动画

Inside my cellForRowAtIndexPath method I try to animate this shape using custom button with callback

let btn:MGSwipeButton = MGSwipeButton(title: "", icon: img, backgroundColor: nil, insets: ins, callback: {
        (sender: MGSwipeTableCell!) -> Bool in
        print("Convenience callback for swipe buttons!")
        UIView.animateWithDuration(4.0, animations:{ () -> Void in
            cell.pageBadgeView.coeff = 1.0
            let frame:CGRect = cell.pageBadgeView.frame
            cell.pageBadgeView.drawRect(frame)
        })
        return true
        }) 

但是它什么也没做,只能打印到控制台上

But it does nothing but prints to console


:CGContextSetFillColorWithColor:无效的上下文0x0。如果您想查看回溯,请设置CG_CONTEXT_SHOW_BACKTRACE环境变量。

: CGContextSetFillColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

尽管我很想知道正确的答案和方法,出于教育目的,很高兴知道为什么此代码不起作用。
预先感谢

Although I'd love to know the right answer and approach, it would be great to know, for education purpose, why this code doesn't work. Thanks in advance

推荐答案

问题的错误部分似乎是代码的这一部分:

The error part of the problem seems to be this part of the code:

cell.pageBadgeView.drawRect(frame)

来自 UIView上的Apple文档 drawRect:

From the Apple docs on UIView drawRect:


在视图中调用此方法会首先显示,或者在发生使视图的可见部分无效的事件时显示。您永远不要自己直接调用此方法。要使视图的一部分无效,从而使该部分重新绘制,请调用setNeedsDisplay或setNeedsDisplayInRect:方法。

This method is called when a view is first displayed or when an event occurs that invalidates a visible part of the view. You should never call this method directly yourself. To invalidate part of your view, and thus cause that portion to be redrawn, call the setNeedsDisplay or setNeedsDisplayInRect: method instead.

因此,如果您可以将代码更改为:

So if you'd change your code to:

cell.pageBadgeView.setNeedsDisplay() 

您将摆脱错误,并正确看到badgeView 填充。但是这不会设置动画,因为默认情况下drawRect无法设置动画。

You'll get rid of the error and see the badgeView filled correctly. However this won't animate it, since drawRect isn't animatable by default.

最简单的解决方法是BadgeView具有填充颜色的内部视图。我会这样重构BadgeView:

The easiest workaround to your problem would be for BadgeView to have an internal view for the fill color. I'd refactor the BadgeView as so:

class BadgeView: UIView {
    private let fillView = UIView(frame: .zero)

    private var coeff:CGFloat = 0.5 {
        didSet {
            // Make sure the fillView frame is updated everytime the coeff changes
            updateFillViewFrame()
        }
    }

    // Only needed if view isn't created in xib or storyboard
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    // Only needed if view isn't created in xib or storyboard
    override init(frame: CGRect) {
        super.init(frame: frame)

        setupView()
    }

    override func awakeFromNib() {
        setupView()
    }

    private func setupView() {
        // Setup the layer
        layer.cornerRadius = bounds.height/2.0
        layer.masksToBounds = true

        // Setup the unfilled backgroundColor
        backgroundColor = UIColor(red: 249.0/255.0, green: 163.0/255.0, blue: 123.0/255.0, alpha: 1.0)

        // Setup filledView backgroundColor and add it as a subview
        fillView.backgroundColor = UIColor(red: 252.0/255.0, green: 95.0/255.0, blue: 95.0/255.0, alpha: 1.0)
        addSubview(fillView)

        // Update fillView frame in case coeff already has a value
        updateFillViewFrame()
    }

    private func updateFillViewFrame() {
        fillView.frame = CGRect(x: 0, y: bounds.height*(1-coeff), width: bounds.width, height: bounds.height*coeff)
    }

    // Setter function to set the coeff animated. If setting it not animated isn't necessary at all, consider removing this func and animate updateFillViewFrame() in coeff didSet
    func setCoeff(coeff: CGFloat, animated: Bool) {
        if animated {
            UIView.animate(withDuration: 4.0, animations:{ () -> Void in
                self.coeff = coeff
            })
        } else {
            self.coeff = coeff
        }
    }
}

在按钮回调中,您只需要做:

In your button callback you'll just have to do:

cell.pageBadgeView.setCoeff(1.0, animated: true)

这篇关于Swift-颜色填充动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆