简体   繁体   English

围绕其中心旋转 UIView 保持其大小

[英]Rotate UIView around its center keeping its size

I'm trying to rotate an UIView a few radians but after applying the transformation it doesn't look to be keeping its size.我正在尝试将UIView旋转几个弧度,但在应用转换后,它看起来并没有保持其大小。 What's the proper way to achieve this?实现这一目标的正确方法是什么?

Here's what I'm doing and what I get (Blue box with the arrow is the View I'm trying to rotate -- it should keep same aspect as red box behind):这是我正在做的和我得到的(带箭头的蓝色框是我试图旋转的视图——它应该与后面的红色框保持相同的方面):

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

double rads = DEGREES_TO_RADIANS(240);
CGAffineTransform transform = CGAffineTransformRotate(CGAffineTransformIdentity, rads);
self.arrowView.transform = transform;

在此处输入图片说明

Thanks!谢谢!

I avoid using macros unless necessary.除非必要,我避免使用宏。 This works perfectly well这很好用

float degrees = 20; //the value in degrees
view.transform = CGAffineTransformMakeRotation(degrees * M_PI/180);

Swift + extension are your friends! Swift + 扩展是你的朋友!

// MARK: - UIView Extension -

extension UIView {

    /**
     Rotate a view by specified degrees

     - parameter angle: angle in degrees
     */
    func rotate(angle: CGFloat) {
        let radians = angle / 180.0 * CGFloat.pi
        let rotation = CGAffineTransformRotate(self.transform, radians);
        self.transform = rotation
    }

}

In this way, anywhere in your code:这样,在您的代码中的任何位置:

let view = UIView(frame: CGRectMake(0, 0, 100, 100))
view.backgroundColor = UIcolor.redColor()
view.rotate(angle: 90)

You're probably hitting a problem with Autolayout.您可能遇到了 Autolayout 的问题。 You probably have constraints on the rotated view pinning it to the edges of the superview.您可能对旋转视图有限制,将其固定到超级视图的边缘。 When the transform is applied, Autolayout is updating the view's size to still fit within the superview.应用转换后,Autolayout 会更新视图的大小以仍然适合超级视图。

You can experiment with different constraints (eg pinning the centre of the view to the centre of another view, and pinning the width and height to constant values) or turn Autolayout off for the rotated view, or, if these don't work or don't suit your needs, use a container view which is laid out under Autolayout, and add your rotating view to this, without using Autolayout.您可以尝试不同的约束(例如将视图的中心固定到另一个视图的中心,并将宽度和高度固定为恒定值)或关闭旋转视图的自动布局,或者,如果这些不起作用或不不适合您的需求,请使用在 Autolayout 下布局的容器视图,并将您的旋转视图添加到其中,而不使用 Autolayout。

This can only be done in code - you can make individual views subject to Autolayout or not by setting translatesAutoresizingMasksIntoConstraints to NO (Autolayout on) or YES (Autolayout off).这只能在代码中完成 - 您可以通过将translatesAutoresizingMasksIntoConstraints设置为NO (自动布局打开)或YES (自动布局关闭)来使单个视图服从或不服从自动布局。 You'll need to set the appropriate autoresizing masks if you switch a view from one to the other.如果从一个视图切换到另一个视图,则需要设置适当的自动调整大小蒙版。

Update Luca Davanzo's answer with Swift 4:用 Swift 4 更新 Luca Davanzo 的回答:

/**
 Rotate a view by specified degrees

 - parameter angle: angle in degrees
 */
func rotate(angle: CGFloat) {
    let radians = angle / 180.0 * CGFloat.pi
    let rotation = self.transform.rotated(by: radians)
    self.transform = rotation
}

The CGAffineTransformRotate transformation rotates from an existing affine transform. CGAffineTransformRotate变换从现有的仿射变换旋转。 The fact that you are using CGAffineTransformIdentity might be the issue.您使用CGAffineTransformIdentity的事实可能是问题所在。 You must specify the current transform of your view.您必须指定视图的当前转换。

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
...
double rads = DEGREES_TO_RADIANS(240);
CGAffineTransform transform = CGAffineTransformRotate(self.arrowView.transform, rads);
self.arrowView.transform = transform;

Also, you might want to consider:此外,您可能需要考虑:

self.arrowView.transform = CGAffineTransformMakeRotation(rads);

EDIT : If you can, share what you kind of transformation (animated/inanimate , single/iterative) you want to achieve.编辑:如果可以,请分享您想要实现的转换类型(动画/无生命,单/迭代)。 I believe there might be a better, optimized way of doing this.我相信可能有更好的、优化的方法来做到这一点。

Swift 5:斯威夫特 5:

extension UIView {
    func setTransformRotation(toDegrees angleInDegrees: CGFloat) {
        let angleInRadians = angleInDegrees / 180.0 * CGFloat.pi
        let rotation = self.transform.rotated(by: angleInRadians)
        self.transform = rotation
    }
}

Try with this code:尝试使用此代码:

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

double rads = DEGREES_TO_RADIANS(240);
self.arrowView.layer.transform = CATransform3DMakeRotation(rads, 0, 0, 1);

On Swift 3:在 Swift 3 上:

let degrees: CGFloat = -90
let radians = CGFloat(__sinpi(degrees.native/180.0))
view.transform = CGAffineTransform(rotationAngle: radians)

I'm using -90 because of this specific part of the documentation about the rotationAngle you have to pass to CGAffineTransform :我使用-90是因为您必须传递给CGAffineTransform关于rotationAngle的文档的这一特定部分:

The angle, in radians, by which this matrix rotates the coordinate system axes.此矩阵旋转坐标系轴的角度(以弧度为单位)。 In iOS, a positive value specifies counterclockwise rotation and a negative value specifies clockwise rotation.在 iOS 中,正值指定逆时针旋转,负值指定顺时针旋转。

Swift5斯威夫特5

Rotate UIView Upside down将 UIView 倒置

let degrees:CGFloat = -180 //angle to convert upside down
rotatingUI.transform = CGAffineTransform(rotationAngle: degrees * CGFloat(Double.pi)/180);
    

To my mind you need to calculate the center of your triangle and rotate around this point.在我看来,您需要计算三角形的中心并围绕该点旋转。 Now you rotate the arrow around the center of your square.现在您围绕正方形的中心旋转箭头。

See: One step affine transform for rotation around a point?请参阅: 绕点旋转的一步仿射变换?

I Hope it will help you.我希望它会帮助你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM