1

我正在尝试根据 DCRoundSwitch 对象的值隐藏或显示视图,但 UIView 动画块没有动画 - 更改会立即应用。我还尝试使用 CATransaction 为视图层设置动画,但这些更改也立即应用了。如果相同的动画块被移动到另一个位置(例如,viewWillAppear:),动画效果很好。

非常感谢任何帮助确定动画为什么不起作用的帮助。谢谢!

这是动画代码:

- (void)switchValueChanged:(id)sender
{
    [UIView animateWithDuration:0.33
                     animations:^{
                         self.containerView.alpha = self.switchView.isOn ? 1 : 0;
                     }];
}

作为参考,这里是 DCRoundSwitch 用于更改开关值的代码。animatedYESignoreControlEventsNO

- (void)setOn:(BOOL)newOn animated:(BOOL)animated ignoreControlEvents:(BOOL)ignoreControlEvents
{
    BOOL previousOn = self.on;
    on = newOn;
    ignoreTap = YES;

    [CATransaction setAnimationDuration:0.014];
    knobLayer.gripped = YES;

    // setup by turning off the manual clipping of the toggleLayer and setting up a layer mask.
    [self useLayerMasking];
    [self positionLayersAndMask];

    [CATransaction setCompletionBlock:^{
        [CATransaction begin];
        if (!animated)
            [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
        else
            [CATransaction setValue:(id)kCFBooleanFalse forKey:kCATransactionDisableActions];

        CGFloat minToggleX = -toggleLayer.frame.size.width / 2.0 + toggleLayer.frame.size.height / 2.0;
        CGFloat maxToggleX = -1;


        if (self.on)
        {
            toggleLayer.frame = CGRectMake(maxToggleX,
                                           toggleLayer.frame.origin.y,
                                           toggleLayer.frame.size.width,
                                           toggleLayer.frame.size.height);
        }
        else
        {
            toggleLayer.frame = CGRectMake(minToggleX,
                                           toggleLayer.frame.origin.y,
                                           toggleLayer.frame.size.width,
                                           toggleLayer.frame.size.height);
        }

        if (!toggleLayer.mask)
        {
            [self useLayerMasking];
            [toggleLayer setNeedsDisplay];
        }

        [self positionLayersAndMask];

        knobLayer.gripped = NO;

        [CATransaction setCompletionBlock:^{
            [self removeLayerMask];
            ignoreTap = NO;

            // send the action here so it get's sent at the end of the animations
            if (previousOn != on && !ignoreControlEvents)
                [self sendActionsForControlEvents:UIControlEventValueChanged];
        }];

        [CATransaction commit];
    }];
}
4

3 回答 3

2

与@Matt 谈论隐式事务让我想到...... UIView 的动画方法环绕CATransaction,并且属性更改通常添加到隐式事务中。但是,没有为完成块中所做的更改创建事务,这显然会影响[UIView animateWithDuration]. 我变了

if (previousOn != on && !ignoreControlEvents)
    [self sendActionsForControlEvents:UIControlEventValueChanged];

if (previousOn != on && !ignoreControlEvents)
{
    [CATransaction begin];
    [CATransaction setDisableActions:NO];
    [self sendActionsForControlEvents:UIControlEventValueChanged];
    [CATransaction commit];
}

它有效。([CATransaction setDisableActions:NO]也是必要的)

谢谢各位帮忙。

于 2012-10-22T19:29:38.057 回答
1

我不知道使用 CATransaction 的 DCRoundSwitch 代码中发生了什么以及它是如何工作的。但你可以试试这个:

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.33];

self.containerView.alpha = self.switchView.isOn ? 1 : 0;

[UIView commitAnimations];
于 2012-10-22T15:22:59.040 回答
0

我已经使用了上述奥斯汀解决方案。但无法修复它。

我在下面的代码中使用了这个。哪个工作正常。

请关注这个话题

https://github.com/domesticcatsoftware/DCRoundSwitch/issues/12

你可以去使用这个 DCRoundSwitch 的类,在那个类的 dealloc 方法上放这条线。

 - (void)dealloc
 {
      [self.MyDCRoundSwitch removeTarget:nil
                         action:NULL
                         forControlEvents:UIControlEventAllEvents];
      [super dealloc];
 }
于 2013-03-22T13:44:27.043 回答