更新的解决方案:主要问题是我的速度计算返回一个整数 -0
对于所有情况,除了索引 3 处的对象,它是1
- 尽管被标记为实例化为float
. 结果?按钮在从起点到终点的“无限”动画(速度为 0 的动画)中。
//////////////////////////////////
奇怪:我正在以编程方式在视图上绘制一些按钮,在对代码进行故障排除时,我发现按钮的框架/位置/中心(在位置 A)与它们实际显示的位置(位置 B)不同。这是我第一次遇到这种现象。。
(更糟糕的是,我正在使用hitTest:withEvent:
和返回基于框架的按钮,所以我实际上是在跟踪对位置 A 的触摸(和触发动作),即使按钮本身显示在位置 B 中。)
注意事项和注意事项:其中一个按钮显示正确。我不知道为什么。所有按钮的动画都正确,因为动画超出了它们的帧。
我确定我的代码中遗漏了一些东西,但我已经研究了好几个小时,并且考虑到我的框架报告错误,我需要更多的眼睛!
图表:
+-----------------------+
|(mainV) |
| |
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(dW)||
| +----+|
|+---------------------+|
||(mV) ||
|+---------------------+|
+-----------------------+
传奇:
- (mainV) = 主视图/视图控制器,所有内容的父视图
- (mV) = menuView, (mainV) 的子视图
- (dW) = drawButton、(mV) 的子视图以及我构建其他按钮的“锚点”
- (sB) = sizeButton 的实例,(mV) 的子视图,用于在超级
hitTest:withEvent:
视图的框架之外进行触摸
代码和注释:
中央按钮创建方法,我最初调用和创建按钮的地方,大多数 vars 是实例变量
- (void)addSizeSubButtons {
BOOL showAnimation = NO;
if ([drawSizeButtonsArray count] == 0) {
for (int i = 0; i < kNumberOfDrawSizes; i++) {
// this method is defined below
// short story is it makes 4 buttons and adds them to an array
[self makeSizeButton];
}
showAnimation = YES;
}
// drawSizeButtonsArray is the array from before - see makeSizeButtons below
for (UIButton *sizeButton in drawSizeButtonsArray) {
int buttonIndex = [drawSizeButtonsArray indexOfObject:sizeButton];
// drawButton is my unofficial anchor point - its center is {287.8, -24.25}
// sizing code in general works and I don't believe is at play here
// see (dW) in the diagram above..
[sizeButton setFrame:CGRectMake(0,
0,
drawButton.bounds.size.height * kStackButtonRatio,
drawButton.bounds.size.height * kStackButtonRatio)];
CGPoint position = CGPointMake(drawButton.center.x,
drawButton.center.y - sizeButton.bounds.size.height * (1.1 + buttonIndex));
[sizeButton.layer setPosition:position];
NSLog(@"sizeButton made at %@ named %@",NSStringFromCGPoint(sizeButton.center),sizeButton);
// NSLog Output (all coords relative to (mV) from legend above:
// sizeButton made at {287.8, -66.6} (this is loop #1/sizeButton atIndex:0)
// sizeButton made at {287.8, -105.1} (this is loop #2/sizeButton atIndex:1)
// sizeButton made at {287.8, -143.6} (this is loop #3/sizeButton atIndex:2)
// sizeButton made at {287.8, -182.1} (this is loop #4/sizeButton atIndex:3)
// note: I have tested that the buttons are all different/at different memory addresses
// --------------------
// HOWEVER, visual display locations are as follows:
// button atIndex:0 @ {287.8, -24.25} (remember this is the same as drawButton!)
// button atIndex:1 @ {287.8, -24.25} (also wrong, and also hidden behind drawButton)
// button atIndex:2 @ {287.8, -24.25} (three in a row in the wrong place)
// button atIndex:3 @ {287.8, -182.1} (!! HARK! this one is actually in the right place.. no clue why one is and the other three are not)
[sizeButton.layer setCornerRadius:sizeButton.bounds.size.width / 7.5];
}
// animations are actually working as desired, because they run off the frame
// as soon as the animation kicks off, buttons all appear in the right place
// and take the correct action; still, i will include the core method just in case
if (showAnimation == YES) {
for (UIButton *sizeButton in drawSizeButtonsArray) {
// so my button is moving FROM its anchor TO its actual center
CGPoint origin = drawButton.center;
CGPoint destination = sizeButton.center;
// this is just to create a visual effect
float speed = ( [drawSizeButtonsArray indexOfObject:sizeButton] + 1 ) / [drawSizeButtonsArray count];
// my central animation method, included below
CABasicAnimation *slideButton = [self slideButton:sizeButton
fromPoint:origin
toPoint:destination
atSpeed:speed];
[sizeButton.layer addAnimation:slideButton
forKey:@"slideSizeButtonAnimation"];
}
}
}
从上面调用的 Button Creator Helper/Worker 方法
- (void)makeSizeButton {
UIButton *sizeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[drawSizeButtonsArray addObject:sizeButton];
// button presses
[sizeButton setUserInteractionEnabled:YES];
[sizeButton addTarget:self
action:@selector(drawSizeButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
// TO DO: remove these debug titles and replace with dots
[sizeButton setTitle:[NSString stringWithFormat:@"%d",[drawSizeButtonsArray indexOfObject:sizeButton]]
forState:UIControlStateNormal];
[sizeButton setTitleColor:[UIColor blackColor]
forState:UIControlStateNormal];
[sizeButton setBackgroundColor:[UIColor whiteColor]];
// show it!
[self addSubview:sizeButton];
[self sendSubviewToBack:sizeButton];
}
动画辅助方法
- (CABasicAnimation *)slideButton:(UIButton *)button
fromPoint:(CGPoint)origin
toPoint:(CGPoint)destination
atSpeed:(float)speed{
// now show animation
CABasicAnimation *slideAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
[slideAnimation setDelegate:self];
// from & to values
[slideAnimation setFromValue:[NSValue valueWithCGPoint:origin]];
[slideAnimation setToValue:[NSValue valueWithCGPoint:destination]];
// easing in and out.. oh yeah!
[slideAnimation setDuration:kAnimationTiming / speed];
CAMediaTimingFunction *easeInOut = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[slideAnimation setTimingFunction:easeInOut];
NSLog(@"slide animation from %@ to %@",NSStringFromCGPoint(origin),NSStringFromCGPoint(destination));
// NSLog Output: (all these values are correct/what I intended)
// AND recall that all animations display properly!
// in fact, judging by NSLog, everything is working fine.. but visually it is not
// slide animation from {287.8, -24.25} to {287.8, -66.6} (for button atIndex:0)
// slide animation from {287.8, -24.25} to {287.8, -105.1} (for button atIndex:1)
// slide animation from {287.8, -24.25} to {287.8, -143.6} (for button atIndex:2)
// slide animation from {287.8, -24.25} to {287.8, -182.1} (for button atIndex:3)
return slideAnimation;
}