Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f044cef62c | |||
| 15376fdf98 | |||
| 55f4bf8ae3 | |||
| 769058a952 | |||
| a5404f12a4 | |||
| cac1ea555f | |||
| f856082f63 | |||
| 409f526cf6 | |||
| b2b30b147f | |||
| a6b09007b2 | |||
| 7b001c292f | |||
| 5498067ffd | |||
| dce0be5a86 | |||
| 237bd57aca | |||
| bdf75322b8 | |||
| 0534cba5df | |||
| 831b2f144f |
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="cIu-62-xtU">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="cIu-62-xtU">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
@@ -62,7 +62,7 @@
|
||||
</scenes>
|
||||
<resources>
|
||||
<systemColor name="secondaryLabelColor">
|
||||
<color red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
|
||||
+29
-3
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
@@ -16,9 +16,32 @@
|
||||
<view key="view" contentMode="scaleToFill" id="jmi-Lo-St4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gqJ-oN-JCK">
|
||||
<rect key="frame" x="110.5" y="50" width="154" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="MXC-rS-qfY"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="18"/>
|
||||
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||
<state key="normal" title="isTranslucent true">
|
||||
<color key="titleColor" systemColor="systemBlueColor"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnChangeTranslucentAction:" destination="p3c-kf-PfN" eventType="touchUpInside" id="hjO-rR-Ij1"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="QCP-uk-H24"/>
|
||||
<color key="backgroundColor" systemColor="opaqueSeparatorColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="gqJ-oN-JCK" firstAttribute="top" secondItem="QCP-uk-H24" secondAttribute="top" constant="30" id="2Vg-iw-6Rl"/>
|
||||
<constraint firstItem="gqJ-oN-JCK" firstAttribute="centerX" secondItem="jmi-Lo-St4" secondAttribute="centerX" id="Crs-BD-puY"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="btnChangeTranslucent" destination="gqJ-oN-JCK" id="34t-Kh-blv"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Uzt-sR-4xA" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
@@ -27,7 +50,10 @@
|
||||
</scenes>
|
||||
<resources>
|
||||
<systemColor name="opaqueSeparatorColor">
|
||||
<color red="0.77647058820000003" green="0.77647058820000003" blue="0.7843137255" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.77647058823529413" green="0.77647058823529413" blue="0.78431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemBlueColor">
|
||||
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
+21
@@ -13,6 +13,7 @@ class ExampleAddCollectionViewController: StoryboardController {
|
||||
|
||||
var container: ContainerController!
|
||||
|
||||
@IBOutlet var btnChangeTranslucent: UIButton!
|
||||
// MARK: - Init
|
||||
|
||||
override func viewDidLoad() {
|
||||
@@ -20,6 +21,8 @@ class ExampleAddCollectionViewController: StoryboardController {
|
||||
|
||||
title = "Example Add CollectionView"
|
||||
|
||||
btnUpdateText()
|
||||
|
||||
let layoutC = ContainerLayout()
|
||||
layoutC.positions = ContainerPosition(top: 100, middle: 250, bottom: 70)
|
||||
container = ContainerController(addTo: self, layout: layoutC)
|
||||
@@ -34,6 +37,24 @@ class ExampleAddCollectionViewController: StoryboardController {
|
||||
container.move(type: .middle)
|
||||
}
|
||||
|
||||
@IBAction func btnChangeTranslucentAction(_ sender: UIButton) {
|
||||
|
||||
guard let translucent = navigationController?.navigationBar.isTranslucent else { return }
|
||||
|
||||
navigationController?.navigationBar.isTranslucent = !translucent
|
||||
|
||||
btnUpdateText()
|
||||
|
||||
container.move(type: container.moveType)
|
||||
}
|
||||
|
||||
func btnUpdateText() {
|
||||
|
||||
guard let translucent = navigationController?.navigationBar.isTranslucent else { return }
|
||||
|
||||
btnChangeTranslucent.setTitle("NavBar isTranslucent \(translucent)", for: .normal)
|
||||
}
|
||||
|
||||
func addCollectionView() -> UICollectionView {
|
||||
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
|
||||
+5
@@ -70,6 +70,9 @@ class ExamplesContainerController: ContainerController, ExampleCellDelegate {
|
||||
ExampleSwitchCellItem(height: h, delegate: self, type: .shadowBackground, value: false),
|
||||
ExampleSliderCellItem(height: h, delegate: self, type: .shadowContainer, value: 0.2, maximumValue: 1.0),
|
||||
ExampleSliderCellItem(height: h, delegate: self, type: .cornerRadius, value: 15, maximumValue: 140),
|
||||
|
||||
ExampleSwitchCellItem(height: h, delegate: self, type: .navbarTranslucent, value: false),
|
||||
|
||||
ExampleSwitchCellItem(height: h, delegate: self, type: .movingEnabled, value: true),
|
||||
ExampleSwitchCellItem(height: h, delegate: self, type: .trackingPosition, value: false),
|
||||
ExampleSliderCellItem(height: h, delegate: self, type: .footerPadding, value: 0, maximumValue: Float(ContainerDevice.screenMax)),
|
||||
@@ -122,6 +125,8 @@ class ExamplesContainerController: ContainerController, ExampleCellDelegate {
|
||||
|
||||
case .shadowContainer: self.view.addShadow(opacity: value)
|
||||
|
||||
case .navbarTranslucent: self.controller?.navigationController?.navigationBar.isTranslucent = boolValue; move(type: moveType)
|
||||
|
||||
case .movingEnabled: set(movingEnabled: boolValue)
|
||||
|
||||
case .trackingPosition: set(trackingPosition: boolValue)
|
||||
|
||||
@@ -20,6 +20,7 @@ extension ExampleCell {
|
||||
public enum Style: String {
|
||||
case `default` = ""
|
||||
case shadowContainer = "ShadowContainer"
|
||||
case navbarTranslucent = "NavbarTranslucent"
|
||||
case movingEnabled = "MovingEnabled"
|
||||
case cornerRadius = "CornerRadius"
|
||||
case footerPadding = "FooterView.Padding"
|
||||
|
||||
@@ -59,6 +59,8 @@ class MapsViewController: StoryboardController, MapsContainerControllerDelegate,
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
navigationController?.navigationBar.isTranslucent = false
|
||||
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
|
||||
navBar(hide: true)
|
||||
|
||||
@@ -17,13 +17,11 @@ class ViewController: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
configureNavigationBar(largeTitleColor: .label, backgoundColor: .systemGroupedBackground, tintColor: .systemBlue, title: "ContainerController", preferredLargeTitle: false)
|
||||
|
||||
title = "ContainerController"
|
||||
|
||||
navigationController?.interactivePopGestureRecognizer?.delegate = self
|
||||
navigationController?.interactivePopGestureRecognizer?.isEnabled = true
|
||||
|
||||
navigationController?.view.backgroundColor = .systemGroupedBackground
|
||||
items = [
|
||||
TitleTextItem(title: "Maps.app", clss: MapsViewController.self),
|
||||
TitleTextItem(title: "Example. Settings", clss: ExamplesSettingsViewController.self),
|
||||
@@ -48,34 +46,6 @@ class ViewController: UIViewController {
|
||||
|
||||
}
|
||||
|
||||
extension ViewController {
|
||||
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
|
||||
if #available(iOS 13.0, *) {
|
||||
let navBarAppearance = UINavigationBarAppearance()
|
||||
navBarAppearance.configureWithOpaqueBackground()
|
||||
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
|
||||
navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
|
||||
navBarAppearance.backgroundColor = backgoundColor
|
||||
|
||||
navigationController?.navigationBar.standardAppearance = navBarAppearance
|
||||
navigationController?.navigationBar.compactAppearance = navBarAppearance
|
||||
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
|
||||
|
||||
navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
|
||||
navigationController?.navigationBar.isTranslucent = false
|
||||
navigationController?.navigationBar.tintColor = tintColor
|
||||
navigationItem.title = title
|
||||
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
navigationController?.navigationBar.barTintColor = backgoundColor
|
||||
navigationController?.navigationBar.tintColor = tintColor
|
||||
navigationController?.navigationBar.isTranslucent = false
|
||||
navigationItem.title = title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ViewController: UIGestureRecognizerDelegate {
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
|
||||
@@ -11,17 +11,46 @@
|
||||
|
||||
UI Component. This is a copy swipe-panel from app: https://www.apple.com/ios/maps/
|
||||
|
||||
It can:
|
||||
- Animately move top / middle / bottom
|
||||
- Add multiple ContainerControlleron top of each other in self.view
|
||||
- Add any type of ScrollView: Table / Collection / Text
|
||||
- Control Gesture or Scroll
|
||||
- Pin HeaderView to top / pin FooterView to bottom,
|
||||
- Add Background Color / background blur transparency
|
||||
- Adjust cornerRadius edges
|
||||
- Adjust container shadow
|
||||
- When raised to top = Add background shadow -
|
||||
- Has the ability to adjust Left / Right margins
|
||||
- And adjust Left / Right margins for landscape state.
|
||||
|
||||
|
||||
## Preview
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
## About the project
|
||||
|
||||
Examples of use (ui swipe component ContainerController) in popular design applications.
|
||||
|
||||
It is used in different categories apps:
|
||||
- Maps / Menu / Player Music / Market / Sports News / Taxi / Finance Banks Stock / Wallets / Analytics / Notes
|
||||
- Alerts / Popups / Notifications
|
||||
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Installation](#installation)
|
||||
- [CocoaPods](#cocoapods)
|
||||
- [Swift Package Manager with Xcode 11](#swift-package-manager-with-xcode-11)
|
||||
- [Design examples](#design-examples)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Action](#action)
|
||||
- [Move position with an animation](#move-position-with-an-animation)
|
||||
@@ -58,7 +87,7 @@ UI Component. This is a copy swipe-panel from app: https://www.apple.com/ios/map
|
||||
|
||||
## Installation
|
||||
|
||||
### CocoaPods
|
||||
### [CocoaPods](https://cocoapods.org)
|
||||
|
||||
ContainerControllerSwift is available through [CocoaPods](https://cocoapods.org). To install
|
||||
it, simply add the following line to your Podfile:
|
||||
@@ -66,10 +95,50 @@ it, simply add the following line to your Podfile:
|
||||
```ruby
|
||||
pod 'ContainerControllerSwift'
|
||||
```
|
||||
### Swift Package Manager with Xcode 11
|
||||
|
||||
### [Swift Package Manager with Xcode 11](https://swift.org/package-manager/)
|
||||
|
||||
```ruby
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/mrustaa/ContainerController.git")
|
||||
]
|
||||
```
|
||||
|
||||
Follow [this doc](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app).
|
||||
|
||||
|
||||
## Design examples
|
||||
### Designs are borrowed from [Dribbble](https://dribbble.com)
|
||||
|
||||
To get the design, you need to add a branch
|
||||
[ui_examples](https://github.com/mrustaa/ContainerController/tree/ui_examples)
|
||||
|
||||
```swift
|
||||
git clone https://github.com/mrustaa/ContainerController.git
|
||||
cd ContainerController/
|
||||
git checkout ui_examples
|
||||
```
|
||||
|
||||
URLs Author:
|
||||
|
||||
- [Play Music](https://dribbble.com/shots/15381326-Move-Multipurpose-HTML-Template-I), [Sallets](https://dribbble.com/shots/18054638-Sowallet-Mobile-Appp), [Crypto](https://dribbble.com/shots/24353177-Crypto-Loan-Mobile-App), [Buy Stock](https://dribbble.com/shots/14364583-Online-Banking-Mobile-App), [Sport](https://dribbble.com/shots/15544535-Sneakers-Shopping-App), [Taxi](https://dribbble.com/shots/23691282-Taxi-Booking-App-Design), [Map Parking](https://dribbble.com/shots/15034854-AirGarage-Mobile-App-Redesign), [Custom Card](https://dribbble.com/shots/20629590-Business-Card-Mobile-IOS-App), [Apple.Maps App](https://apps.apple.com/us/app/apple-maps/id915056765)
|
||||
|
||||
GIF Previews:
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
```swift
|
||||
|
||||
@@ -218,7 +218,7 @@ open class ContainerController: NSObject {
|
||||
|
||||
shadowHiddenCheck()
|
||||
|
||||
delegate?.containerControllerRotation(self)
|
||||
delegate?.containerControllerRotation?(self)
|
||||
|
||||
calculationView()
|
||||
calculationScrollViewHeight(from: .rotation)
|
||||
@@ -357,7 +357,7 @@ open class ContainerController: NSObject {
|
||||
}
|
||||
|
||||
@objc private func shadowButtonAction() {
|
||||
delegate?.containerControllerShadowClick(self)
|
||||
delegate?.containerControllerShadowClick?(self)
|
||||
}
|
||||
|
||||
// MARK: - Create Container-View
|
||||
@@ -477,7 +477,11 @@ open class ContainerController: NSObject {
|
||||
transform.ty = ((positionTop / 2) + (transform.ty / 2))
|
||||
}
|
||||
|
||||
let position = transform.ty
|
||||
var position = transform.ty
|
||||
if topTranslucent {
|
||||
position = position + topBarHeight
|
||||
}
|
||||
|
||||
let type: ContainerMoveType = moveType
|
||||
let from: ContainerFromType = .pan
|
||||
let animation = false
|
||||
@@ -555,7 +559,7 @@ open class ContainerController: NSObject {
|
||||
scrollInsetsBottom = 0.0
|
||||
}
|
||||
|
||||
let top: CGFloat = layout.scrollInsets.top
|
||||
var top: CGFloat = layout.scrollInsets.top
|
||||
let bottom: CGFloat = layout.scrollInsets.bottom + scrollInsetsBottom
|
||||
|
||||
let indicatorTop: CGFloat = layout.scrollIndicatorInsets.top
|
||||
@@ -575,6 +579,10 @@ open class ContainerController: NSObject {
|
||||
height = 0
|
||||
}
|
||||
|
||||
if topTranslucent {
|
||||
height = height + topBarHeight
|
||||
}
|
||||
|
||||
if animation ,
|
||||
!isScrolling,
|
||||
footerView == nil,
|
||||
@@ -735,7 +743,10 @@ open class ContainerController: NSObject {
|
||||
from: ContainerFromType = .custom,
|
||||
completion: (() -> Void)? = nil) {
|
||||
|
||||
let position = positionMoveFrom(type: type)
|
||||
var position = positionMoveFrom(type: type)
|
||||
if topTranslucent {
|
||||
position = position + topBarHeight
|
||||
}
|
||||
|
||||
move(position: position,
|
||||
animation: animation,
|
||||
@@ -834,7 +845,7 @@ open class ContainerController: NSObject {
|
||||
type: ContainerMoveType,
|
||||
animation: Bool) {
|
||||
|
||||
delegate?.containerControllerMove(self, position: position, type: type, animation: animation)
|
||||
delegate?.containerControllerMove?(self, position: position, type: type, animation: animation)
|
||||
}
|
||||
|
||||
//MARK: - Shadow Alpha Level
|
||||
@@ -1229,7 +1240,10 @@ extension ContainerController: UIScrollViewDelegate {
|
||||
|
||||
scrollTransform = view.transform
|
||||
|
||||
let top: CGFloat = positionTop
|
||||
var top: CGFloat = positionTop
|
||||
if topTranslucent {
|
||||
top = top + topBarHeight
|
||||
}
|
||||
|
||||
if gesture.state == .ended {
|
||||
scrollOnceBeginDragging = false
|
||||
|
||||
@@ -9,30 +9,16 @@
|
||||
import UIKit
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
public protocol ContainerControllerDelegate {
|
||||
@objc public protocol ContainerControllerDelegate {
|
||||
|
||||
/// Reports rotation and orientation changes
|
||||
func containerControllerRotation(_ containerController: ContainerController)
|
||||
@objc optional func containerControllerRotation(_ containerController: ContainerController)
|
||||
|
||||
/// Reports a click on the background shadow
|
||||
func containerControllerShadowClick(_ containerController: ContainerController)
|
||||
@objc optional 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)
|
||||
@objc optional func containerControllerMove(_ containerController: ContainerController, position: CGFloat, type: ContainerMoveType, animation: Bool)
|
||||
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
public extension ContainerControllerDelegate {
|
||||
|
||||
func containerControllerRotation(_ containerController: ContainerController) {
|
||||
}
|
||||
|
||||
|
||||
func containerControllerShadowClick(_ containerController: ContainerController) {
|
||||
}
|
||||
|
||||
func containerControllerMove(_ containerController: ContainerController, position: CGFloat, type: ContainerMoveType, animation: Bool) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import UIKit
|
||||
|
||||
typealias ContainerCompletion = () -> Void
|
||||
|
||||
public enum ContainerMoveType {
|
||||
@objc public enum ContainerMoveType: Int {
|
||||
case top
|
||||
case middle
|
||||
case bottom
|
||||
|
||||
Reference in New Issue
Block a user