Моим решением является создание настраиваемого контроллера представлений с настраиваемой модальной презентацией на основе иерархии дочерних элементов-контроллеров.
Мои предложения для анимации:
animateWithDuration:(animated ? 0.6 : 0.0)
delay:0.0
usingSpringWithDamping:1.f
initialSpringVelocity:0.6f
options:UIViewAnimationOptionCurveEaseOut
Он будет выглядеть точно так же, как анимация модального представления по умолчанию в iOS7 / 8.
Существует несколько различных преобразований, которые вы можете выполнять на слое, но основными являются
Чтобы выполнить преобразования в CALayer
, вы устанавливаете свойство слоя transform
к типу CATransform3D
. Например, чтобы перевести слой, вы должны сделать что-то вроде этого:
myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)
Слово Make
используется в имени для создания исходного преобразования: CATransform3D Make Translation. Последующие преобразования, которые применяются, опускают Make
. См., Например, это вращение с последующим переводом:
let rotation = CATransform3DMakeRotation(CGFloat.pi * 30.0 / 180.0, 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)
Теперь, когда у нас есть основа для того, как сделать преобразование, давайте рассмотрим некоторые примеры того, как сделать каждое из них. Однако сначала я покажу, как настроить проект на случай, если вы тоже захотите поиграть с ним.
Для следующих примеров я настроил приложение Single View и добавил UIView
с голубым фоном в раскадровку. Я подключил вид к контроллеру вида с помощью следующего кода:
import UIKit
class ViewController: UIViewController {
var myLayer = CATextLayer()
@IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// setup the sublayer
addSubLayer()
// do the transform
transformExample()
}
func addSubLayer() {
myLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
myLayer.backgroundColor = UIColor.blue.cgColor
myLayer.string = "Hello"
myView.layer.addSublayer(myLayer)
}
//******** Replace this function with the examples below ********
func transformExample() {
// add transform code here ...
}
}
Существует много различных видов CALayer
, но я решил использовать CATextLayer
, чтобы преобразования будут более ясными визуально.
Преобразование перевода перемещает слой. Основной синтаксис:
CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)
, где tx
- это изменение координат x, ty
- это изменение y, а tz
- это изменение z.
Пример
В iOS источник системы координат находится в верхнем левом углу поэтому, если мы хотим переместить слой на 90 пунктов вправо и на 50 пунктов вниз, мы сделаем следующее:
myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)
Примечания
transformExample()
в коде проекта выше. tz
установлено значение 0
. Преобразование масштаба растягивает или сжимает слой. Основной синтаксис:
CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)
, где sx
, sy
и sz
- это числа, на которые масштабируются (умножаются) координаты x, y и z соответственно.
Пример
Если мы хотим вдвое увеличить ширину и утроить высоту, мы сделал бы следующее
myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)
Примечания
Преобразование вращения вращает слой вокруг точки привязки (по умолчанию центр слоя). Основной синтаксис:
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)
, где angle
- это угол в радианах, что слой должен вращаться, а x
, y
и z
- оси, вокруг которых вращается. Установка оси в 0 отменяет вращение вокруг этой конкретной оси.
Пример
Если бы мы хотели повернуть слой по часовой стрелке на 30 градусов, мы бы сделали следующее :
let degrees = 30.0
let radians = CGFloat(degrees * Double.pi / 180)
myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)
Примечания
x
и y
в 0.0
и в z
в 1.0
. z
в -1.0
. Чтобы объединить несколько преобразований, мы могли бы использовать конкатенацию, подобную этой
CATransform3DConcat(a: CATransform3D, b: CATransform3D)
Однако, мы просто будем делать одно за другим. Первое преобразование будет использовать Make
в своем имени. Следующие преобразования не будут использовать Make
, но они будут принимать предыдущее преобразование в качестве параметра.
Пример
На этот раз мы объединяем все три из предыдущих преобразований.
let degrees = 30.0
let radians = CGFloat(degrees * Double.pi / 180)
// translate
var transform = CATransform3DMakeTranslation(90, 50, 0)
// rotate
transform = CATransform3DRotate(transform, radians, 0.0, 0.0, 1.0)
// scale
transform = CATransform3DScale(transform, 0.5, 3.0, 1.0)
// apply the transforms
myLayer.transform = transform
Примечания
Мы сделали все наши преобразования выше, не меняя точку привязки. Однако иногда необходимо изменить его, например, если вы хотите вращаться вокруг какой-либо другой точки, кроме центра. Тем не менее, это может быть немного сложно.
Якорная точка и положение находятся в одном и том же месте. Точка привязки выражается в единицах системы координат слоя (по умолчанию 0.5, 0.5
), а позиция выражается в системе координат суперслоя. Они могут быть установлены следующим образом
myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
myLayer.position = CGPoint(x: 50, y: 50)
Если вы устанавливаете опорную точку только без изменения положения, то рамка изменяется таким образом, что положение будет в правильном месте. Точнее, кадр пересчитывается на основе новой точки привязки и старой позиции. Это обычно дает неожиданные результаты. В следующих двух статьях это прекрасно обсуждается.