1

我在使用 drawRect 时遇到了一个基本问题:任何建议将不胜感激。

应用程序需要在不同的时间绘制各种 .png 图像,有时有动画,有时没有。

我希望坚持的一个设计目标是在 drawRect 中包含代码:非常简单且“愚蠢” - 即只进行绘图而没有其他应用程序逻辑。

要绘制图像,我使用 UIImage 的 drawAtPoint: 方法。由于该方法不以 CGContext 作为参数,因此只能在 drawRect: 方法中调用。所以我有:

- (void)drawRect:(CGRect)rect {

 [firstImage drawAtPoint:CGPointMake(firstOffsetX, firstOffsetY)];

}

一张照片的一切都很好。为了绘制多个图像(随着时间的推移),我采用的方法是维护一个字典数组,每个字典包含一个图像、要绘制的点位置和一个启用/抑制该图像绘制的标志。随着时间的推移,我将字典添加到数组中,并通过 UIView 的 setNeedsDisplay: 方法触发绘图。使用字典数组可以让我随时完全重建整个显示。drawRect: 现在变成:

- (void)drawRect:(CGRect)rect {


 for (NSMutableDictionary *imageDict in [self imageDisplayList]) {
  if ([[imageDict objectForKey:@"needsDisplay"] boolValue]) {
   [[imageDict objectForKey:@"image"] drawAtPoint:[[imageDict objectForKey:@"location"] CGPointValue]];
   [imageDict setValue:[NSNumber numberWithBool:NO] forKey:@"needsDisplay"];
  }
 }
}

还可以。代码简单紧凑。动画这是我遇到问题的地方。第一个问题是我把动画代码放在哪里?我把它放在 UIView 还是 UIViewController 中?如果在 UIView 中,我是把它放在 drawRect: 还是其他地方?因为实际的动画取决于应用程序的整体状态,所以我需要嵌套的 switch 语句,如果放在 drawRect: 中,它看起来像这样:

- (void)drawRect:(CGRect)rect {

 for (NSMutableDictionary *imageDict in [self imageDisplayList]) {
  if ([[imageDict objectForKey:@"needsDisplay"] boolValue]) {

   switch ([self currentState]) {
    case STATE_1:
     switch ([[imageDict objectForKey:@"animationID"] intValue]) {
      case ANIMATE_FADE_IN:
       [self setAlpha:0.0];
       [UIView beginAnimations:[[imageDict objectForKey:@"animationID"] intValue] context:nil];
       [UIView setAnimationDelegate:self];
       [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
       [UIView setAnimationDuration:2];
       [self setAlpha:1.0];
       break;
      case ANIMATE_FADE_OUT:
       [self setAlpha:1.0];
       [UIView beginAnimations:[[imageDict objectForKey:@"animationID"] intValue] context:nil];
       [UIView setAnimationDelegate:self];
       [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
       [UIView setAnimationDuration:2];
       [self setAlpha:0.0];
       break;
      case ANIMATE_OTHER:
       // similar code here
       break;
      default:
       break;
     }
     break;
    case STATE_2:
     // similar code here
     break;
    default:
     break;
   }
   [[imageDict objectForKey:@"image"] drawAtPoint:[[imageDict objectForKey:@"location"] CGPointValue]];
   [imageDict setValue:[NSNumber numberWithBool:NO] forKey:@"needsDisplay"];
  }
 }

 [UIView commitAnimations];

}

此外,为了使多个连续动画正常工作,需要有一个涉及动画委托 animationDidStop: 回调的外部控制机制,它将设置字典中的 needsDisplay 条目以允许/禁止绘制(和动画)。

我们现在的重点是,这一切都开始变得非常丑陋。进一步来说:

  • drawRect:开始迅速膨胀并包含不是“只是绘制”代码的代码
  • UIView 需要对应用程序状态的隐式感知
  • 整个绘图过程现在至少分布在三种方法中

以及这篇文章的重点:我怎样才能做得更好?就整体结构而言,专家们会推荐什么?如何将应用程序状态信息保持在视图之外?我是不是从错误的方向看这个问题。我应该考虑一些完全不同的方法吗?

4

1 回答 1

2

我会从不重新发明核心动画开始……</p>

Bill Dudney 的可能是最好的:Mac OS X 和 iPhone 的核心动画:创建引人注目的动态用户界面

于 2010-06-05T16:17:42.790 回答