我试图创建一个旋转拨号控制,基本上是一组6位数字,旋转和周围给一个旋转数字表的效果(类似于你的电力/水表,或者扑克机,事实上非常类似于现有的UIPickerView控制,但有一个完全不同的外观和感觉)。
到目前为止,我几乎有它的工作,但我在一个阶段,核心动画是给我的悲伤。
它相当复杂,所以代码片段很难给出一个很好的快照,所以我认为伪代码就足够了。
UIView
s(称为NumberView1、NumberView2等…),控件中每个数字对应一个。
在每个数字里我都有另一个
UIView视图
,这是一个容器视图,称为ContainerView1、2等。。。
然后我有10个
UIImageView
重要提示:我的数字只会向上滚动
这些数字表示向上滚动的5位小数(即2.34677)(例如,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,这是一个为了测试的任意数字。
我叫:
[self animateDecimalPlace: 0
withAnimation: self.dollarSlot1Animation
andContainerView: self.containerViewDollarSlot1];
[self animateDecimalPlace: 1
withAnimation: self.decimalPlace1Animation
andContainerView: self.containerViewDecimalPlace1];
//etc... for all 6 numbers
其中DollarSlot1动画是
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视图
到容器UIView
在上面
最初的10个图像块。
完成滚动之后,我移除动态添加的
UIImageView视图
,并将容器视图的y偏移重新定位回0到-270之间的值(基本上是以相同的数字结束,但删除了所有不必要的图像视图)。
这会产生我想要的平滑动画。而且很有效。相信我:)
我的问题有两个,第一,当动画停止时,核心动画会还原动画,因为我设置了
animation.fillMode = kCAFillModeRemoved;
我不知道如何在动画完成后设置容器层的y偏移,我知道这听起来很奇怪,但是如果我将fillMode属性设置为kCAFillModeForwards,我尝试的任何操作似乎都不会对层产生影响。
谢谢