UIView, масштабирующийся во время анимации

Вы пытаетесь установить вес слоя без веса (ReLU).

Внутри weights_init вы должны проверить тип слоев перед инициализацией весов. Например:

def weights_init(m):
    if type(m) == nn.Linear:
        m.weight.data.normal_(0.0, 1)

См. Как инициализировать веса в PyTorch? .

6
задан Peter Hosey 8 July 2010 в 22:16
поделиться

3 ответа

Если Core Animation пришлось перезванивать Ваш код для каждого фрейма анимации никогда не будет таким быстрым, как он есть, а анимация пользовательских свойств является давно запрашиваемой функцией и часто задаваемыми вопросами для CA на Mac.

Использование UIViewContentModeRedraw справа трек, а также лучшее, что вы получите от CA. Проблема в том, что с точки зрения UIKit кадр имеет только два значения: значение в начале перехода и значение в конце перехода, и это то, что вы видите. Если вы посмотрите документы архитектуры Core Animation, вы увидите, как CA имеет частное представление всех свойств слоя и их значений, изменяющихся со временем. Вот где происходит интерполяция кадров, и вы не можете получать уведомления об изменениях по мере их возникновения.

Таким образом, единственный способ - использовать NSTimer (или executeSelector: withObject: afterDelay: ) для изменения рамки просмотра с течением времени по старинке.

15
ответ дан 8 December 2019 в 03:28
поделиться

As Duncan indicates, Core Animation won't redraw your UIView's layer's content every frame as it is resized. You need to do that yourself using a timer.

The guys at Omni posted a nice example of how to do animations based on your own custom properties that might be applicable to your case. That example, along with an explanation for how it works, can be found here.

2
ответ дан 8 December 2019 в 03:28
поделиться

Я столкнулся с похожей проблемой в другом контексте, наткнулся на эту тему и нашел предложение Дункана об установке фрейма в NSTimer. Я реализовал этот код для достижения того же самого:

CGFloat kDurationForFullScreenAnimation = 1.0;
CGFloat kNumberOfSteps = 100.0; // (kDurationForFullScreenAnimation / kNumberOfSteps) will be the interval with which NSTimer will be triggered.
int gCurrentStep = 0;
-(void)animateFrameOfView:(UIView*)inView toNewFrame:(CGRect)inNewFrameRect withAnimationDuration:(NSTimeInterval)inAnimationDuration numberOfSteps:(int)inSteps
{
    CGRect originalFrame = [inView frame];

    CGFloat differenceInXOrigin = originalFrame.origin.x - inNewFrameRect.origin.x;
    CGFloat differenceInYOrigin = originalFrame.origin.y - inNewFrameRect.origin.y;
    CGFloat stepValueForXAxis = differenceInXOrigin / inSteps;
    CGFloat stepValueForYAxis = differenceInYOrigin / inSteps;

    CGFloat differenceInWidth = originalFrame.size.width - inNewFrameRect.size.width;
    CGFloat differenceInHeight = originalFrame.size.height - inNewFrameRect.size.height;
    CGFloat stepValueForWidth = differenceInWidth / inSteps;
    CGFloat stepValueForHeight = differenceInHeight / inSteps;

    gCurrentStep = 0;
    NSArray *info = [NSArray arrayWithObjects: inView, [NSNumber numberWithInt:inSteps], [NSNumber numberWithFloat:stepValueForXAxis], [NSNumber numberWithFloat:stepValueForYAxis], [NSNumber numberWithFloat:stepValueForWidth], [NSNumber numberWithFloat:stepValueForHeight], nil];
    NSTimer *aniTimer = [NSTimer timerWithTimeInterval:(kDurationForFullScreenAnimation / kNumberOfSteps)
                                                target:self
                                              selector:@selector(changeFrameWithAnimation:)
                                              userInfo:info
                                               repeats:YES];
    [self setAnimationTimer:aniTimer];
    [[NSRunLoop currentRunLoop] addTimer:aniTimer
                                 forMode:NSDefaultRunLoopMode];
}

-(void)changeFrameWithAnimation:(NSTimer*)inTimer
{
    NSArray *userInfo = (NSArray*)[inTimer userInfo];
    UIView *inView = [userInfo objectAtIndex:0];
    int totalNumberOfSteps = [(NSNumber*)[userInfo objectAtIndex:1] intValue];
    if (gCurrentStep<totalNumberOfSteps)
    {
        CGFloat stepValueOfXAxis = [(NSNumber*)[userInfo objectAtIndex:2] floatValue];
        CGFloat stepValueOfYAxis = [(NSNumber*)[userInfo objectAtIndex:3] floatValue];
        CGFloat stepValueForWidth = [(NSNumber*)[userInfo objectAtIndex:4] floatValue];
        CGFloat stepValueForHeight = [(NSNumber*)[userInfo objectAtIndex:5] floatValue];

        CGRect currentFrame = [inView frame];
        CGRect newFrame;
        newFrame.origin.x = currentFrame.origin.x - stepValueOfXAxis;
        newFrame.origin.y = currentFrame.origin.y - stepValueOfYAxis;
        newFrame.size.width = currentFrame.size.width - stepValueForWidth;
        newFrame.size.height = currentFrame.size.height - stepValueForHeight;

        [inView setFrame:newFrame];

        gCurrentStep++;
    }
    else 
    {
        [[self animationTimer] invalidate];
    }
}

Я обнаружил, что требуется много времени для установки рамки и завершения работы таймера. Возможно, это зависит от того, насколько глубока иерархия представления, на котором вы вызываете -setFrame, используя этот подход. И, вероятно, именно по этой причине в sdk сначала изменяется размер представления, а затем выполняется анимация к началу координат. Или, возможно, есть какая-то проблема в механизме таймера в моем коде, из-за которой производительность снизилась?

Это работает, но очень медленно, возможно, потому что моя иерархия представлений слишком глубокая.

4
ответ дан 8 December 2019 в 03:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: