Ответ 1
Цвет оттенка не анимализуется через общедоступные API. Вы можете обойти это, вручную изменив цвет оттенка на таймер. Вам нужно будет интерполировать промежуточные уровни цвета.
Я пытаюсь анимировать свойство tintColor UIToolbar, чтобы изменить его от одного tintColor к другому.
Вот код, который я пытаюсь сделать. К сожалению, изменение происходит немедленно и не исчезает от зеленого до синего. Это странно, потому что я знаю, что Apple исчезает и "пульсирует" цвета оттенков панели инструментов при привязке или по телефону. Так почему же это не работает?
// set initial tint color
myBottomToolBar.tintColor = [UIColor colorWithRed:0.15 green:0.95 blue:0.15 alpha:0.6];
//animation stuff
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.95];
[UIView setAnimationDelegate:self];
//thing to animate
myBottomToolBar.tintColor = [UIColor colorWithRed:0.15 green:0.35 blue:0.45 alpha:0.6];
//animation stuff
[UIView commitAnimations];
Цвет оттенка не анимализуется через общедоступные API. Вы можете обойти это, вручную изменив цвет оттенка на таймер. Вам нужно будет интерполировать промежуточные уровни цвета.
В будущем, здесь мое поспешное решение для оживления оттенка. Я уверен, что есть более умные способы сделать это с помощью категорий и структуры для значений rgb yadda yadda. Я спешил, ладно?!
Подкласс UITabBarController:
@interface BaseNavigationController : UINavigationController
{
NSTimer * tintTimer;
UIColor * targetColor;
}
-(void)changeTintTo:(UIColor*)color;
-(void)animateTint;
.
-(void)changeTintTo:(UIColor*)color;
{
targetColor = [color retain];
[tintTimer invalidate];
tintTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/30.0 target:self selector:@selector(animateTint) userInfo:nil repeats:YES];
}
-(void)animateTint;
{
UIColor * currentColor = self.navigationBar.tintColor;
CGFloat red, green, blue, alpha;
[currentColor getRed:&red green:&green blue:&blue alpha:&alpha];
CGFloat targetRed, targetGreen, targetBlue, targetAlpha;
[targetColor getRed:&targetRed green:&targetGreen blue:&targetBlue alpha:&targetAlpha];
CGFloat newRed = red + ((targetRed - red)*.2);
UIColor * newColor = [UIColor colorWithRed:newRed
green:green + ((targetGreen - green)*.2)
blue:blue + ((targetBlue - blue)*.2) // the .2 adjusts the fade speed
alpha:1.0];
if(
(newRed < targetRed && newRed >= targetRed-0.01) ||
(newRed > targetRed && newRed <= targetRed+0.01)
)
{
newColor = targetColor;
[targetColor autorelease];
[tintTimer invalidate];
tintTimer = nil;
targetColor = nil;
}
self.navigationBar.tintColor = newColor;
}
NSTimer
, и это настройка - большая работа для простой анимации. Здесь мое решение, использующее диспетчеризацию, я просто затухаю UIBarButtonItem
внутри и вне, изменяя альфа-значение цвета оттенка:
-(void)animateItemToTargetAlpha:(CGFloat)targetAlpha
{
static dispatch_source_t timer = nil;
static CGFloat DURATION = 0.25f;
static CGFloat FPS = 30.f;
dispatch_source_cancel(timer);
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1/FPS * NSEC_PER_SEC,(1ull * NSEC_PER_SEC) / 10);
CGFloat red, green, blue, __block alpha;
[self.navigationItem.rightBarButtonItem.tintColor getRed:&red green:&green blue:&blue alpha:&alpha];
dispatch_source_set_event_handler(timer, ^{
alpha = targetAlpha == 1.0f ? alpha + (1/(FPS * DURATION)) : alpha - (1/(FPS * DURATION));
self.navigationItem.rightBarButtonItem.tintColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
if(alpha >= 1 || alpha <= 0)
{
dispatch_source_cancel(timer);
}
});
dispatch_resume(timer);
}
Линейная кривая может быть немного заметной, но я сначала хочу попробовать CADisplayLink, прежде чем вносить какие-либо изменения.