Поверните UIView вокруг его центра, сохраняя его размер

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

Вот что я делаю и что получаю (синяя рамка со стрелкой - это вид, который я пытаюсь повернуть - он должен сохранять тот же аспект, что и красная коробка сзади):

#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;

Спасибо!

8 ответов

Решение

Вы, вероятно, столкнулись с проблемой с Autolayout. Вероятно, у вас есть ограничения на повернутый вид, прикрепляющий его к краям суперпредставления. Когда преобразование применено, Autolayout обновляет размер представления, чтобы все еще соответствовать в суперпредставлении.

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

Это может быть сделано только в коде - вы можете сделать отдельные представления подлежащими автоматической разметке или нет, установив translatesAutoresizingMasksIntoConstraints в NO (Autolayout on) или YES (Автопрокат выключен). Вам нужно будет установить соответствующие маски автоматического изменения размера, если вы переключаете представление с одного на другое.

Я избегаю использования макросов без необходимости. Это отлично работает

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

Swift + extension ваши друзья!

// MARK: - UIView Extension -

extension UIView {

    /**
     Rotate a view by specified degrees

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

}

Таким образом, в любом месте вашего кода:

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

Обновите ответ Луки Давандзо со Swift 4:

/**
 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
}

CGAffineTransformRotate преобразование вращается от существующего аффинного преобразования. Тот факт, что вы используете CGAffineTransformIdentity может быть проблема. Вы должны указать текущую трансформацию вашего представления.

#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;

Кроме того, вы можете рассмотреть:

self.arrowView.transform = CGAffineTransformMakeRotation(rads);

РЕДАКТИРОВАТЬ: Если вы можете, поделитесь тем, что вы трансформации (анимированные / неодушевленные, одиночные / итеративные) вы хотите достичь. Я считаю, что может быть лучший, оптимизированный способ сделать это.

Свифт 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
    }
}

Попробуйте с этим кодом:

#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);

Swift5

Повернуть UIView вверх ногами

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

На Свифте 3:

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

я использую -90 из-за этой конкретной части документации о rotationAngle Вы должны перейти к CGAffineTransform:

Угол в радианах, на который эта матрица поворачивает оси системы координат. В iOS положительное значение указывает вращение против часовой стрелки, а отрицательное значение указывает вращение по часовой стрелке.

На мой взгляд, вам нужно рассчитать центр вашего треугольника и вращаться вокруг этой точки. Теперь вы вращаете стрелку вокруг центра вашего квадрата.

Смотрите: Один шаг аффинного преобразования для вращения вокруг точки?

Надеюсь, это поможет вам.

Другие вопросы по тегам