【问题标题】:Can't draw to several subclassed UIView objects at the same time. Tried many methods不能同时绘制到多个子类 UIView 对象。试过很多方法
【发布时间】:2017-09-07 20:35:56
【问题描述】:

[编辑]

原始问题从下面开始。这里有更多信息

我整天都在处理这个问题,但找不到解决方案。我对 UIView 进行了子类化,并将绘图代码缩减为以下内容。

-(void)drawRect:(CGRect)rect
{


    //// rechargeLevel Drawing
    CGRect rechargeLevelRect = CGRectMake(17.5, 17.75, 64, 64);
    UIBezierPath* rechargeLevelPath = [UIBezierPath bezierPath];
    [rechargeLevelPath addArcWithCenter: CGPointMake(CGRectGetMidX(rechargeLevelRect), CGRectGetMidY(rechargeLevelRect)) radius: rechargeLevelRect.size.width / 2 startAngle: 90 * M_PI/180 endAngle: endAngle * M_PI/180 clockwise: YES];

    [[UIColor redColor] setStroke];
    rechargeLevelPath.lineWidth = 4.5;
    [rechargeLevelPath stroke];

    endAngle++;
    if (endAngle > 359) {
        endAngle = 1;
    }
}

我已经尝试了以下所有方法。

  1. drawRect:使用调用 setNeedsDisplay 的计时器(也尝试过 setNeedsDisplayInRect:

  2. 带有计时器的 CAShapeLayer,该计时器调用绘制形状的方法

  3. 块内的 CAShapeLayer 在延迟后调用,然后自行调用。因为我认为计时器把事情搞砸了。

  4. 创建了 UIView 的第二个子类,代码相同,但标签不同。初始化其中一个仍然不起作用。

  5. 我已经在两个子类之间尝试了上述方法的组合,但仍然没有。

计时器在您启动另一个计时器时停止,或者它全部使用相同的上下文。我不知道。

我已经使用我制作的测试项目创建了一个 GitHub 存储库。它有一个带有六个按钮的 viewController,用于从两个子类初始化上述每个方法并将它们添加到视图中。

GitHub 代码库是:https://github.com/MoseCode/drawTest

[结束编辑]

原始问题如下:

尝试使用计时器同时对多个对象进行自定义 DrawRect 绘图。

我有一个自定义 UIController (WP_BonusController) 设置为接收触摸事件。在控制器被触摸 5 次后,它会禁用事件,直到经过指定的时间。

为了说明充电时间,我从 DrawRect 中画了一个圆形路径。我正在使用 UIGraphicsGetCurrentContext 然后抚摸新路径。

我的问题是当我实例化一堆这些 WP_BonusController 对象时,它们都从 UIGraphicsGetCurrentContext 共享相同的上下文。我检查了对象的 ram 分配,它们都是不同的。但是当我在 drawRect: 中放置一个断点并从 UIGraphicsGetCurrentContext 检查 CGContextRef 时,它们都具有相同的 ram 分配。

当我点击 bonusController1 五次时,计时器启动并开始围绕图标绘制圆圈。它工作正常。

然后我按五次bonusController2 并启动它的计时器,但是当它在drawRect 中绘制上下文时,我从另一个bonusController1 获得相同的上下文。所以画的线已经画了一半了。

这对于任意数量的控制器都是一样的。

有没有一种方法可以创建我自己的不使用 UIGraphicsGetCurrentContext 的干净上下文。我一直在寻找,找不到解决方案。也许我没有正确理解上下文的用法。我需要能够在任何时候单独绘制这些控制器,并且可以同时绘制很多次。

这是我的 drawRect: 被计时器调用的:

-(void)drawRect:(CGRect)rect
{
    _currentAngle = _currentAngle + 1;

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.frame.size.width, self.frame.size.height), NO, 0);


    // General Declarations
    CGContextRef context = UIGraphicsGetCurrentContext();
    // Resize to Target Frame
    CGContextSaveGState(context);
    CGRect resizedFrame = WP_CustomIconsResizingBehaviorApply(WP_CustomIconsResizingBehaviorAspectFill, CGRectMake(0, 0, 100, 100), [self getImageRect]);
    CGContextTranslateCTM(context, resizedFrame.origin.x, resizedFrame.origin.y);
    CGContextScaleCTM(context, resizedFrame.size.width / 100, resizedFrame.size.height / 100);


    //// rechargeLevel Drawing
    CGRect rechargeLevelRect = CGRectMake(17.5, 17.75, 64, 64);
    UIBezierPath* rechargeLevelPath = [UIBezierPath bezierPath];
    [rechargeLevelPath addArcWithCenter: CGPointMake(CGRectGetMidX(rechargeLevelRect), CGRectGetMidY(rechargeLevelRect)) radius: rechargeLevelRect.size.width / 2 startAngle: 90 * M_PI/180 endAngle: _currentAngle * M_PI/180 clockwise: YES];

    [WP_CustomIcons.thirdColor setStroke];
    rechargeLevelPath.lineWidth = 4.5;
    [rechargeLevelPath stroke];
    CGContextRestoreGState(context);

    refillMeter = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self.refillImageView setImage:refillMeter];

}

【问题讨论】:

  • 这个draw方法属于自定义的UIView实现吗?
  • 是的 Reinier,它有点像自定义 UIView。它是 UIControl 的子类,我认为它是 UIView 的子类,并且认为应该没问题。我花了一天时间尝试不同的实现,但无法让它们中的任何一个工作。我将用我尝试过的其他方法来更新我的问题。谢谢。
  • 很抱歉,由于 Irma 飓风,我从星期五开始就无法连接到 SO,我知道你可以应付欢呼声!

标签: ios core-graphics drawrect cgcontext


【解决方案1】:

想通了。最后一个尝试。也许应该是第一个,但出于某种原因,我只是在考虑计时器。

CALayerAnimation

@implementation ThirdTimerView


- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //
    }
    return self;
}

-(UIBezierPath *)samplePath
{
    CGRect rechargeLevelRect = CGRectMake(17.5, 17.75, 64, 64);
    UIBezierPath* rechargeLevelPath = [UIBezierPath bezierPath];
    [rechargeLevelPath addArcWithCenter: CGPointMake(CGRectGetMidX(rechargeLevelRect), CGRectGetMidY(rechargeLevelRect)) radius: rechargeLevelRect.size.width / 2 startAngle: 90 * M_PI/180 endAngle: 450 * M_PI/180 clockwise: YES];

    return rechargeLevelPath;
}


- (void)startAnimation
{
    if (self.pathLayer == nil)
    {
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        shapeLayer.path = [[self samplePath] CGPath];
        shapeLayer.strokeColor = [[UIColor redColor] CGColor];
        shapeLayer.fillColor = nil;
        shapeLayer.lineWidth = 4.5f;
        shapeLayer.lineJoin = kCALineJoinBevel;

        [self.layer addSublayer:shapeLayer];

        self.pathLayer = shapeLayer;
    }

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeTimer"];
    pathAnimation.duration = 3.0;
    pathAnimation.fromValue = @(0.0f);
    pathAnimation.toValue = @(1.0f);

    [CATransaction setCompletionBlock:^{

        [self removeFromSuperview];

    }];

    [self.pathLayer addAnimation:pathAnimation forKey:@"strokeTimer"];
}

@end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    相关资源
    最近更新 更多