CALayer, или как закруглить углы, сделать тень и градиент на Swift
В данной статье мы рассмотрим свойство UIView — layer, то есть слой. Это класс CALayer, который в свою очередь имеет ряд весьма полезных свойств, регулируя которые можно изменить внешний вид любого UIView. Самое популярное применение свойств CALayer — это закругление углов (cornerRadius) и тень (shadow), а также рисование градиента (gradient). Как Вы помните, UIView — это базовый класс для всего, что отображается на экране — кнопок, картинок, переключателей и т.д. А это означает, что все свойства, которые мы будем менять в данной статье можно изменить у любого элемента в интерфейсе пользователя
.
Мы создадим проект, в котором сделаем (сверху вниз по картинке): градиент, закругление углов с выделением границы, и закругление углов и тень вокруг кнопки.
Подготовка
Для начала создайте проект в Xcode Single View Application, перейдите в Storyboard и добавьте на контроллер три элемента: два View и одну кнопку. Добавьте цвета для фона контроллера, двух волов View и кнопки, что было удобно с ними работать и различать их. Далее создайте два файла с классами, которые будут наследниками класса UIView. Я назвал классы BlueView и LogoView.
// // proSwift.ru // // BlueView.Swift import UIKit @IBDesignable class BlueView: UIView { }
// // proSwift.ru // // LogoView.Swift import UIKit @IBDesignable class LogoView: UIView { }
Инстркуция @IBDesignable добавлена для того, чтобы просматривать изменения отрисовки для UIView и его подклассов прямо в Storyboard без компиляции приложения и запуска его на симуляторе или реальном устройстве.
Далее каждому из добавленных ранее View в Identity Inspector установите соответствующие классы.
Далее создайте аутлеты для элементов интерфейса.
// // proSwift.ru // import UIKit class ViewController: UIViewController { @IBOutlet weak var blueView: BlueView! @IBOutlet weak var orangeButton: UIButton! @IBOutlet weak var logoView: LogoView! }
Для нашей задачи абсолютно не принципиально расположение элементов, но у меня после добавления констрейнтов получилось так:
Как вы заметили, у меня в LogoView красуется картинка. У вас ее не будет. Я ниже напишу как добавить картину в LogoView. А пока можете приготовить любую квадратную картинку, над которой вы будете ставить эксперименты. Я приведу код файла LogoView, в котором я сделал возможность выбора картинки непосредственно в Interface Builder, т.е. в Storyboard. Именно поэтому в нем реализовано такое количество методов. Однако если внимательно посмотреть, то все вполне логично:
// // proSwift.ru // import UIKit @IBDesignable class LogoView: UIView { let imageView = UIImageView() @IBInspectable var image: UIImage? { didSet { addImage() } } override func awakeFromNib() { super.awakeFromNib() setup() } override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() setup() } func setup () { imageView.frame = CGRectMake(0, 0, 240, 240) imageView.contentMode = .ScaleAspectFit addSubview(imageView) } func addImage() { imageView.image = image } }
Методы awakeFromNib() и prepareForInterfaceBuilder() запускаются единожды: первый при запуске приложения и загрузки UIView из Storybord, второй при переходе в Storyboard для отрисовки изменений непосредственно на сцене Interface Builder. Для нашего LogoView я добавил свойство imageView: UIImgeView для отображения картинки, и свойство image для выбора картинки, которое будет отображать imageView. Метод setup() запускает настройку для imageView.
Свойство image я пометил инструкцией @IBInspectable и установил наблюдателя свойства didSet. Тип @IBInspectable свойства должен быть явно указан, как в нашем случае — мы сказали что оно будет опционалом UIImage (то есть явно указали тип после двоеточия). А при помощи наблюдателя свойства мы устанавливаем картинку в UIImageView.
Вы спросите — зачем все эти сложности? А я вам отвечу — для того, чтобы менять картинку прямо из Storyboard. После всех наших изменений в Storyboard можно обнаружить следующие изменения:
При выборе нашего LogoView в атрибут инспекторе появилась настройка Image в которой можно выбрать любую картинку, которую вы добавите в проект. Добавьте картинку или несколько в проект, и после этого выберите ее из выпадающего списка. Картинка отрисуется прямо на сцене Interface Builder.
Давайте подобные настройки сделаем для blueView. В класс BluewView добавьте следующее:
// // proSwift.ru // import UIKit @IBDesignable class BlueView: UIView { // 1 let gradientLayer = CAGradientLayer() // 2 @IBInspectable var startColor: UIColor = UIColor.blackColor() { didSet { gradientSetup() } } // 3 @IBInspectable var midColor: UIColor = UIColor.blueColor() { didSet { gradientSetup() } } // 4 @IBInspectable var endColor: UIColor = UIColor.whiteColor() { didSet { gradientSetup() } } // 5 override func awakeFromNib() { super.awakeFromNib() setup() } // 6 override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() setup() } // 7 private func setup() { layer.addSublayer(gradientLayer) gradientSetup() } // 8 private func gradientSetup() { } // 9 override func layoutSubviews() { gradientLayer.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) } }
Давайте разберем по пунктам, но для начала, также как и классу LogoView, установим директиву @IBDesignable
- Для нашего класса BlueView мы добавали свойство gradienLayer типа CAGradientLayer и использовали стандартный инициализатор. Задавать свойства для градиенты мы будем именно этому слою, а потом добавим его в иерархию слоев BlueView
- Свойство, в котором мы будем задавать стартовый цвет для градиента.
- Свойство, в котором мы будем задавать средний цвет для градиента.
- Свойство, в котором мы будем задавать конечный цвет для градиента.
- Метод, который вызывается единожды при загрузке View из Storyboard
- Метод, который вызывается единожды для отрисовки непосредственно в Storyboard
- В этом методе мы добавляем слой градиента в иерархию слоев BlueView и вызываем метод, в котором будем устанавливать настройки для градиента
- Непосредственно, метод, в котором мы и будем задавать настройки отображения градиента
- Как и в случае с LogoView . В нашем случае это удобнее всего в методе layoutSubviews(), т.к. размер frame у нас насчитывается из размеров BlueView, в котором он отображается. А при выполнении этого метода размеры BlueView уже известны.
Свойства 2-4 помечены директивой @IBInspectable для отображения в списке Attributes Inspector. Это дает нам возможность выбора цветов мышкой прямо в Interface Builder.
Вся подготовительная работа выполнена и можно приступить непосредственно к настройки параметров отображения.
Следующая часть: CALayer- градиент: CAGradientLayer
Ссылка проекта на Github
Добавить комментарий