Я пытаюсь создать вращающийся диск управления, в основном набор из 6 цифр, которые вращаются вокруг и вокруг, чтобы дать эффект счетчика вращающихся чисел (аналогично вашим счетчикам мощности / воды или, возможно, покерному автомату, на самом деле оченьпохож на существующий элемент управления UIPickerView, но с совершенно другим внешним видом и ощущением).
Пока у меня почти все работает, но я нахожусь на этапе, когда основная анимация доставляет мне горе.
Это довольно сложно, поэтому фрагменты кода было бы сложно дать хороший снимок происходящего, поэтому я думаю, что псевдокода будет достаточно.
Во-первых, с точки зрения настройки представления, у меня есть 6 отдельных UIView
s (называемый NumberView1, NumberView2 и т. Д.), Каждый для каждого числа в элементе управления.
Внутри каждого NumberViewX у меня есть еще один UIView
, представляющий собой контейнер, называемый ContainerView1, 2 и т. Д. *
У меня по 10 UIImageView
s, сложенных поверх каждогодругие с разными смещениями Y.Все эти изображения 30х30, что делает его красивым.Сначала 9, затем 8 со смещением y 30, затем 7 со смещением y 60 и т. Д. ... вплоть до 0 со смещением y 270.
ВАЖНОЕ ПРИМЕЧАНИЕ: Мои числатолько прокрутка вверх
Числа представляют собой 5-значное десятичное число (т. е. 2,33477), которое прокручивается вверх (например, до 2,61722).
У меня также есть несколько словарей, которыеудерживать текущее числовое значение для каждого числа и смещения для каждого числа:
NSArray *offsets = [[NSArray alloc] initWithObjects:
[NSNumber numberWithInt:0], //9
[NSNumber numberWithInt:-30], //8
[NSNumber numberWithInt:-60], //7
[NSNumber numberWithInt:-90], //6
[NSNumber numberWithInt:-120], //5
[NSNumber numberWithInt:-150], //4
[NSNumber numberWithInt:-180], //3
[NSNumber numberWithInt:-210], //2
[NSNumber numberWithInt:-240], //1
[NSNumber numberWithInt:-270], //0
nil];
NSArray *keys = [[NSArray alloc] initWithObjects:
[NSNumber numberWithInt:9],
[NSNumber numberWithInt:8],
[NSNumber numberWithInt:7],
[NSNumber numberWithInt:6],
[NSNumber numberWithInt:5],
[NSNumber numberWithInt:4],
[NSNumber numberWithInt:3],
[NSNumber numberWithInt:2],
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:0], nil];
offsetDict = [[NSDictionary alloc] initWithObjects:offsets forKeys:keys];
[currentValuesForDecimalPlace setObject:[NSNumber numberWithInt:2] forKey: [NSValue valueWithNonretainedObject: self.containerViewDollarSlot1]];
[currentValuesForDecimalPlace setObject:[NSNumber numberWithInt:8] forKey: [NSValue valueWithNonretainedObject: self.containerViewDecimalPlace1]];
[currentValuesForDecimalPlace setObject:[NSNumber numberWithInt:3] forKey: [NSValue valueWithNonretainedObject: self.containerViewDecimalPlace2]];
[currentValuesForDecimalPlace setObject:[NSNumber numberWithInt:3] forKey: [NSValue valueWithNonretainedObject: self.containerViewDecimalPlace3]];
[currentValuesForDecimalPlace setObject:[NSNumber numberWithInt:8] forKey: [NSValue valueWithNonretainedObject: self.containerViewDecimalPlace4]];
[currentValuesForDecimalPlace setObject:[NSNumber numberWithInt:5] forKey: [NSValue valueWithNonretainedObject: self.containerViewDecimalPlace5]];
Теперь для логики я начну с установки свойств слоя ContainerView для определенных смещений Y, которые будут перемещать текущие числа вих правильные места, например, так:
self.containerViewDollarSlot1.layer.transform = CATransform3DTranslate(self.containerViewDollarSlot1.layer.transform, 0, -210, 0);
self.containerViewDecimalPlace1.layer.transform = CATransform3DTranslate(self.containerViewDecimalPlace1.layer.transform, 0, -30, 0);
self.containerViewDecimalPlace2.layer.transform = CATransform3DTranslate(self.containerViewDecimalPlace2.layer.transform, 0, -180, 0);
self.containerViewDecimalPlace3.layer.transform = CATransform3DTranslate(self.containerViewDecimalPlace3.layer.transform, 0, -180, 0);
self.containerViewDecimalPlace4.layer.transform = CATransform3DTranslate(self.containerViewDecimalPlace4.layer.transform, 0, -30, 0);
self.containerViewDecimalPlace5.layer.transform = CATransform3DTranslate(self.containerViewDecimalPlace5.layer.transform, 0, -120, 0);
, который покажет числа, 2.83385, который является произвольным числом для тестирования ради.
Затем я ввожу другое значение в текстовое поле и нажимаюкнопка «go», которая запускает логику анимации, где я получаю трудности в Core Animation (как следует из названия)
Я звоню:
[self animateDecimalPlace: 0
withAnimation: self.dollarSlot1Animation
andContainerView: self.containerViewDollarSlot1];
[self animateDecimalPlace: 1
withAnimation: self.decimalPlace1Animation
andContainerView: self.containerViewDecimalPlace1];
//etc... for all 6 numbers
, где dollarSlot1Animation - это CABasicAnimation
ивар
Метод определен ниже:
- (void) animateDecimalPlace: (int) decimalIndex withAnimation: (CABasicAnimation*)animation andContainerView: (UIView*) containerView{
NSRange decimalRange = {decimalIndex == 0 ? 0 : 2,
decimalIndex == 0 ? 1 : decimalIndex};
double diff = 0;
if (decimalIndex == 0)
{
int decimalPartTarget = [[[NSString stringWithFormat:@"%f", targetNumber] substringWithRange: decimalRange] intValue];
int decimalPartCurrent = [[[NSString stringWithFormat:@"%f", currentValue] substringWithRange: decimalRange] intValue];
diff = decimalPartTarget - decimalPartCurrent;
}
else {
double fullDiff = targetNumber - currentValue;
diff = [[[NSString stringWithFormat:@"%f", fullDiff] substringWithRange: decimalRange] doubleValue];
}
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeRemoved;
animation.duration = 5.0;
NSNumber *n = [currentValuesForDecimalPlace objectForKey:[NSValue valueWithNonretainedObject: containerView]];
NSNumber *offset = (NSNumber*)[offsetDict objectForKey: n];
int rotations = [self setupNumberForAnimation: diff decimalIndex: decimalIndex forContainer: containerView];
int finalOffset = (rotations*30)+([offset intValue]);
CATransform3D translation = CATransform3DMakeTranslation(0, finalOffset, 0);
animation.fromValue = [NSValue valueWithCATransform3D:containerView.layer.transform];
animation.toValue = [NSValue valueWithCATransform3D:translation];
animation.delegate = self;
[containerView.layer addAnimation: animation forKey: [NSString stringWithFormat:@"%i", decimalIndex] ];
}
Как вы можете видеть (или, возможно, нет :)), я рассматриваю каждое число в основном независимо, и говорю ему перевести в новую позицию Y,но вы, возможно, заметили там метод с именем setupNumberForAnimation
, который является еще одним крупным методом, который динамически добавляет больше UIImageView
s к контейнеру UIView над начальными 10 фрагментами изображения.
Например, есть 10 плиток, с которых нужно начать, если я хочу прокрутить шкалу ВВЕРХ на 21 точку (например, от 3 до 24), мне нужно добавить 15 новых чисел выше 9, затеманимируйте перевод представления контейнера до самой верхней части изображения.
После того, как прокрутка сделана, я удаляю динамически добавленные UIImageView
s и переставляю смещение по оси y представления контейнера обратно к значениюв пределах от 0 до -270 (по сути, заканчивая тем же номером, но удаляя все ненужные изображения).
Это дает плавную анимацию, которая будет после.И это работает.Поверьте мне:)
Моя проблема двоякая, во-первых, когда анимация останавливается, Core Animation отменяет изменения анимации в слое, потому что я установил animation.fillMode = kCAFillModeRemoved;
Я не мог понять, как после завершения анимации, чтобыустановите смещение y слоя контейнера, я знаю, это звучит странно, но если у меня установлено свойство fillMode, равное kCAFillModeForwards, то все, что я пробовал, казалось, не оказало влияния на слой.
Во-вторых, когда анимация останавливается иизменения отменяются, между моментом, когда анимация восстанавливает перевод, возникает крошечная вспышка, и я не могу понять, как обойти это.
Я знаю, что здесь есть куча деталей и специфичности, но любая помощь или идеи о том, как этого добиться, будут очень благодарны.
Большое спасибо