在 drawRect 上动画创建 cgrect 不起作用

Posted

技术标签:

【中文标题】在 drawRect 上动画创建 cgrect 不起作用【英文标题】:Animate creating of cgrect on drawRect not working 【发布时间】:2013-08-11 14:42:16 【问题描述】:

我有一个带有 UIVIewcontroller 的情节提要场景。在这个场景中,我有一个 UIImageview,其中包含背景图像、一个 UIButton 和一个 UIView。

这个 UIView 有一个覆盖的 drawRect 方法:

- (void)drawRect:(CGRect)rect


    CGFloat height = self.bounds.size.height-15; // - 15 for text space

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, rect);

    UIColor *barColor = [UIColor colorWithRed:226.0/255.0 green:178.0/255.0 blue:39.0/255.0 alpha:1.0];

    CGContextSetFillColorWithColor(context, barColor.CGColor);
    CGFloat barWidth = 37.5;
    [UIView animateWithDuration:1.0 animations:^
        int count = 0;
        NSArray *values = [NSArray arrayWithObjects:@1, @0.5, @0.2, @0.7, nil];
        for (NSNumber *num in values) 

            CGFloat x = count * (barWidth + 18);
            CGFloat startY = (height - ([num floatValue] * height));
            CGRect barRect = CGRectMake(x, startY+15, barWidth, [num floatValue] * height);
            CGContextAddRect(context, barRect);
            // save context state first
            CGContextSaveGState(context);
            [self drawWords:[NSString stringWithFormat:@"%@%%",num] AtPoint:CGPointMake(x + (barWidth/2)-10 , startY) color:[UIColor whiteColor]];
            count++;
            // restore context state first
            CGContextRestoreGState(context);

        
    ];
    CGContextFillPath(context);

我尝试过为酒吧的成长设置动画,但没有成功。我的问题是:我怎样才能让这个工作?

问候

----使用新代码更新,但已经无法使用

---图形代码

- (void) initHelper 
    height=0;
    graphBars = [[NSMutableArray alloc] initWithCapacity:0];
     [self performSelector:@selector(animateBars) withObject:NULL afterDelay:0.5];


- (void) animateBars

    for (GraphBar *bar in graphBars)
    
        bar.bottom+=bar.height;
    

    CGFloat barWidth=37.5;
    CGFloat rat = self.frame.size.height*0.95;

    [UIView animateWithDuration:1.0 animations:^

        NSUInteger _index = 0;
        for (GraphBar *bar in graphBars)
        
            bar.frame = CGRectMake(_index*(barWidth+18),  self.frame.size.height-roundf(bar.barValue*rat), barWidth, roundf(bar.barValue*rat));

            _index++;
        
    ];


- (void) layoutSubviews

    [super layoutSubviews];

    CGFloat barWidth=37.5;
    CGFloat rat = self.frame.size.height*0.01;

    NSUInteger _index = 0;
    for (GraphBar *bar in graphBars)
    
        bar.frame = CGRectMake(_index*(barWidth+18),  self.frame.size.height-roundf(bar.barValue*rat), barWidth, roundf(bar.barValue*rat));

        _index++;

    

---条形图代码

- (void)drawRect:(CGRect)rect


    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, rect);

    UIColor *barColor = [UIColor colorWithRed:226.0/255.0 green:178.0/255.0 blue:39.0/255.0 alpha:1.0];

    CGContextSetFillColorWithColor(context, barColor.CGColor);

    CGContextAddRect(context, rect);

    CGContextFillPath(context);

【问题讨论】:

【参考方案1】:

不要简单地使用+animateWithDuration:animations: 便捷方法,而是使用更详细的+animateWithDuration:delay:options:animations:completion: 方法,它允许您传递UIViewAnimationOptionAllowAnimatedContent 选项。然后在 animations 块中更改视图的高度,让视图和条形高度在动画期间增长。

此选项专门用于告诉 CoreAnimation 在动画期间重绘您的内容(在动画的每一步调用 drawRect:)。没有它,动画是在快照图像上完成的。


来自UIView class Reference 文档:

UIViewAnimationOptionAllowAnimatedContent

通过动态更改属性值和重绘视图来动画化视图。如果此键不存在,视图将使用快照图像进行动画处理。


或者,您可以改为为每个条形图使用一个 UIView,并使用 +animateWithDuration:animations: 为这些条形框架设置动画,而不是使用 CoreGraphics 绘制它们(因为 UIView 动画方法旨在为查看 (frame, alpha, ...) 及其 subviews,主要不是为使用 CoreGraphics 完成的绘图设置动画)

【讨论】:

我试着照你说的做,但没有用。我用新代码编辑了我的问题 当然不行。你为什么将animateWithDuration:… 方法调用...放在drawRect: 方法中?这根本没有意义!您应该改为在外部调用它,CoreAnimation 将确保为视图高度的变化设置动画……并且在您指定上述选项时在每一帧绘制视图。 drawRect: 只负责绘制一个帧/状态。 我创建了函数 -(void)anim 并更新了有问题的代码,然后在 viewController 的 viewDidLoad 中调用了这个函数,但我无法查看动画,只有高度 0 到最大值的变化瞬间改变。为什么? 我不明白:您最新的代码更新中的height 变量是什么?然后完全忽略和丢失的局部变量?! (或者稍后在您的drawRect 代码中使用的实例变量?在最新的情况下,这就是它之前解释的工作方式。那是UIViewframe 的变化将被动画化,而不是做作任何height 任意变量!(您应该真的阅读与CoreAnimation 和动画属性相关的编程指南!) 感谢您的帮助,我已经进行了所有更改,但仍然无法正常工作..我将每个条形图作为一个独立的简单视图(一个矩形),然后在我制作一个带有所有条形图的 graphView视图作为子视图..但是栏没有长大...更新的代码有问题更新

以上是关于在 drawRect 上动画创建 cgrect 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 CAGradientLayer 和 drawRect:(CGRect) 绘制顺序

动画 UIView setFrame 在每个动画帧上强制 drawRect

如何创建带有红色角的 UILabel?

如何正确使用 DrawRect

drawRect中的UILabel不绘制

通过循环 drawRect 动画自定义贝塞尔路径