Commit c894e882 by Michael Gaylord

Merge branch 'development' of https://github.com/CosmicMind/Material into development

# Conflicts:
#	Sources/iOS/TextField.swift
parents 055a151b 7307c49e
Pod::Spec.new do |s|
s.name = 'Material'
s.version = '2.6.1'
s.version = '2.6.3'
s.license = 'BSD-3-Clause'
s.summary = 'An animation and graphics framework for Material Design in Swift.'
s.homepage = 'http://materialswift.com'
......
......@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
9606CFAC1E957AC3006B4E74 /* TabMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9606CFAB1E957AC3006B4E74 /* TabMenuController.swift */; };
961409B01E43D15C00E7BA99 /* CollectionViewCard.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961730591E145DE900A9A297 /* CollectionViewCard.swift */; settings = {ATTRIBUTES = (Public, ); }; };
961409B11E43D15C00E7BA99 /* FABMenu.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96A183621E0C6CE200083C30 /* FABMenu.swift */; settings = {ATTRIBUTES = (Public, ); }; };
961409B21E43D15C00E7BA99 /* FABMenuController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96A183641E0C6DD400083C30 /* FABMenuController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -189,6 +190,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
9606CFAB1E957AC3006B4E74 /* TabMenuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabMenuController.swift; sourceTree = "<group>"; };
961276621DCD8B1800A7D920 /* CharacterAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CharacterAttribute.swift; sourceTree = "<group>"; };
961730591E145DE900A9A297 /* CollectionViewCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCard.swift; sourceTree = "<group>"; };
961E6BDE1DDA2A95004E6C93 /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
......@@ -362,12 +364,13 @@
name = Height;
sourceTree = "<group>";
};
962DDD071D6FBBB7001C307C /* Page */ = {
962DDD071D6FBBB7001C307C /* TabMenu */ = {
isa = PBXGroup;
children = (
963FBF071D669D14008F8512 /* PageTabBarController.swift */,
9606CFAB1E957AC3006B4E74 /* TabMenuController.swift */,
);
name = Page;
name = TabMenu;
sourceTree = "<group>";
};
962DDD081D6FBBD0001C307C /* BottomTabBar */ = {
......@@ -527,7 +530,7 @@
96BCB8091CB4107700C806FE /* Motion */,
96BCB8011CB40F1700C806FE /* Navigation */,
961E6BEF1DDA4B04004E6C93 /* NavigationDrawer */,
962DDD071D6FBBB7001C307C /* Page */,
962DDD071D6FBBB7001C307C /* TabMenu */,
96717B151DBE6B1800DA84DB /* Photos */,
96328B8F1E05B69A009A4C90 /* Reminders */,
9626CA951DAB5370003E2611 /* Root */,
......@@ -992,6 +995,7 @@
965E80D81DD4C50600D61E4B /* Layer.swift in Sources */,
965E80D91DD4C50600D61E4B /* Layout.swift in Sources */,
965E80DA1DD4C50600D61E4B /* Border.swift in Sources */,
9606CFAC1E957AC3006B4E74 /* TabMenuController.swift in Sources */,
965E80DB1DD4C50600D61E4B /* InterimSpace.swift in Sources */,
965E80DC1DD4C50600D61E4B /* Depth.swift in Sources */,
965E80DD1DD4C50600D61E4B /* EdgeInsets.swift in Sources */,
......
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.6.1</string>
<string>2.6.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
......@@ -33,6 +33,8 @@ import UIKit
public enum MotionAnimationKeyPath: String {
case backgroundColor
case barTintColor
case borderColor
case borderWidth
case cornerRadius
case transform
case rotation = "transform.rotation"
......@@ -66,6 +68,8 @@ public enum MotionAnimation {
case custom(CABasicAnimation)
case backgroundColor(UIColor)
case barTintColor(UIColor)
case borderColor(UIColor)
case borderWidth(CGFloat)
case cornerRadius(CGFloat)
case transform(CATransform3D)
case rotationAngle(CGFloat)
......@@ -264,6 +268,10 @@ extension CALayer {
a.append(Motion.background(color: color))
case let .barTintColor(color):
a.append(Motion.barTint(color: color))
case let .borderColor(color):
a.append(Motion.border(color: color))
case let .borderWidth(width):
a.append(Motion.border(width: width))
case let .cornerRadius(radius):
a.append(Motion.corner(radius: radius))
case let .transform(transform):
......@@ -478,6 +486,28 @@ extension Motion {
}
/**
Creates a CABasicAnimation for the borderColor key path.
- Parameter color: A UIColor.
- Returns: A CABasicAnimation.
*/
public static func border(color: UIColor) -> CABasicAnimation {
let animation = CABasicAnimation(keyPath: .borderColor)
animation.toValue = color.cgColor
return animation
}
/**
Creates a CABasicAnimation for the borderWidth key path.
- Parameter width: A CGFloat.
- Returns: A CABasicAnimation.
*/
public static func border(width: CGFloat) -> CABasicAnimation {
let animation = CABasicAnimation(keyPath: .borderWidth)
animation.toValue = width
return animation
}
/**
Creates a CABasicAnimation for the cornerRadius key path.
- Parameter radius: A CGFloat.
- Returns: A CABasicAnimation.
......
......@@ -30,7 +30,7 @@
import UIKit
extension UINavigationController {
extension NavigationController {
/// Device status bar style.
open var statusBarStyle: UIStatusBarStyle {
get {
......
......@@ -55,7 +55,7 @@ public enum PageTabBarAlignment: Int {
}
extension UIViewController {
/// Grid reference.
/// PageTabBarItem reference.
public private(set) var pageTabBarItem: PageTabBarItem {
get {
return AssociatedObject(base: self, key: &PageTabBarItemKey) {
......@@ -113,8 +113,18 @@ open class PageTabBarController: RootController {
/// Indicates that the tab has been pressed and animating.
open internal(set) var isTabSelectedAnimation = false
/// An internal reference to the selectedIndex.
fileprivate var internalSelectedIndex = 0
/// The currently selected UIViewController.
open internal(set) var selectedIndex = 0
open var selectedIndex: Int {
get {
return internalSelectedIndex
}
set(value) {
setInternalSelectedIndex(index: value, animated: true)
}
}
/// PageTabBar alignment setting.
open var pageTabBarAlignment = PageTabBarAlignment.bottom
......@@ -148,23 +158,24 @@ open class PageTabBarController: RootController {
public required init?(coder aDecoder: NSCoder) {
isBounceEnabled = true
super.init(coder: aDecoder)
prepare()
}
public override init(rootViewController: UIViewController) {
isBounceEnabled = true
super.init(rootViewController: UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil))
viewControllers.append(rootViewController)
setViewControllers(viewControllers, direction: .forward, animated: true)
prepare()
setInternalSelectedIndex(index: 0, animated: true)
}
public init(viewControllers: [UIViewController], selectedIndex: Int = 0) {
public init(viewControllers: [UIViewController], selectedIndex index: Int = 0) {
isBounceEnabled = true
super.init(rootViewController: UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil))
self.selectedIndex = selectedIndex
self.viewControllers.append(contentsOf: viewControllers)
setViewControllers([self.viewControllers[selectedIndex]], direction: .forward, animated: true)
setInternalSelectedIndex(index: index, animated: true)
}
open override func viewDidLoad() {
super.viewDidLoad()
prepare()
}
......@@ -198,7 +209,6 @@ open class PageTabBarController: RootController {
*/
open func setViewControllers(_ viewControllers: [UIViewController], direction: UIPageViewControllerNavigationDirection, animated: Bool, completion: ((Bool) -> Void)? = nil) {
pageViewController?.setViewControllers(viewControllers, direction: direction, animated: animated, completion: completion)
prepare()
}
/**
......@@ -240,43 +250,64 @@ open class PageTabBarController: RootController {
button.addTarget(self, action: #selector(handlePageTabBarButton(button:)), for: .touchUpInside)
}
}
}
extension PageTabBarController {
/// Prepares the pageTabBar.
fileprivate func preparePageTabBar() {
pageTabBar.zPosition = 1000
pageTabBar.dividerColor = Color.grey.lighten3
view.addSubview(pageTabBar)
pageTabBar.select(at: internalSelectedIndex)
}
}
extension PageTabBarController {
/**
Handles the pageTabBarButton.
- Parameter button: A UIButton.
*/
@objc
internal func handlePageTabBarButton(button: UIButton) {
fileprivate func handlePageTabBarButton(button: UIButton) {
guard let index = pageTabBar.buttons.index(of: button) else {
return
}
guard index != selectedIndex else {
guard index != internalSelectedIndex else {
return
}
setInternalSelectedIndex(index: index, animated: true)
}
}
extension PageTabBarController {
/**
Internally sets the internalSelectedIndex value.
- Parameter index: Int.
- Parameter animated: Bool.
*/
fileprivate func setInternalSelectedIndex(index: Int, animated: Bool = false) {
guard animated else {
internalSelectedIndex = index
return
}
let direction: UIPageViewControllerNavigationDirection = index < selectedIndex ? .reverse : .forward
let direction: UIPageViewControllerNavigationDirection = index < internalSelectedIndex ? .reverse : .forward
isTabSelectedAnimation = true
selectedIndex = index
pageTabBar.select(at: selectedIndex)
internalSelectedIndex = index
setViewControllers([viewControllers[index]], direction: direction, animated: true) { [weak self] _ in
pageTabBar.select(at: internalSelectedIndex)
setViewControllers([viewControllers[internalSelectedIndex]], direction: direction, animated: true) { [weak self] _ in
guard let s = self else {
return
}
s.isTabSelectedAnimation = false
s.delegate?.pageTabBarController?(pageTabBarController: s, didTransitionTo: s.viewControllers[s.selectedIndex])
}
s.delegate?.pageTabBarController?(pageTabBarController: s, didTransitionTo: s.viewControllers[s.internalSelectedIndex])
}
/// Prepares the pageTabBar.
private func preparePageTabBar() {
pageTabBar.zPosition = 1000
pageTabBar.dividerColor = Color.grey.lighten3
view.addSubview(pageTabBar)
pageTabBar.select(at: selectedIndex)
}
}
......@@ -290,8 +321,9 @@ extension PageTabBarController: UIPageViewControllerDelegate {
return
}
selectedIndex = index
pageTabBar.select(at: selectedIndex)
setInternalSelectedIndex(index: index)
pageTabBar.select(at: index)
if finished && completed {
delegate?.pageTabBarController?(pageTabBarController: self, didTransitionTo: v)
......
......@@ -195,7 +195,7 @@ public class PhotoLibrary: NSObject {
}
/// Prepare the instance object.
private func prepare() {
open func prepare() {
prepareChangeObservers()
}
......
......@@ -59,7 +59,6 @@ open class RootController: UIViewController {
*/
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
prepare()
}
/**
......@@ -69,7 +68,6 @@ open class RootController: UIViewController {
*/
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
prepare()
}
/**
......@@ -79,6 +77,10 @@ open class RootController: UIViewController {
public init(rootViewController: UIViewController) {
super.init(nibName: nil, bundle: nil)
self.rootViewController = rootViewController
}
open override func viewDidLoad() {
super.viewDidLoad()
prepare()
}
......
/*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
/// A memory reference to the TabMenuBarItem instance for UIViewController extensions.
fileprivate var TabMenuBarItemKey: UInt8 = 0
open class TabMenuBarItem: FlatButton {
open override func prepare() {
super.prepare()
pulseAnimation = .none
}
}
@objc(TabMenuAlignment)
public enum TabMenuAlignment: Int {
case top
case bottom
}
open class TabMenu: UIView {
@IBInspectable
open var tabBar = TabBar() {
didSet {
layoutSubviews()
}
}
open var viewControllers: [UIViewController]
open var selectedIndex: Int
public required init?(coder aDecoder: NSCoder) {
viewControllers = []
selectedIndex = 0
fatalError("init(coder:) has not been implemented")
}
public init(viewControllers: [UIViewController], selectedIndex: Int = 0) {
self.viewControllers = viewControllers
self.selectedIndex = selectedIndex
super.init(frame: .zero)
}
open override func layoutSubviews() {
super.layoutSubviews()
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
to initialize property values and other setup operations.
The super.prepare method should always be called immediately
when subclassing.
*/
open func prepare() {
prepareTabBar()
}
}
extension TabMenu {
fileprivate func prepareTabBar() {
tabBar.isLineAnimated = false
tabBar.lineAlignment = .top
}
}
extension UIViewController {
/// tabMenuBarItem reference.
public private(set) var tabMenuBarItem: TabMenuBarItem {
get {
return AssociatedObject(base: self, key: &TabMenuBarItemKey) {
return TabMenuBarItem()
}
}
set(value) {
AssociateObject(base: self, key: &TabMenuBarItemKey, value: value)
}
}
}
extension UIViewController {
/**
A convenience property that provides access to the TabMenuController.
This is the recommended method of accessing the TabMenuController
through child UIViewControllers.
*/
public var tabMenuBarController: TabMenuController? {
var viewController: UIViewController? = self
while nil != viewController {
if viewController is TabMenuController {
return viewController as? TabMenuController
}
viewController = viewController?.parent
}
return nil
}
}
open class TabMenuController: UIViewController {
/// A reference to the TabMenu instance.
@IBInspectable
open let tabMenu: TabMenu
/**
An initializer that initializes the object with a NSCoder object.
- Parameter aDecoder: A NSCoder instance.
*/
public required init?(coder aDecoder: NSCoder) {
tabMenu = TabMenu(viewControllers: [])
super.init(coder: aDecoder)
}
/**
An initializer that accepts an Array of UIViewControllers.
- Parameter viewControllers: An Array of UIViewControllers.
*/
public init(viewControllers: [UIViewController], selectedIndex: Int = 0) {
tabMenu = TabMenu(viewControllers: viewControllers, selectedIndex: selectedIndex)
super.init(nibName: nil, bundle: nil)
}
open override func viewDidLoad() {
super.viewDidLoad()
prepare()
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
to initialize property values and other setup operations.
The super.prepare method should always be called immediately
when subclassing.
*/
open func prepare() {
}
}
......@@ -350,9 +350,6 @@ open class TextField: UITextField {
}
}
@IBInspectable
open var isPlaceholderUppercasedWhenEditing: Bool = false
/**
An initializer that initializes the object with a NSCoder object.
- Parameter aDecoder: A NSCoder instance.
......@@ -390,6 +387,17 @@ open class TextField: UITextField {
return super.becomeFirstResponder()
}
/// EdgeInsets for text.
open var textInset: CGFloat = 0
open override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: textInset, dy: 0)
}
open override func editingRect(forBounds bounds: CGRect) -> CGRect {
return textRect(forBounds: bounds)
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
......@@ -485,24 +493,24 @@ extension TextField {
extension TextField {
/// Layout the placeholderLabel.
fileprivate func layoutPlaceholderLabel() {
let w = leftViewWidth
let w = leftViewWidth + textInset
let h = 0 == height ? intrinsicContentSize.height : height
placeholderLabel.transform = CGAffineTransform.identity
guard isEditing || !isEmpty || !isPlaceholderAnimated else {
placeholderLabel.frame = CGRect(x: w, y: 0, width: width - w, height: h)
placeholderLabel.frame = CGRect(x: w, y: 0, width: width - leftViewWidth - 2 * textInset, height: h)
return
}
placeholderLabel.frame = CGRect(x: w, y: 0, width: width - w, height: h)
placeholderLabel.frame = CGRect(x: w, y: 0, width: width - leftViewWidth - 2 * textInset, height: h)
placeholderLabel.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
switch textAlignment {
case .left, .natural:
placeholderLabel.x = w
case .right:
placeholderLabel.x = width - placeholderLabel.width
placeholderLabel.x = width - placeholderLabel.width - textInset
default:break
}
......@@ -640,14 +648,12 @@ extension TextField {
}
s.placeholderLabel.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
if self?.isPlaceholderUppercasedWhenEditing ?? false {
s.placeholderLabel.text = s.placeholderLabel.text?.uppercased()
}
switch s.textAlignment {
case .left, .natural:
s.placeholderLabel.x = s.leftViewWidth
s.placeholderLabel.x = s.leftViewWidth + s.textInset
case .right:
s.placeholderLabel.x = s.width - s.placeholderLabel.width
s.placeholderLabel.x = s.width - s.placeholderLabel.width - s.textInset
default:break
}
......@@ -676,11 +682,9 @@ extension TextField {
guard let s = self else {
return
}
if self?.isPlaceholderUppercasedWhenEditing ?? false{
s.placeholderLabel.text = s.placeholderLabel.text?.capitalized
}
s.placeholderLabel.transform = CGAffineTransform.identity
s.placeholderLabel.x = s.leftViewWidth
s.placeholderLabel.x = s.leftViewWidth + s.textInset
s.placeholderLabel.y = 0
})
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment