如何在Swift中旋转UIAlertController

7

我有一个工作中的UIAlertController,但我想将alert.view向左旋转90度。

我该如何实现?以下是我的代码:

let alert = UIAlertController(title: "", message: "Message Sample", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Okay", style: .Default){(action)->() in })
presentViewController(alert, animated: true) {}

我尝试添加:

 alert.view.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))

但是它不起作用。

谢谢!

4个回答

11

使用此代码:

let alert = UIAlertController(title: "", message: "Message Sample", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Okay", style: .Default){(action)->() in })

self.presentViewController(alert, animated: true, completion: {() -> Void in
      alert.view.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))

})

Swift3

let alert = UIAlertController(title: "", message: "Message Sample", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Okay", style: .default){(action)->() in })

    self.present(alert, animated: true, completion: {() -> Void in
        alert.view.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi/2) )

    })

你可以实现这个效果:

enter image description here

更新的答案

 self.presentViewController(alert, animated: true, completion: {() -> Void in
         // alert.view.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))

        UIView.animateWithDuration(1.0, delay: 0, options: .CurveLinear, animations: { () -> Void in
            alert.view.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
        }) { (finished) -> Void in
          // do something if you need
        }

    })

谢谢,它起作用了,但是有一个问题,当警报首次显示时看起来很正常,1秒钟后向左旋转90度。我们该如何解决? - SwiftDeveloper
@SwiftDeveloper - 好的兄弟,我明白了,给我一些时间,我有一个小任务要完成,然后我就开始你的工作。 - Anbu.Karthik
谢谢兄弟,我们需要解决这个问题,我认为这将会帮助很多人! - SwiftDeveloper
@SwiftDeveloper - 兄弟,你可以根据自己的需要更改时间间隔。 - Anbu.Karthik
我把间隔改为0了,不要像第一个代码那样在正常后旋转90度 :( 不要首先打开90度。 - SwiftDeveloper
显示剩余2条评论

2

我认为这个问题可能在FaceID中更加常见。我必须解决这个问题,因为我的应用程序处于横向模式,但是当用户在iPhone上启动应用程序或者使用FaceID进行身份验证时,他们通常处于纵向模式。所以我想根据用户拿手机的方式显示警报。我的解决方案是扩展UIAlertController类,如下所示:

extension UIAlertController {
    open override func viewWillAppear(_ animated: Bool) {
        view.isHidden = true
    }
    override open func viewDidAppear(_ animated: Bool) {
        let appDirection = UIApplication.shared.statusBarOrientation
        let deviceDirection = UIDevice.current.orientation
        var direction:CGFloat = 0
        if deviceDirection == .portrait {
            if appDirection == .landscapeLeft {
                direction = 1.0
            } else if appDirection == .landscapeRight {
                direction = -1.0
            }
        } else if deviceDirection == .portraitUpsideDown {
            if deviceDirection == .landscapeLeft {
                direction = -1.0
            } else if appDirection == .landscapeRight {
                direction = 1.0
            }
        }
        if direction != 0 {
           view.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 2) * direction);
        }
        view.isHidden = false
    }
    open override func viewWillDisappear(_ animated: Bool) {
        view.isHidden = true
    }
}

0

我受到Nico Nierenberg的回答的启发,但是加入了一些核心动画逻辑。这个额外的逻辑是必要的,以便在呈现和解除警报时旋转警报(Nico的原始实现只隐藏警报,这将与传递falseanimated相同)。

我还添加了一个通知监听器,当设备方向改变时调整旋转。

此实现假定您的原始演示仅为纵向。如果您的呈现控制器可以处于其他方向,则需要修复radians方法。

以下是整个类:

import UIKit

class RotatingAlertController : UIAlertController {
    
    private static let animationKey = "rotationHack"
    private static let animationDuration: TimeInterval = 0.3
    private var currentOrientation: UIDeviceOrientation = .portrait
    
    private func radians(for orientation: UIDeviceOrientation) -> CGFloat {
        switch orientation {
        case .landscapeLeft: return CGFloat.pi*0.5
        case .portraitUpsideDown: return CGFloat.pi*1
        case .landscapeRight: return CGFloat.pi*1.5
        default: return 0
        }
    }
    
    private func applyCoreAnimationRotation() {
        let rotationValue = radians(for: currentOrientation)
        let anim = CABasicAnimation(keyPath: "transform.rotation.z")
        anim.duration = 9999
        anim.toValue = rotationValue
        anim.fromValue = rotationValue
        view.layer.add(anim, forKey: RotatingAlertController.animationKey)
    }
    
    private func animatedApplyDeviceRotation() {
        let deviceOrientation = UIDevice.current.orientation
        guard deviceOrientation != currentOrientation &&
              deviceOrientation != .unknown &&
              deviceOrientation != .faceDown &&
              deviceOrientation != .faceUp
        else {
            return
        }
        UIView.animate(withDuration: RotatingAlertController.animationDuration, delay: 0) {
            self.view.transform = CGAffineTransform(rotationAngle: self.radians(for: deviceOrientation))
        }
        currentOrientation = deviceOrientation
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        currentOrientation = UIDevice.current.orientation
        applyCoreAnimationRotation()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        view.layer.removeAnimation(forKey: RotatingAlertController.animationKey)
        self.view.transform = CGAffineTransform(rotationAngle: self.radians(for: currentOrientation))
        animatedApplyDeviceRotation()
        NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
                                               object: nil,
                                               queue: nil) { [weak self] _ in
            self?.animatedApplyDeviceRotation()
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        NotificationCenter.default.removeObserver(self)
        applyCoreAnimationRotation()
    }
}

你可以像这样调用它:

let alert = RotatingAlertController(title: "Title", message: "Message", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)

0
如果您的应用程序支持landscapeRight、landscapeLeft和default(作为portrait),您可以尝试这个方法。
self.present(alertController, animated: false, completion: {
            switch UIDevice.current.orientation {
            case .landscapeRight:
                self.alertController.view.transform=CGAffineTransform(rotationAngle: CGFloat(-Double.pi / 2))
            case .landscapeLeft:
                self.alertController.view.transform=CGAffineTransform(rotationAngle: CGFloat(Double.pi / 2))
            default:
                self.alertController.view.transform=CGAffineTransform.identity
            }
        })

这将根据您的屏幕旋转旋转您的警报视图,而不会产生任何UI动画问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接