我将从UI截图开始,更准确地描绘我的问题:
每当我向单元格引入新的价值时,我想为这个最左边的灯泡设置动画,让它看起来像是充满了红色.
这是BadgeView的实现,它基本上是前面提到的最左边的圆圈
class BadgeView: UIView { var coeff:CGFloat = 0.5 override func drawRect(rect: CGRect) { let topRect:CGRect = CGRectMake(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.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中修改的系数.
在我的cellForRowAtIndexPath方法中,我尝试使用带回调的自定义按钮为此形状设置动画
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 })
但它只会打印到控制台
: CGContextSetFillColorWithColor: invalid context 0x0. If you want to see the backtrace,please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
解决方法
cell.pageBadgeView.drawRect(frame)
从UIView上的Apple docs drawRect:
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.
因此,如果您将代码更改为:
cell.pageBadgeView.setNeedsDisplay()
您将摆脱错误并看到badgeView正确填充.但是这不会为它设置动画,因为默认情况下drawRect不可动画.
解决问题的最简单方法是让BadgeView拥有填充颜色的内部视图.我将重构BadgeView如下:
class BadgeView: UIView { private let fillView = UIView(frame: CGRectZero) 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,alpha: 1.0) // Setup filledView backgroundColor and add it as a subview fillView.backgroundColor = UIColor(red: 252.0/255.0,alpha: 1.0) addSubview(fillView) // Update fillView frame in case coeff already has a value updateFillViewFrame() } private func updateFillViewFrame() { fillView.frame = CGRectMake(0,bounds.height*(1-coeff),bounds.width,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.animateWithDuration(4.0,animations:{ () -> Void in self.coeff = coeff }) } else { self.coeff = coeff } } }
在你的按钮回调中你只需要做:
cell.pageBadgeView.setCoeff(1.0,animated: true)