我在NSStatusItem对象中有一个自定义视图。此视图显示图标。它也可以显示进度,但是您必须调用[self.statusitemview setProgressValue:theValue]; --我有一组图标,它使用这个值选择正确的图标。
这看起来很不稳定,因为执行的进程并不总是发送更新。所以我想把这个动画化。
我想像其他可可控件一样调用动画:[self.statusItemView动画家setProgressValue:value];
如果有可能的话
做这件事的正确方法是什么?我不想使用NSTimer。
编辑
这些图像使用drawRect:方法绘制。
下面是代码:
- (void)drawRect:(NSRect)dirtyRect
{
if (self.isHighlighted) {
[self.statusItem drawStatusBarBackgroundInRect:self.bounds withHighlight:YES];
}
[self drawIcon];
}
- (void)drawIcon {
if (!self.showsProgress) {
[self drawIconWithName:@"statusItem"];
} else {
[self drawProgressIcon];
}
}
- (void)drawProgressIcon {
NSString *pushed = (self.isHighlighted)?@"-pushed":@"";
int iconValue = ((self.progressValue / (float)kStatusItemViewMaxValue) * kStatusItemViewProgressStates);
[self drawIconWithName:[NSString stringWithFormat:@"statusItem%@-%d", pushed, iconValue]];
}
- (void)drawIconWithName:(NSString *)iconName {
if (self.isHighlighted && !self.showsProgress) iconName = [iconName stringByAppendingString:@"-pushed"];
NSImage *icon = [NSImage imageNamed:iconName];
NSRect drawingRect = NSCenterRect(self.bounds, icon);
[icon drawInRect:drawingRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil];
}
- (void)setProgressValue:(int)progressValue {
if (progressValue > kStatusItemViewMaxValue || progressValue < 0) {
@throw [NSException exceptionWithName:@"Invalid Progress Value"
reason:[NSString stringWithFormat:@"The value %d id invalid. Range {0 - %d}", progressValue, kStatusItemViewMaxValue]
userInfo:nil];
}
_progressValue = progressValue;
[self setNeedsDisplay:YES];
}
- (void)setShowsProgress:(BOOL)showsProgress {
if (!showsProgress) self.progressValue = 0;
_showsProgress = showsProgress;
[self setNeedsDisplay:YES];
}这一定是有可能的。由于来自苹果的标准控件是使用drawRect:绘制的,但是有平滑的动画.
发布于 2012-10-16 01:55:07
要动画自定义属性,需要使视图符合NSAnimatablePropertyContainer协议。
然后,您可以将多个自定义属性设置为可动的(除了NSView已经支持的属性之外),然后只需使用视图的animator代理来动画这些属性:
yourObject.animator.propertyName = finalPropertyValue;除了使动画非常简单外,它还允许您使用NSAnimationContext同时动画多个对象。
[NSAnimationContext beginGrouping];
firstObject.animator.propertyName = finalPropertyValue1;
secondObject.animator.propertyName = finalPropertyValue2;
[NSAnimationContext endGrouping];还可以设置持续时间并提供一个完成处理程序块:
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0.5];
[[NSAnimationContext currentContext] setCompletionHandler:^{
NSLog(@"animation finished");
}];
firstObject.animator.propertyName = finalPropertyValue1;
secondObject.animator.propertyName = finalPropertyValue2;
[NSAnimationContext endGrouping];对于标准NSView对象,如果要向视图中的属性添加动画支持,只需覆盖视图中的+defaultAnimationForKey:方法并返回属性的动画:
//declare the default animations for any keys we want to animate
+ (id)defaultAnimationForKey:(NSString *)key
{
//in this case, we want to add animation for our x and y keys
if ([key isEqualToString:@"x"] || [key isEqualToString:@"y"]) {
return [CABasicAnimation animation];
} else {
// Defer to super's implementation for any keys we don't specifically handle.
return [super defaultAnimationForKey:key];
}
}我创建了一个简单的sample project,它演示了如何使用NSAnimatablePropertyContainer协议同时动画视图的多个属性。
要成功地更新视图,所需做的就是确保在修改任何可动画属性时调用setNeedsDisplay:YES。然后,您可以在drawRect:方法中获取这些属性的值,并根据这些值更新动画。
发布于 2012-10-14 03:49:22
我已经回答了类似的问题,here
你不能用动画师动画自定义属性,但是如果你需要的话,你可以写自定义动画,尽管这不是最好的主意。
更新(自定义动画):
- (void) scrollTick:(NSDictionary*) params
{
static NSTimeInterval timeStart = 0;
if(!timeStart)
timeStart = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval stTime = timeStart;
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval totalTime = [[params valueForKey:@"duration"] doubleValue];
if(currentTime > timeStart + totalTime)
{
currentTime = timeStart + totalTime;
timeStart = 0;
}
double progress = (currentTime - stTime)/totalTime;
progress = (sin(progress*3.14-3.14/2.0)+1.0)/2.0;
NSClipView* clip = [params valueForKey:@"target"];
float startValue = [[params valueForKey:@"from"] floatValue];
float endValue = [[params valueForKey:@"to"] floatValue];
float newValue = startValue + (endValue - startValue)*progress;
[self setProperty:newValue];
if(timeStart)
[self performSelectorOnMainThread:@selector(scrollTick:) withObject:params waitUntilDone:NO];
}
- (void) setAnimatedProperty:(float)newValue
{
NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:self.property], @"from",
[NSNumber numberWithFloat:newValue],@"to",
[NSNumber numberWithFloat:1.0],@"duration",
nil];
[self performSelectorOnMainThread:@selector(scrollTick:) withObject:params waitUntilDone:NO];
}https://stackoverflow.com/questions/12834092
复制相似问题