iOS: кнопки вращаются в неподвижных видах, например в приложении «Камера».

Я пытаюсь создать вид, похожий на верхнюю и нижнюю панели в приложении iPhone Camera. Я не могу получить вид сверху и вид снизу, чтобы остаться в портрете.

Когда я использую - (BOOL)shouldAutorotate, и, как и ожидалось, уведомления о повороте останавливаются. Я попытался обновить ограничения с помощью setNeedsUpdateConstraints, но эффект анимации все еще остается. Я хочу, чтобы представления были заблокированы, а вращались только UIButtons.

Как заставить вращаться только кнопки в представлении, а все остальное оставаться заблокированным?


person Siriss    schedule 25.09.2014    source источник


Ответы (2)


У меня есть UIViewController, который вращает только некоторые из его подвидов при повороте устройства. (Это прекрасно работает в iOS7, но не работает в iOS8.) Вам нужно использовать CGAffineTransform для «ручного поворота» ваших представлений.

Вот код:

@interface VVViewController ()
@property (weak, nonatomic) IBOutlet UIView *pinnedControls;
@property (nonatomic, strong) NSMutableArray *pinnedViews;

@end

@implementation VVViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.pinnedViews = [NSMutableArray array];
    [self.pinnedViews addObject:self.pinnedControls];
}

-(void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    [UIViewController rotatePinnedViews:self.pinnedViews forOrientation:self.interfaceOrientation];
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation) && UIInterfaceOrientationIsLandscape(self.interfaceOrientation))  {
        [UIViewController rotatePinnedViews:self.pinnedViews forOrientation:toInterfaceOrientation];
    }
}

@end

Мы создали категорию в UIViewController для обработки такого поведения. Вот соответствующий код:

@implementation UIViewController (VVSupport)

+ (void)rotatePinnedViews:(NSArray *)views forOrientation:(UIInterfaceOrientation)orientation {
    const CGAffineTransform t1 = [UIViewController pinnedViewTansformForOrientation:orientation counter:YES];
    const CGAffineTransform t2 = [UIViewController pinnedViewTansformForOrientation:orientation counter:NO];
    [views enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
        // Rotate the view controller
        view.transform = t1;
        [view.subviews enumerateObjectsUsingBlock:^(UIView *counterView, NSUInteger idx, BOOL *stop) {
            // Counter-rotate the controlsUIin the view controller
            counterView.transform = t2;
        }];
    }];
}

+ (CGAffineTransform)pinnedViewTansformForOrientation:(UIInterfaceOrientation)orientation counter:(BOOL)counter {
    CGAffineTransform t;
    switch ( orientation ) {
        case UIInterfaceOrientationPortrait:
        case UIInterfaceOrientationPortraitUpsideDown:
            t = CGAffineTransformIdentity;
            break;

        case UIInterfaceOrientationLandscapeLeft:
            t = CGAffineTransformMakeRotation(counter ? M_PI_2 : -M_PI_2);
            break;

        case UIInterfaceOrientationLandscapeRight:
            t = CGAffineTransformMakeRotation(counter ? -M_PI_2 : M_PI_2);
            break;
    }

    return t;
}

@end

Теперь это не работает идеально под iOS8, см. Размер UIView не изменяется при вращении с помощью CGAffineTransform под iOS8 для моего вопроса.

person Paul Cezanne    schedule 25.09.2014
comment
Спасибо! Это работает для первых нескольких поворотов, а затем вид начал перемещаться. Что может привести к тому, что он перестанет работать? я не могу понять - person Siriss; 28.09.2014
comment
Не знаю, обратите внимание на движения вашего устройства и пройдитесь по отладчику при этом. Посмотрите, где что-то пойдет не так. - person Paul Cezanne; 29.09.2014

В Swift 5 и использовании свойства transform для поворота вручную.

override func viewDidLoad() {
    super.viewDidLoad()
    UIDevice.current.beginGeneratingDeviceOrientationNotifications()
    NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange),
        name: UIDevice.orientationDidChangeNotification, object: nil)
}

@objc private func deviceOrientationDidChange() {
    let viewsToRotate = [button1, button2, labelXX, viewXX]
    let rotation = UIDevice.current.orientation.rotationTransform
    viewsToRotate.forEach {
        $0.transform = rotation
    }
}

extension UIDeviceOrientation {
    var rotationTransform: CGAffineTransform {
        switch self {
        case .landscapeLeft: return CGAffineTransform(rotationAngle: .pi/2)
        case .landscapeRight: return CGAffineTransform(rotationAngle: -.pi/2)
        case .portraitUpsideDown: return CGAffineTransform(rotationAngle: .pi)
        default: return .identity
        }
    }
}

У меня есть подробности в моем блоге здесь: https://samwize.com/2019/08/06/how-to-rotate-selected-views-like-camera-app/

person samwize    schedule 06.08.2019