2

更新的解决方案:主要问题是我的速度计算返回一个整数 -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;
}
4

1 回答 1

1

如果您禁用动画,是否还会出现此问题?

您是否对任何视图应用了转换?

我要注意的一件事:设置 UIView 的框架然后调整其图层的位置很奇怪。如何使用[sizeButton setCenter:position]而不是访问图层。我不认为这是问题所在,但它可能与它有关。同样,为什么不使用 UIView 的动画方法而不是潜入 CABasicAnimation 领域呢?

于 2012-08-05T16:34:59.063 回答