更新された解決策:主な問題は、速度計算が整数を返す0
ことでし1
たfloat
。結果?ボタンは、起点から終点まで「無限」アニメーション (速度 0 のアニメーション) になっていました。
//////////////////////////////////////
奇妙な:プログラムでビューにいくつかのボタンを描画しています。コードのトラブルシューティング中に、ボタンのフレーム/位置/中心 (場所 A) が実際に表示される場所 (場所 B) と異なることがわかりました。こういう現象は初めて見ました..
(さらに悪いことにhitTest:withEvent:
、ボタン自体は場所 B に表示されているにもかかわらず、フレームに基づいてボタンを使用および返すため、実際には場所 A へのタッチでヒット (およびアクションの実行) を追跡しています。)
注意事項と警告:ボタンの 1 つが正しく表示されます。どうしてか分かりません。アニメーションはフレームからはみ出すため、すべてのボタンが正しくアニメーション化されます。
私は自分のコードに何かが欠けていると確信していますが、何時間もかけて、フレームが間違っていると報告していることを考えると、もっと目が必要です!
図:
+-----------------------+
|(mainV) |
| |
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(sB)||
| +----+|
| +----+|
| |(dW)||
| +----+|
|+---------------------+|
||(mV) ||
|+---------------------+|
+-----------------------+
伝説:
- (mainV) = メイン ビュー/ビュー コントローラー、すべての親ビュー
- (mV) = menuView、(mainV) のサブビュー
- (dW) = drawButton、(mV) のサブビュー、および他のボタンを作成するための「アンカー」
- (sB) = sizeButton のインスタンス、(mV) のサブビュー
hitTest:withEvent:
、スーパービューのフレーム外のタッチを取得するために使用
コードとコメント:
最初にボタンを呼び出して作成する中央ボタン作成メソッド。ほとんどの変数はインスタンス変数です
- (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;
}