ContainerController компонент UI пользовательского интерфейса. Это копия свайп-панели из приложения AppleMaps
Что он может:
Анимировано перемещаться на 3 позиции: (Верх / Середина / Вниз)
Перемещаться программно 2 позиции: (Скрыть / Пользовательский)
Можно настраивать позиции
Можно настраивать позиции отдельно для ландшафтного разворотаДобавлять несколько ContainerController (друг на друга) в одном контроллере
Таким образом можно осуществлять переход между ними.Управлять панелью с помощью жеста PanGesture или свайпом (вертикально)
Добавлять любой тип ScrollView: TableView / CollectionView / TextView
и управлять панелью за счет скролаМожно закреплять HeaderView на вверху / и FooterView внизу
Настройка вьюшки панели ContainerView:
- Изменять окружность углов cornerRadius
- Добавлять тень контейнера
- Фон:
1) Добавлять цвет
2) Размытие Blur Effects (может потребоваться для темной темы)
3) ПрозрачностьПри поднятии наверх, можно включить добавление тени фона позади панели
1) Можно настраивать левые / правые отступы
2) И настраивать левые / правые отступы для ландшафтного разворота
Превью
Копия приложения Apple Maps
Видно что в 1 контейнере SearchBar закреплен на верхушке, а под ним tableView
А в 3 контейнере
TabBar находится внизу,
и тоже неподвижен, в открытом состоянии контейнера
- Для этого создан HeaderView / FooterView
Экран демонстрация
Полных настроек
Создание множества компонентов в одном контроллере
Добавить готовые ScrollView: TableView / CollectionView / TextView
Добавить готовые HeaderView / FooterView
Изменить позиции
Переместиться программно в позицию
Добавить цвет / блюр фона
Добавить тени
Добавить отступы (для ландшафтной оринтации отдельно)
И остальные параметры
Копия приложения Apple Maps
Перевернутый экран
Ландшафтная ориентация
Применение Темной темы
Для это добавлен параметр Blur
.dark .light .extraLight
О проекте
Примеры использования компонента в популярных приложениях.
Используется в разных категориях приложений:
Карты / Меню / Плеер Музыка / Маркет / Спортивные новости / Такси / Финансы Банки Акции / Кошельки / Аналитика / Заметки
Оповещения / Всплывающие окна / Уведомления (Alerts / Popups / Notifications)
Функции
-
-
Настройте макет с помощью создания подкласса
ContainerLayout
при инициализацииИли создайте объект
ContainerLayout
-
Изменить
CornerRadius
Добавить слой
Shadow
Добавить
Blur
-
ContainerController
Delegate
Требования
✏️ ContainerController написан на Swift 5.0+. Его можно собрать в Xcode 11 или более поздней версии. Совместим с iOS 13.0+.
Установка
CocoaPods
ContainerControllerSwift доступен через CocoaPods. Чтобы установить его, просто добавьте следующую строку в свой Podfile:
pod 'ContainerControllerSwift'
Swift Package Manager with Xcode 11
dependencies: [
.package(url: "https://github.com/mrustaa/ContainerController.git")
]
Следуйте этому документу.
Примеры дизайна
Дизайны заимствованы с Dribbble
Для получения дизайна необходимо добавить ветку ui_examples
git clone https://github.com/mrustaa/ContainerController.git
cd ContainerController/
git checkout ui_examples
Видео
Авторы дизайн ui URL-адресов:
Плеер Музыка
YoutubeMusic
Магазин Покупка
Выбор товаров
Акции
Финансы
Банки
Начало работы
import UIKit
import ContainerControllerSwift
class ViewController: UIViewController, ContainerControllerDelegate {
var container: ContainerController!
override func viewDidLoad() {
super.viewDidLoad()
// Create ContainerController Layout object
let layout = ContainerLayout()
layout.startPosition = .hide
layout.backgroundShadowShow = true
layout.positions = ContainerPosition(top: 70, middle: 250, bottom: 70)
// Create ContainerController object, along with the container.view
// Pass the current UIViewController
let container = ContainerController(addTo: self, layout: layout)
container.view.cornerRadius = 15
container.view.addShadow()
// Create subclass scrollView
let tableView = UITableView()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate = self
tableView.dataSource = self
// Add scrollView to container
container.add(scrollView: tableView)
// Finishing settings ContainerController,
// Animated move position Top
container.move(type: .top)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// Remove the subviews ContainerController
container.remove()
container = nil
}
}
Действие
Анимированное перемещение к позициям
Основные позиции 3 Можно перемещаться свайпом жестом между ними
Вверх | .top
Середина | .middle
Вниз | .bottom
Остальные 2 Можно перемещать только программно
Скрыть | .hide (Скрыть за пределы экрана)
Пользовательский | .custom (Пользовательская установленная позиция)
container.move(type: .top)
container.move(type: .middle)
container.move(type: .bottom)
container.move(type: .hide)
container.move(type: .custom)
Добавление кастомных вьюшек в ContainerController
Добавлять ScrollView
let tableView = UITableView()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.backgroundColor = .clear
tableView.tableFooterView = UIView()
tableView.delegate = self
tableView.dataSource = self
// Add scrollView to container
container.add(scrollView: tableView)
Delegate self ?
Если вы реализуете делегат ScrollView (TableView, CollectionView, TextView) для self, то вам нужно вызвать 4 функции в ContainerController
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
container.scrollViewDidScroll(scrollView)
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
container.scrollViewWillBeginDragging(scrollView)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
container.scrollViewDidEndDecelerating(scrollView)
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
container.scrollViewDidEndDragging(scrollView, willDecelerate: decelerate)
}
}
extension ViewController: UITableViewDelegate {
...
}
extension ViewController: UITableViewDataSource {
...
}
Добавить HeaderView
let headerView = ExampleHeaderGripView()
headerView.height = 20
container.add(headerView: headerView)
Добавить FooterView
let tabBarView = HeaderTabBarView()
tabBarView.height = 49.0
container.add(footerView: tabBarView)
Добавить кастомное вью CustomView
// Add custom shadow
let layer = container.view.layer
layer.shadowOpacity = 0.5
layer.shadowColor = UIColor.red.cgColor
layer.shadowOffset = CGSize(width: 1, height: 4)
layer.shadowRadius = 5
// Add view in container.view
let viewRed = UIView(frame: CGRect(x: 50, y: 50, width: 50, height: 50))
viewRed.backgroundColor = .systemRed
container.view.addSubview(viewRed)
// Add view under scrollView container.view
let viewGreen = UIView(frame: CGRect(x: 25, y: 25, width: 50, height: 50))
viewGreen.backgroundColor = .systemGreen
container.view.insertSubview(viewGreen, at: 0)
Настройки ⚙️
Layout Макет
Настройте Layout с помощью создания подкласса ContainerLayout при инициализации
class NewContainerLayout: ContainerLayout {
override init() {
super.init()
// Initialization start position.
startPosition = .hide
// Disables any moving with gestures.
movingEnabled = true
// Sets the new value for positions of animated movement (top, middle, bottom).
positions = ContainerPosition(top: 70, middle: 250, bottom: 70)
// Sets insets container.view (left, right).
insets = ContainerInsets(right: 20, left: 20)
}
}
class ViewController: UIViewController {
var container: ContainerController!
override func viewDidLoad() {
super.viewDidLoad()
container = ContainerController(addTo: self, layout: NewContainerLayout())
container.move(type: .top)
}
}
Или создайте объект ContainerLayout
override func viewDidLoad() {
super.viewDidLoad()
// Create ContainerController Layout object
let layout = ContainerLayout()
layout.startPosition = .hide
layout.backgroundShadowShow = true
layout.positions = ContainerPosition(top: 70, middle: 250, bottom: 70)
container = ContainerController(addTo: self, layout: layout)
}
Измените настройки контейнера сразу - не обновляя Layout
// Properties
container.set(movingEnabled: true)
container.set(trackingPosition: false)
container.set(footerPadding: 100)
// Add ScrollInsets Top/Bottom
container.set(scrollIndicatorTop: 5) // ↓
container.set(scrollIndicatorBottom: 5) // ↑
// Positions
container.set(top: 70) // ↓
container.set(middle: 250) // ↑
container.set(bottom: 80) // ↑
// Middle Enable/Disable
container.set(middle: 250)
container.set(middle: nil)
// Background Shadow
container.set(backgroundShadowShow: true)
// Insets View
container.set(left: 5) // →
container.set(right: 5) // ←
// Landscape params
container.setLandscape(top: 30)
container.setLandscape(middle: 150)
container.setLandscape(bottom: 70)
container.setLandscape(middle: nil)
container.setLandscape(backgroundShadowShow: false)
container.setLandscape(left: 10)
container.setLandscape(right: 100)
ContainerController View
Используйте готовое решение
ContainerView
генерируется автоматически при создании ContainerController Используйте готовое решение для изменения радиуса, добавления тени и размытия.
Изменить окружность краев CornerRadius
// Change cornerRadius global for all subviews
container.view.cornerRadius = 15
Добавить слой Shadow
container.view.addShadow(opacity: 0.1)
Добавить фон Blur
// add blur UIVisualEffectView
container.view.addBlur(style: .dark)
Подробнее
Изменение положения на экране Верх / Середина / Низ ( .top / .middle / .bottom)
// These parameters set the new position value.
container.layout.positions = ContainerPosition(top: 70, middle: 250, bottom: 70)
// Change settings right away
container.set(top: 70) // ↓
container.set(middle: 250) // ↑
container.set(bottom: 80) // ↑
Настройте отступы
// Sets insets container.view (left, right).
container.layout.insets = ContainerInsets(right: 20, left: 20)
container.layout.landscapeInsets = ContainerInsets(right: 20, left: 100)
// Change settings right away
container.set(left: 5) // →
container.set(right: 5) // ←
container.setLandscape(left: 10)
container.setLandscape(right: 100)
Настроить для альбомной ориентации
// Sets the background shadow under container. (Default: backgroundShadowShow).
container.layout.landscapeBackgroundShadowShow = false
// Sets the new value for positions of animated movement (top, middle, bottom). (Default: positions).
container.layout.landscapePositions = ContainerPosition(top: 20, middle: 150, bottom: 70)
// Sets insets container.view (left, right). (Default: insets).
container.layout.landscapeInsets = ContainerInsets(right: 20, left: 100)
// Change settings right away
container.setLandscape(top: 30)
container.setLandscape(middle: 150)
container.setLandscape(bottom: 70)
container.setLandscape(middle: nil)
container.setLandscape(backgroundShadowShow: false)
container.setLandscape(left: 10)
container.setLandscape(right: 100)
Параметры для управления footerView
// Padding-top from container.view, if headerView is added, then its + height is summed.
container.layout.footerPadding = 100
// Tracking position container.view during animated movement.
container.layout.trackingPosition = false
// Change settings right away
container.set(footerPadding: 100)
container.set(trackingPosition: false)
ContainerController Delegate
class ViewController: UIViewController, ContainerControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let container = ContainerController(addTo: self, layout: layout)
container.delegate = self
}
}
/// Reports rotation and orientation changes
func containerControllerRotation(_ containerController: ContainerController) {
...
}
/// Reports a click on the background shadow
func containerControllerShadowClick(_ containerController: ContainerController) {
...
}
/// Reports the changes current position of the container, after its use
func containerControllerMove(_ containerController: ContainerController, position: CGFloat, type: ContainerMoveType, animation: Bool) {
...
}
Получение событий от делегата
func containerControllerRotation
Сообщает об изменениях поворота и ориентации
func containerControllerShadowClick
Сообщает о нажатии на фоновую тень
func containerControllerMove
Сообщает об изменениях текущего положения контейнера
Позиция значение — position: CGFloat
,
Тип позиции — type: ContainerMoveType
,
Анимированное перемещение — animation: Bool