2014-01-26 3 views
36

Я пытаюсь повернуть 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; 

enter image description here

Спасибо!

+0

Вы забыли вызвать макрос? Например. CGAffineTransform transform = CGAffineTransformMakeRotation (DEGREES_TO_RADIANS (45)); – Marco

+0

@Marco Извините, я редактирую вопрос. Я не использую макрос, но все еще не работаю так, как предполагалось. –

+0

Ну, вам нужно, потому что параметр для CGAffineTransformMakeRotation находится в радианах. – Marco

ответ

20

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

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

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

+0

Спасибо !. Это именно то, что я искал. Добавление этой строки решило мою проблему: [self.arrowView setTranslatesAutoresizingMaskIntoConstraints: YES]; Разве это не способ визуализировать это или изменить с IB? –

+1

С IB, это все авто макет или ничего автоматического макета. Рад, что это сработало, это было немного догадка, но у меня была такая же проблема пару дней назад. – jrturton

+0

'translatesAutoresizingMaskIntoConstraints' not' translatesAutoresizingMasksIntoConstraints' –

4

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

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

Я получаю точно такой же результат. –

0

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

См: One step affine transform for rotation around a point?

Я надеюсь, что это поможет вам.

+0

Спасибо за ссылку на этот ответ, я попытался реализовать это решение, однако стрелка по-прежнему изменяется после вращения. –

12

Преобразование 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); 

EDIT: Если вы можете, поделиться тем, что вы вроде трансформации (анимированный/неживое, одно/итеративный) вы хотите достичь. Я считаю, что может быть лучший, оптимизированный способ сделать это.

32

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

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

Приятный и простой. –

17

расширение Swift + ваши друзья!

// 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(M_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) 
1

На Swift 3:

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

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

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

3

ответ Update Luca ДаВанзо с Swift 4:

/** 
Rotate a view by specified degrees 

- parameter angle: angle in degrees 
*/ 
func rotate(angle: CGFloat) { 
    let radians = angle/180.0 * CGFloat(Double.pi) 
    let rotation = self.transform.rotated(by: radians) 
    self.transform = rotation 
} 
Смежные вопросы