Commit f83591e9 by Daniel Dahan

added SearchBarViewController example

parent 531f2711
...@@ -96,6 +96,13 @@ ...@@ -96,6 +96,13 @@
</Group> </Group>
<Group <Group
location = "container:" location = "container:"
name = "SearchBarViewController">
<FileRef
location = "group:Programmatic/SearchBarViewController/SearchBarViewController.xcodeproj">
</FileRef>
</Group>
<Group
location = "container:"
name = "NavigationBarViewController"> name = "NavigationBarViewController">
<FileRef <FileRef
location = "group:Programmatic/NavigationBarViewController/NavigationBarViewController.xcodeproj"> location = "group:Programmatic/NavigationBarViewController/NavigationBarViewController.xcodeproj">
......
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
96A71ED71C6FFF7300C0C4AE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A71ED61C6FFF7300C0C4AE /* ViewController.swift */; }; 96A71ED71C6FFF7300C0C4AE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A71ED61C6FFF7300C0C4AE /* ViewController.swift */; };
96A71EDC1C6FFF7300C0C4AE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96A71EDB1C6FFF7300C0C4AE /* Assets.xcassets */; }; 96A71EDC1C6FFF7300C0C4AE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96A71EDB1C6FFF7300C0C4AE /* Assets.xcassets */; };
96A71EDF1C6FFF7300C0C4AE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96A71EDD1C6FFF7300C0C4AE /* LaunchScreen.storyboard */; }; 96A71EDF1C6FFF7300C0C4AE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96A71EDD1C6FFF7300C0C4AE /* LaunchScreen.storyboard */; };
96A7200F1C777D0F00C0C4AE /* Material.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96A7200E1C777D0F00C0C4AE /* Material.framework */; };
96A720101C777D0F00C0C4AE /* Material.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 96A7200E1C777D0F00C0C4AE /* Material.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
...@@ -22,7 +20,6 @@ ...@@ -22,7 +20,6 @@
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
96A720101C777D0F00C0C4AE /* Material.framework in Embed Frameworks */,
); );
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
...@@ -36,7 +33,6 @@ ...@@ -36,7 +33,6 @@
96A71EDB1C6FFF7300C0C4AE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 96A71EDB1C6FFF7300C0C4AE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
96A71EDE1C6FFF7300C0C4AE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 96A71EDE1C6FFF7300C0C4AE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
96A71EE01C6FFF7300C0C4AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 96A71EE01C6FFF7300C0C4AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
96A7200E1C777D0F00C0C4AE /* Material.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = Material.framework; path = "/Users/danieldahan/Library/Developer/Xcode/DerivedData/Material-hbpnflxhoouqxebjcyhbbhqyesjd/Build/Products/Debug-iphoneos/Material.framework"; sourceTree = "<absolute>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
...@@ -44,7 +40,6 @@ ...@@ -44,7 +40,6 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
96A7200F1C777D0F00C0C4AE /* Material.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -54,7 +49,6 @@ ...@@ -54,7 +49,6 @@
96A71EC81C6FFF7300C0C4AE = { 96A71EC81C6FFF7300C0C4AE = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
96A7200E1C777D0F00C0C4AE /* Material.framework */,
96A71ED31C6FFF7300C0C4AE /* MaterialSwitch */, 96A71ED31C6FFF7300C0C4AE /* MaterialSwitch */,
96A71ED21C6FFF7300C0C4AE /* Products */, 96A71ED21C6FFF7300C0C4AE /* Products */,
); );
......
...@@ -38,7 +38,6 @@ import Material ...@@ -38,7 +38,6 @@ import Material
class ViewController: UIViewController, MaterialSwitchDelegate { class ViewController: UIViewController, MaterialSwitchDelegate {
private var topView: MaterialView = MaterialView() private var topView: MaterialView = MaterialView()
private var bottomView: MaterialView = MaterialView() private var bottomView: MaterialView = MaterialView()
var c2: MaterialSwitch!
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
...@@ -70,7 +69,7 @@ class ViewController: UIViewController, MaterialSwitchDelegate { ...@@ -70,7 +69,7 @@ class ViewController: UIViewController, MaterialSwitchDelegate {
c1.translatesAutoresizingMaskIntoConstraints = false c1.translatesAutoresizingMaskIntoConstraints = false
topView.addSubview(c1) topView.addSubview(c1)
c2 = MaterialSwitch(state: .Off, style: .LightContent) let c2: MaterialSwitch = MaterialSwitch(state: .On, style: .LightContent)
c2.delegate = self c2.delegate = self
c2.translatesAutoresizingMaskIntoConstraints = false c2.translatesAutoresizingMaskIntoConstraints = false
topView.addSubview(c2) topView.addSubview(c2)
......
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:SearchBarViewController.xcodeproj">
</FileRef>
</Workspace>
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* 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 Material 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
import Material
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window!.rootViewController = AppSearchBarViewController(mainViewController: MainViewController())
window!.makeKeyAndVisible()
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* 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 GraphKit 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.
*/
/*
The following is an example of using a SearchBarViewController to control the
flow of your application.
*/
import UIKit
import Material
class AppSearchBarViewController: SearchBarViewController {
/// Menu backdrop layer.
private lazy var menuBackdropLayer: MaterialLayer = MaterialLayer()
/// MenuView diameter.
private let menuViewDiameter: CGFloat = 56
/// MenuView inset.
private let menuViewInset: CGFloat = 16
/// MenuView.
private let menuView: MenuView = MenuView()
override func viewDidLoad() {
super.viewDidLoad()
prepareView()
prepareSearchBarView()
prepareMenuBackdropLayer()
prepareMenuView()
}
/**
Handles the menu button click, which opens the
SideNavigationBarViewController.
*/
func handleMenuButton() {
sideNavigationBarViewController?.openLeftView()
}
/**
Handles the more button click, which opens the
SideNavigationBarViewController.
*/
func handleMoreButton() {
sideNavigationBarViewController?.openRightView()
}
/// Handle the menuView touch event.
func handleMenu() {
let image: UIImage?
if menuView.menu.opened {
hideMenuBackdropLayer()
menuView.menu.close()
image = UIImage(named: "ic_add_white")
} else {
showMenuBackdropLayer()
menuView.menu.open() { (v: UIView) in
(v as? MaterialButton)?.pulse()
}
image = UIImage(named: "ic_close_white")
}
// Add a nice rotation animation to the base button.
let first: MaterialButton? = menuView.menu.views?.first as? MaterialButton
first?.animate(MaterialAnimation.rotate(1))
first?.setImage(image, forState: .Normal)
first?.setImage(image, forState: .Highlighted)
}
/// Prepares view.
private func prepareView() {
view.backgroundColor = MaterialColor.white
}
/// Prepares the searchBarView.
private func prepareSearchBarView() {
var image = UIImage(named: "ic_close_white")
let clearButton: FlatButton = FlatButton()
clearButton.pulseColor = MaterialColor.white
clearButton.pulseScale = false
clearButton.setImage(image, forState: .Normal)
clearButton.setImage(image, forState: .Highlighted)
image = UIImage(named: "ic_menu_white")
let menuButton: FlatButton = FlatButton()
menuButton.pulseColor = MaterialColor.white
menuButton.pulseScale = false
menuButton.setImage(image, forState: .Normal)
menuButton.setImage(image, forState: .Highlighted)
// Switch control.
let switchControl: MaterialSwitch = MaterialSwitch(state: .Off, style: .LightContent, size: .Small)
switchControl.buttonOnColor = MaterialColor.lightBlue.base
/*
To lighten the status bar - add the
"View controller-based status bar appearance = NO"
to your info.plist file and set the following property.
*/
searchBarView.statusBarStyle = .LightContent
searchBarView.delegate = self
searchBarView.backgroundColor = MaterialColor.indigo.base
searchBarView.placeholder = "Search"
searchBarView.tintColor = MaterialColor.white
searchBarView.textColor = MaterialColor.white
searchBarView.placeholderTextColor = MaterialColor.white
searchBarView.textField.font = RobotoFont.regularWithSize(17)
searchBarView.clearButton = clearButton
searchBarView.leftControls = [menuButton]
searchBarView.rightControls = [switchControl]
view.addSubview(searchBarView)
}
/// Prepares the menuBackdropLayer.
private func prepareMenuBackdropLayer() {
menuBackdropLayer.backgroundColor = MaterialColor.white.colorWithAlphaComponent(0.75).CGColor
menuBackdropLayer.hidden = true
menuBackdropLayer.zPosition = 2000
view.layer.addSublayer(menuBackdropLayer)
}
/// Prepares the add button.
private func prepareMenuView() {
var image: UIImage? = UIImage(named: "ic_add_white")
let btn1: FabButton = FabButton()
btn1.pulseColor = nil
btn1.setImage(image, forState: .Normal)
btn1.setImage(image, forState: .Highlighted)
btn1.addTarget(self, action: "handleMenu", forControlEvents: .TouchUpInside)
menuView.addSubview(btn1)
image = UIImage(named: "ic_create_white")
let btn2: FabButton = FabButton()
btn2.backgroundColor = MaterialColor.blue.base
btn2.setImage(image, forState: .Normal)
btn2.setImage(image, forState: .Highlighted)
menuView.addSubview(btn2)
image = UIImage(named: "ic_photo_camera_white")
let btn3: FabButton = FabButton()
btn3.backgroundColor = MaterialColor.green.base
btn3.setImage(image, forState: .Normal)
btn3.setImage(image, forState: .Highlighted)
menuView.addSubview(btn3)
image = UIImage(named: "ic_note_add_white")
let btn4: FabButton = FabButton()
btn4.backgroundColor = MaterialColor.amber.base
btn4.setImage(image, forState: .Normal)
btn4.setImage(image, forState: .Highlighted)
menuView.addSubview(btn4)
// Initialize the menu and setup the configuration options.
menuView.menu.direction = .Up
menuView.menu.baseViewSize = CGSizeMake(menuViewDiameter, menuViewDiameter)
menuView.menu.views = [btn1, btn2, btn3, btn4]
menuView.zPosition = 3000
view.insertSubview(menuView, aboveSubview: searchBarView)
menuView.translatesAutoresizingMaskIntoConstraints = false
MaterialLayout.size(view, child: menuView, width: menuViewDiameter, height: menuViewDiameter)
MaterialLayout.alignFromBottomRight(view, child: menuView, bottom: menuViewInset, right: menuViewInset)
}
/// Displays the menuBackdropLayer.
private func showMenuBackdropLayer() {
// Disable the side nav, so users can't swipe while viewing the menu.
sideNavigationBarViewController?.enabled = false
// Position the menuBackdropLayer for the animation when opening.
MaterialAnimation.animationDisabled { [unowned self] in
self.menuBackdropLayer.frame = self.menuView.frame
self.menuBackdropLayer.shape = .Circle
self.menuBackdropLayer.hidden = false
}
menuBackdropLayer.animate(MaterialAnimation.scale(30, duration: 0.25))
}
/// Hides the menuBackdropLayer.
private func hideMenuBackdropLayer() {
// Enable the side nav.
sideNavigationBarViewController?.enabled = true
// Position the menuBackdropLayer for the animation when closing.
menuBackdropLayer.animate(MaterialAnimation.animationGroup([
MaterialAnimation.scale(1),
MaterialAnimation.position(menuView.center)
], duration: 0.25))
MaterialAnimation.delay(0.25) { [weak self] in
self?.menuBackdropLayer.hidden = true
}
}
}
{
"images" : [
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Material-Icon-29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Material-Icon-29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Material-Icon-40@2x-1.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Material-Icon-40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Material-Icon-60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Material-Icon-60@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Material-Icon-29.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Material-Icon-29@2x-1.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Material-Icon-40.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Material-Icon-40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Material-Icon-76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Material-Icon-76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Material-Icon-83.5@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_close_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_close_white_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_close_white_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_menu_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_menu_white_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_menu_white_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* 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 GraphKit 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
import Material
private struct Item {
var text: String
var detail: String
var image: UIImage?
}
class MainViewController: UIViewController {
/// A tableView used to display Bond entries.
private let tableView: UITableView = UITableView()
/// A list of all the Author Bond types.
private var items: Array<Item> = Array<Item>()
override func viewDidLoad() {
super.viewDidLoad()
prepareView()
prepareItems()
prepareTableView()
}
/**
Handles the search button click, which opens the
SideNavigationBarViewController.
*/
func handleSearchButton() {
sideNavigationBarViewController?.openRightView()
}
/// Prepares view.
private func prepareView() {
view.backgroundColor = MaterialColor.white
}
/// Prepares the items Array.
private func prepareItems() {
items.append(Item(text: "Summer BBQ", detail: "Wish I could come, but I am out of town this weekend.", image: UIImage(named: "Profile1")))
items.append(Item(text: "Birthday gift", detail: "Have any ideas about what we should get Heidi for her birthday?", image: UIImage(named: "Profile2")))
items.append(Item(text: "Brunch this weekend?", detail: "I'll be in your neighborhood doing errands this weekend.", image: UIImage(named: "Profile3")))
items.append(Item(text: "Giants game", detail: "Are we on this weekend for the game?", image: UIImage(named: "Profile4")))
items.append(Item(text: "Recipe to try", detail: "We should eat this: Squash, Corn and tomatillo Tacos.", image: UIImage(named: "Profile5")))
items.append(Item(text: "Interview", detail: "The candidate will be arriving at 11:30, are you free?", image: UIImage(named: "Profile6")))
items.append(Item(text: "Book recommendation", detail: "I found the book title, Surely You’re Joking, Mr. Feynman!", image: UIImage(named: "Profile7")))
items.append(Item(text: "Oui oui", detail: "Do you have Paris recommendations? Have you ever been?", image: UIImage(named: "Profile8")))
}
/// Prepares the tableView.
private func prepareTableView() {
tableView.registerClass(MaterialTableViewCell.self, forCellReuseIdentifier: "MaterialTableViewCell")
tableView.dataSource = self
tableView.delegate = self
// Use MaterialLayout to easily align the tableView.
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
MaterialLayout.alignToParent(view, child: tableView)
}
}
/// TableViewDataSource methods.
extension MainViewController: UITableViewDataSource {
/// Determines the number of rows in the tableView.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count;
}
/// Returns the number of sections.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
/// Prepares the cells within the tableView.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: MaterialTableViewCell = MaterialTableViewCell(style: .Subtitle, reuseIdentifier: "MaterialTableViewCell")
let item: Item = items[indexPath.row]
cell.selectionStyle = .None
cell.textLabel!.text = item.text
cell.textLabel!.font = RobotoFont.regular
cell.detailTextLabel!.text = item.detail
cell.detailTextLabel!.font = RobotoFont.regular
cell.detailTextLabel!.textColor = MaterialColor.grey.darken1
cell.imageView!.image = item.image?.resize(toWidth: 40)
cell.imageView!.layer.cornerRadius = 20
return cell
}
/// Prepares the header within the tableView.
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView(frame: CGRectMake(0, 0, view.bounds.width, 48))
header.backgroundColor = MaterialColor.white
let label: UILabel = UILabel()
label.font = RobotoFont.medium
label.textColor = MaterialColor.grey.darken1
label.text = "Today"
header.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
MaterialLayout.alignToParent(header, child: label, left: searchBarViewController!.searchBarView.contentInset.left + searchBarViewController!.searchBarView.spacing)
return header
}
}
/// UITableViewDelegate methods.
extension MainViewController: UITableViewDelegate {
/// Sets the tableView cell height.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 80
}
/// Sets the tableView header height.
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 48
}
}
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
65FDC2EB1C66858A00103AC2 /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65FDC2EA1C66858A00103AC2 /* Menu.swift */; }; 65FDC2EB1C66858A00103AC2 /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65FDC2EA1C66858A00103AC2 /* Menu.swift */; };
960036151C77E1B600EBA579 /* SearchBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960036141C77E1B600EBA579 /* SearchBarViewController.swift */; };
960B23271C383E5500E96216 /* Material+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23261C383E5500E96216 /* Material+String.swift */; }; 960B23271C383E5500E96216 /* Material+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23261C383E5500E96216 /* Material+String.swift */; };
960B232E1C383EAA00E96216 /* Material+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23281C383EAA00E96216 /* Material+UIImage.swift */; }; 960B232E1C383EAA00E96216 /* Material+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23281C383EAA00E96216 /* Material+UIImage.swift */; };
960B232F1C383EAA00E96216 /* Material+UIImage+Crop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */; }; 960B232F1C383EAA00E96216 /* Material+UIImage+Crop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */; };
...@@ -126,6 +127,7 @@ ...@@ -126,6 +127,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
65FDC2EA1C66858A00103AC2 /* Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = "<group>"; }; 65FDC2EA1C66858A00103AC2 /* Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = "<group>"; };
960036141C77E1B600EBA579 /* SearchBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBarViewController.swift; sourceTree = "<group>"; };
960B23261C383E5500E96216 /* Material+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+String.swift"; sourceTree = "<group>"; }; 960B23261C383E5500E96216 /* Material+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+String.swift"; sourceTree = "<group>"; };
960B23281C383EAA00E96216 /* Material+UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage.swift"; sourceTree = "<group>"; }; 960B23281C383EAA00E96216 /* Material+UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage.swift"; sourceTree = "<group>"; };
960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage+Crop.swift"; sourceTree = "<group>"; }; 960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage+Crop.swift"; sourceTree = "<group>"; };
...@@ -447,6 +449,7 @@ ...@@ -447,6 +449,7 @@
children = ( children = (
96A71FB21C764E3200C0C4AE /* StatusBarView.swift */, 96A71FB21C764E3200C0C4AE /* StatusBarView.swift */,
96A71EF51C71127100C0C4AE /* SearchBarView.swift */, 96A71EF51C71127100C0C4AE /* SearchBarView.swift */,
960036141C77E1B600EBA579 /* SearchBarViewController.swift */,
96D88C151C1328D800B91418 /* NavigationBarView.swift */, 96D88C151C1328D800B91418 /* NavigationBarView.swift */,
96A71F2F1C72E41100C0C4AE /* NavigationBarViewController.swift */, 96A71F2F1C72E41100C0C4AE /* NavigationBarViewController.swift */,
96D88C1D1C1328D800B91418 /* SideNavigationViewController.swift */, 96D88C1D1C1328D800B91418 /* SideNavigationViewController.swift */,
...@@ -626,6 +629,7 @@ ...@@ -626,6 +629,7 @@
960B23481C38480E00E96216 /* TextView.swift in Sources */, 960B23481C38480E00E96216 /* TextView.swift in Sources */,
96D88C291C1328D800B91418 /* MaterialBasicAnimation.swift in Sources */, 96D88C291C1328D800B91418 /* MaterialBasicAnimation.swift in Sources */,
96D88C3A1C1328D800B91418 /* MaterialTextLayer.swift in Sources */, 96D88C3A1C1328D800B91418 /* MaterialTextLayer.swift in Sources */,
960036151C77E1B600EBA579 /* SearchBarViewController.swift in Sources */,
96A71EF61C71127100C0C4AE /* SearchBarView.swift in Sources */, 96A71EF61C71127100C0C4AE /* SearchBarView.swift in Sources */,
96D88C371C1328D800B91418 /* MaterialRadius.swift in Sources */, 96D88C371C1328D800B91418 /* MaterialRadius.swift in Sources */,
960B232F1C383EAA00E96216 /* Material+UIImage+Crop.swift in Sources */, 960B232F1C383EAA00E96216 /* Material+UIImage+Crop.swift in Sources */,
......
...@@ -30,6 +30,11 @@ ...@@ -30,6 +30,11 @@
import UIKit import UIKit
@objc(NavigationBarView)
public protocol NavigationBarViewDelegate : MaterialDelegate {
optional func navigationBarViewDidChangeLayout(navigationBarView: NavigationBarView)
}
public class NavigationBarView : StatusBarView { public class NavigationBarView : StatusBarView {
/// Title label. /// Title label.
public var titleLabel: UILabel? { public var titleLabel: UILabel? {
...@@ -140,4 +145,8 @@ public class NavigationBarView : StatusBarView { ...@@ -140,4 +145,8 @@ public class NavigationBarView : StatusBarView {
self.titleLabel = titleLabel self.titleLabel = titleLabel
self.detailLabel = detailLabel self.detailLabel = detailLabel
} }
internal override func statusBarViewDidChangeLayout() {
(delegate as? NavigationBarViewDelegate)?.navigationBarViewDidChangeLayout?(self)
}
} }
...@@ -161,9 +161,9 @@ public class NavigationBarViewController: UIViewController { ...@@ -161,9 +161,9 @@ public class NavigationBarViewController: UIViewController {
} }
} }
extension NavigationBarViewController : StatusBarViewDelegate { extension NavigationBarViewController : NavigationBarViewDelegate {
/// Monitor layout changes. /// Monitor layout changes.
public func statusBarViewDidChangeLayout(statusBarView: StatusBarView) { public func navigationBarViewDidChangeLayout(navigationBarView: NavigationBarView) {
layoutSubviews() layoutSubviews()
} }
} }
\ No newline at end of file
...@@ -91,6 +91,8 @@ public class SearchBarView : StatusBarView { ...@@ -91,6 +91,8 @@ public class SearchBarView : StatusBarView {
public override func layoutSubviews() { public override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
grid.axis.columns = Int(width / 48)
// General alignment. // General alignment.
if UIApplication.sharedApplication().statusBarOrientation.isLandscape { if UIApplication.sharedApplication().statusBarOrientation.isLandscape {
grid.contentInset.top = 8 grid.contentInset.top = 8
...@@ -100,8 +102,6 @@ public class SearchBarView : StatusBarView { ...@@ -100,8 +102,6 @@ public class SearchBarView : StatusBarView {
height = 64 height = 64
} }
// Column adjustment.
width = UIScreen.mainScreen().bounds.width
reloadView() reloadView()
} }
...@@ -114,12 +114,12 @@ public class SearchBarView : StatusBarView { ...@@ -114,12 +114,12 @@ public class SearchBarView : StatusBarView {
public override func reloadView() { public override func reloadView() {
super.reloadView() super.reloadView()
/// Prepare the clearButton /// Prepare the clearButton.
if let v: UIButton = clearButton { if let v: UIButton = clearButton {
v.frame = CGRectMake(0, 0, textField.height, textField.height) v.frame = CGRectMake(0, 0, textField.height, textField.height)
} }
textField.grid.columns -= textField.grid.offset.columns textField.grid.columns = contentView.grid.columns
grid.reloadLayout() grid.reloadLayout()
} }
...@@ -154,5 +154,10 @@ public class SearchBarView : StatusBarView { ...@@ -154,5 +154,10 @@ public class SearchBarView : StatusBarView {
textField.clearButtonMode = .Never textField.clearButtonMode = .Never
textField.rightViewMode = .WhileEditing textField.rightViewMode = .WhileEditing
contentView.addSubview(textField) contentView.addSubview(textField)
contentView.grid.views = [textField]
}
internal override func statusBarViewDidChangeLayout() {
(delegate as? SearchBarViewDelegate)?.searchBarViewDidChangeLayout?(self)
} }
} }
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* 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 Material 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
public extension UIViewController {
/**
A convenience property that provides access to the SearchBarViewController.
This is the recommended method of accessing the SearchBarViewController
through child UIViewControllers.
*/
public var searchBarViewController: SearchBarViewController? {
var viewController: UIViewController? = self
while nil != viewController {
if viewController is SearchBarViewController {
return viewController as? SearchBarViewController
}
viewController = viewController?.parentViewController
}
return nil
}
}
public class SearchBarViewController: UIViewController {
public private(set) lazy var searchBarView: SearchBarView = SearchBarView()
/**
A Boolean property used to enable and disable interactivity
with the mainViewController.
*/
public var userInteractionEnabled: Bool {
get {
return mainViewController.view.userInteractionEnabled
}
set(value) {
mainViewController.view.userInteractionEnabled = value
}
}
/**
A UIViewController property that references the active
main UIViewController. To swap the mainViewController, it
is recommended to use the transitionFromMainViewController
helper method.
*/
public private(set) var mainViewController: UIViewController!
/**
An initializer for the SearchBarViewController.
- Parameter mainViewController: The main UIViewController.
*/
public convenience init(mainViewController: UIViewController) {
self.init()
self.mainViewController = mainViewController
prepareView()
}
public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
layoutSubviews()
}
/**
A method to swap mainViewController objects.
- Parameter toViewController: The UIViewController to swap
with the active mainViewController.
- Parameter duration: A NSTimeInterval that sets the
animation duration of the transition.
- Parameter options: UIViewAnimationOptions thst are used
when animating the transition from the active mainViewController
to the toViewController.
- Parameter animations: An animation block that is executed during
the transition from the active mainViewController
to the toViewController.
- Parameter completion: A completion block that is execited after
the transition animation from the active mainViewController
to the toViewController has completed.
*/
public func transitionFromMainViewController(toViewController: UIViewController, duration: NSTimeInterval = 0.5, options: UIViewAnimationOptions = [], animations: (() -> Void)?, completion: ((Bool) -> Void)?) {
mainViewController.willMoveToParentViewController(nil)
addChildViewController(toViewController)
toViewController.view.frame = view.bounds
transitionFromViewController(mainViewController,
toViewController: toViewController,
duration: duration,
options: options,
animations: animations,
completion: { [unowned self] (result: Bool) in
toViewController.didMoveToParentViewController(self)
self.mainViewController.removeFromParentViewController()
self.mainViewController = toViewController
completion?(result)
})
}
/// A method that generally prepares the SearchBarViewController.
private func prepareView() {
prepareSearchBarView()
prepareMainViewController()
}
/// Prepares the SearchBarView.
private func prepareSearchBarView() {
searchBarView.delegate = self
view.addSubview(searchBarView)
}
/// A method that prepares the mainViewController.
private func prepareMainViewController() {
prepareViewControllerWithinContainer(mainViewController, container: view)
}
/**
A method that adds the passed in controller as a child of
the SearchBarViewController within the passed in
container view.
- Parameter viewController: A UIViewController to add as a child.
- Parameter container: A UIView that is the parent of the
passed in controller view within the view hierarchy.
*/
private func prepareViewControllerWithinContainer(viewController: UIViewController?, container: UIView) {
if let v: UIViewController = viewController {
addChildViewController(v)
container.insertSubview(v.view, atIndex: 0)
v.didMoveToParentViewController(self)
}
}
/// Layout subviews.
private func layoutSubviews() {
let size: CGSize = UIScreen.mainScreen().bounds.size
let h: CGFloat = UIApplication.sharedApplication().statusBarFrame.size.height
mainViewController.view.frame = CGRectMake(0, searchBarView.height, size.width, size.height - searchBarView.height - (20 >= h ? 0 : h - 20))
}
}
extension SearchBarViewController : SearchBarViewDelegate {
/// Monitor layout changes.
public func searchBarViewDidChangeLayout(searchBarView: SearchBarView) {
layoutSubviews()
}
}
\ No newline at end of file
...@@ -30,12 +30,6 @@ ...@@ -30,12 +30,6 @@
import UIKit import UIKit
@objc(StatusBarViewDelegate)
public protocol StatusBarViewDelegate : MaterialDelegate {
optional func statusBarViewDidChangeLayout(statusBarView: StatusBarView)
}
@objc(StatusBarView)
public class StatusBarView : ControlView { public class StatusBarView : ControlView {
/// Tracks the old frame size. /// Tracks the old frame size.
private var oldFrame: CGRect? private var oldFrame: CGRect?
...@@ -66,7 +60,9 @@ public class StatusBarView : ControlView { ...@@ -66,7 +60,9 @@ public class StatusBarView : ControlView {
width = UIScreen.mainScreen().bounds.width width = UIScreen.mainScreen().bounds.width
if frame.origin.x != oldFrame!.origin.x || frame.origin.y != oldFrame!.origin.y || frame.width != oldFrame!.width || frame.height != oldFrame!.height { if frame.origin.x != oldFrame!.origin.x || frame.origin.y != oldFrame!.origin.y || frame.width != oldFrame!.width || frame.height != oldFrame!.height {
(delegate as? StatusBarViewDelegate)?.statusBarViewDidChangeLayout?(self) if nil != delegate {
statusBarViewDidChangeLayout()
}
oldFrame = frame oldFrame = frame
} }
reloadView() reloadView()
...@@ -97,4 +93,7 @@ public class StatusBarView : ControlView { ...@@ -97,4 +93,7 @@ public class StatusBarView : ControlView {
grid.contentInset.right = 8 grid.contentInset.right = 8
grid.axis.inherited = false grid.axis.inherited = false
} }
/// Chaining method for subclasses to offer delegation or other useful features.
internal func statusBarViewDidChangeLayout() {}
} }
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