【问题标题】:Odd animation in UINavigationBar (UIBarButtonItem with custom view)UINavigationBar 中的奇怪动画(带有自定义视图的 UIBarButtonItem)
【发布时间】:2015-03-01 02:53:21
【问题描述】:

我正在尝试在UINavigationBar 中添加“基于饼图的倒数计时器视图”。

UIView 子类(巧妙地称为ProgressView)在添加到标准UIView 时可以正常工作。

但是,当我尝试将它用作 UIBarButtonItem 中的 UINavigationBar/UINavigationItem 的自定义视图时,事情变得有些不稳定。

原因是,当计时器倒计时结束时,视图会变成一个绿色圆圈,该圆圈缩小为一个绿点以不那么突兀。

我正在像这样初始化自定义UIBarButtonItem

self.progressView                      = [[ProgressView alloc] initWithFrame:CGRectMake(0, 0, 36, 36)];     
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.progressView];

这是在计时器结束时运行的代码:

[UIView animateWithDuration:1.0f
                      delay:1.0f
                    options:UIViewAnimationOptionCurveEaseInOut
                 animations:^{
                     self.transform = CGAffineTransformScale(self.transform, 0.25f, 0.25f);
                 }
                 completion:nil];

我是否使用这个似乎并不重要:

self.transform = CGAffineTransformScale(self.transform, 0.25f, 0.25f);

或者这个:

self.transform = CGAffineTransformMakeScale(0.25f, 0.25f);

当我通过覆盖 -(void)setFrame:(CGRect)frame 访问器来监视自定义视图的 frame 属性时,我得到以下输出(在 iPhone 6 Plus 上测试):

frame: {{0, 0}, {0, 0}}
frame: {{0, 0}, {36, 36}}
frame: {{358, 4}, {36, 36}} // <-- This displays 3 times for some reason
frame: {{385, 17}, {9, 9}}

现在,很明显,帧宽度的减少(减少 27 个点)导致 UINavigationBar/UINavigationItem 将整个视图向右移动,以在右侧边缘保持一些缓冲区屏幕。我的计算似乎表明它保持了 20 点缓冲区。

如何在不改变框架的情况下为 UIView 的“缩小”设置动画?绘图是如此基本(此时它只是一个绿点),如果有某种方法可以做到这一点,它可以“看起来”缩小。

我会满足于一些绘图技巧,但似乎动画变换会给出最好的外观。

【问题讨论】:

    标签: ios objective-c uiview uibarbuttonitem


    【解决方案1】:

    使用 UIBezierPath / addArcWithCenter 可以画一个圆。

    您可以按如下方式模拟动画: 有一个 UIView 类,它接收你的圆的半径并绘制你的圆。 (我们称她为圈子)

    有一个方法可以启动你想要的动画。 此方法启动一个定时器,用于移除子视图圈(如果存在) 重新分配圆形类,传递新的半径并将其添加为子视图。

    这并不完全是您的情况,但我认为会有所帮助。

    在您的按钮中:

    - (void)drawCircularProgressBarWithMinutesLeft:(NSInteger)minutes secondsLeft:(NSInteger)seconds
    {
        // Removing unused view to prevent them from stacking up
        for (id subView in [self subviews]) {
            if ([subView isKindOfClass:[CircularProgressTimer class]]) {
                [subView removeFromSuperview];
            }
        }
       // Init our view and set current circular progress bar value
        CGRect progressBarFrame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
        self.progressTimerView = [[CircularProgressTimer alloc] initWithFrame:progressBarFrame ];
        [self.progressTimerView setCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2)];
        [self.progressTimerView setPercent:seconds];
    
        // Here, setting the minutes left before adding it to the parent view
        [self.progressTimerView setMinutesLeft:minutes];
        [self.progressTimerView setSecondsLeft:seconds];
        [self addSubview:self.progressTimerView];
        self.progressTimerView = nil;
        [self setNeedsDisplay];
    }
    

    在 UIView (CircularProgressTimer) 中

    - (void)drawRect:(CGRect)rect
    {
        // Create our arc, with the correct angles
        // The initialAngleFactor is the extra angular distance the stroke will cover from
        // angle zero to the desired initial angle. For example, if you want it to start from
        // angle zero, the factor will be zero. In this case, we'll start from 12 o'clock,
        // which is angle 3M_PI/2 or 1.5M_PI
        float initialAngleFactor = 1.5 * M_PI;
        UIBezierPath *bezierPath = [UIBezierPath bezierPath];
        [bezierPath addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2)
                              radius:rect.size.width / 2 - indiceGrossuraLinha
                          startAngle:0 + initialAngleFactor
                            endAngle:(_percent * M_PI) / 30.0 + initialAngleFactor
                           clockwise:YES];
    
        // Are you wondering where the previous formula comes from?
        // (_percent * M_PI) / 30.0 + initialAngleFactor
        // Well, M_PI covers just half of the circle, which can display as much as 30 seconds.
        // That's the number of pieces in which the half circle is divided: 30 on each piece.
        bezierPath.lineWidth = 5;
        [[UIColor colorWithRed:0.03f green:0.64f blue:0.90f alpha:1.00f] setStroke]; 
    //    [[UIColor colorWithRed:0.64f green:0.81f blue:0.99f alpha:1.00f] setStroke];
        [bezierPath stroke];
    }
    

    我的 UIViewcontroller 调用 drawCircularProgressBarWithMinutesLeft 中的计时器

    【讨论】:

    • 我不确定你的意思。你能添加一些代码来解释你的想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2014-03-04
    相关资源
    最近更新 更多