Восстановление CGRect со значениями Transform из NSDictionary - PullRequest
1 голос
/ 08 марта 2019

Мне нужно иметь возможность сохранить кадр после преобразования UIImageView.В приведенном ниже примере исходный кадр - это когда изображение добавляется в суперпредставление.Затем пользователь имеет возможность вращать, масштабировать и панорамировать изображение в любом месте серой области (суперпредставление).

Я беру эти изображения и сохраняю их координаты в NSDictionary (что не является проблемой).Проблема в том, что если я получаю кадр после поворота, кадр полностью отключается.Мне нужно иметь возможность сохранять новый кадр с преобразованием в словаре, чтобы при возвращении пользователя к этому представлению и загрузке изображений кадры и сохраненные преобразования были такими же, как и предполагалось.

Панорамирование

CGPoint translation = [gestureRecognizer translationInView:[object superview]];
if (CGRectContainsPoint(self.frame, CGPointMake([object center].x + translation.x,  [object center].y + translation.y))) {
    [object setCenter:CGPointMake([object center].x + translation.x, [object center].y + translation.y)];
    [gestureRecognizer setTranslation:CGPointZero inView:[object superview]];
}

Поворот

self.transformRotation = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);

[gestureRecognizer view].transform = self.transformRotation;
if ( [gestureRecognizer rotation] != 0 ) {
    self.rotate = [gestureRecognizer rotation];
}
[gestureRecognizer setRotation:0];

Масштабирование

self.transformScale = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
[gestureRecognizer view].transform = self.transformScale;
if ( [gestureRecognizer scale] != 1 ) {
    self.scale = [gestureRecognizer scale];
}
[gestureRecognizer setScale:1];

Использование центральной точки обзора позволяет сохранить изображение ближе к исходному положению, когда оно было сохранено,первый раз загружается.Каждый раз, когда он сохраняется после этого, позиция остается той же, потому что преобразование не изменилось во время этого сеанса.

- (CGPoint)centerOnCanvas {
    CGPoint originalCenter = self.center;
    return originalCenter;
}

- (CGRect)frameOnCanvas {
    return CGRectMake(
        self.preTransformedFrame.origin.x,
        self.preTransformedFrame.origin.y,
        self.preTransformedFrame.size.width,
        self.preTransformedFrame.size.height
    );
}

- (CGRect)preTransformedFrame {
    CGAffineTransform currentTransform = self.transform;
    self.transform = CGAffineTransformIdentity;
    CGRect originalFrame = self.bounds;
    self.transform = currentTransform;
    return originalFrame;
}

enter image description here

ОБНОВЛЕНИЕ: Немноговыкл и немного больше оригинала

enter image description here

1 Ответ

3 голосов
/ 15 марта 2019

Согласно документу Apple для свойства преобразования UIView

Если значение этого свойства отличается от преобразования идентификатора, значение в свойстве фрейма не определено и должнобыть проигнорированным.

Вот почему вы не можете получить frame после изменения transform.

Как я понимаю, после поворота, масштабирования или панорамирования вы хотите сохранитьТекущее состояние восстановить позже.На мой взгляд, все, что вам нужно сделать, это сохранять transform и center из UIImageView каждый раз, когда они меняются.В этом случае вам не нужен frame.

Например, _transformTarget - это ваш UIImageView, чтобы сохранить его текущее состояние, вы можете использовать метод ниже ( Вместо сохранения в NSDictionary, я использую NSUserDefaults. Вы можете изменить его на NSDictionary)

- (void)saveCurrentState {
    [[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGAffineTransform(_transformTarget.transform) forKey:@"_transformTarget.transform"];
    [[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGPoint(_transformTarget.center) forKey:@"_transformTarget.center"];
}

В конце каждого метода обработки жестов сохраните текущее состояние с помощью saveCurrentState.

- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture {
    CGPoint translation = [gesture translationInView:self.view];
    CGPoint newCenter = CGPointMake(_transformTarget.center.x + translation.x, _transformTarget.center.y + translation.y);

    if (CGRectContainsPoint(self.view.frame, newCenter)) {
        _transformTarget.center = newCenter;
        [gesture setTranslation:CGPointZero inView:self.view];

        [self saveCurrentState];  // Save current state when center is changed
    }
}

- (void)handleRotationGesture:(UIRotationGestureRecognizer*)gesture {
    _transformTarget.transform = CGAffineTransformRotate(_transformTarget.transform, gesture.rotation);
    gesture.rotation = 0;

    [self saveCurrentState];  // Save current state when transform is changed
}

- (void)handlePinchGesture:(UIPinchGestureRecognizer*)gesture {
    _transformTarget.transform = CGAffineTransformScale(_transformTarget.transform, gesture.scale, gesture.scale);
    gesture.scale = 1;

    [self saveCurrentState];  // Save current state when transform is changed
}

Теперь информация о UIImageView сохраняется при каждом изменении.В следующий раз, когда пользователь вернется, получите информацию о center и transform из своего словаря и установите их снова.

- (void)restoreFromSavedState {
    NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.transform"];
    CGAffineTransform transform = transformString ? CGAffineTransformFromString(transformString) : CGAffineTransformIdentity;

    NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.center"];
    CGPoint center = centerString ? CGPointFromString(centerString) : self.view.center;

    _transformTarget.center = center;
    _transformTarget.transform = transform;
}

Результат

Для более подробной информации, вы можете взглянуть на мой репо https://github.com/trungducc/stackoverflow/tree/restore-view-transform

...