| // Copyright 2017-present the Material Components for iOS authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| import UIKit |
| |
| import MaterialComponents.MaterialButtons |
| |
| class FloatingButtonExampleSwiftViewController: UIViewController { |
| |
| let miniFloatingButton = MDCFloatingButton(frame: .zero, shape: .mini) |
| let defaultFloatingButton = MDCFloatingButton() |
| let largeIconFloatingButton = MDCFloatingButton() |
| |
| override func viewDidLoad() { |
| super.viewDidLoad() |
| |
| view.backgroundColor = UIColor(white: 0.9, alpha: 1) |
| |
| let plusImage = #imageLiteral(resourceName: "Plus") |
| let plusImage36 = UIImage(named: "plus_white_36", in: Bundle(for: type(of: self)), |
| compatibleWith: traitCollection) |
| |
| miniFloatingButton.sizeToFit() |
| miniFloatingButton.translatesAutoresizingMaskIntoConstraints = false |
| miniFloatingButton.setMinimumSize(CGSize(width: 96, height: 40), for: .mini, in: .expanded) |
| miniFloatingButton.setImage(plusImage, for: .normal) |
| miniFloatingButton.accessibilityLabel = "Create" |
| |
| defaultFloatingButton.sizeToFit() |
| defaultFloatingButton.translatesAutoresizingMaskIntoConstraints = false |
| defaultFloatingButton.setImage(plusImage, for: .normal) |
| defaultFloatingButton.accessibilityLabel = "Create" |
| |
| largeIconFloatingButton.sizeToFit() |
| largeIconFloatingButton.translatesAutoresizingMaskIntoConstraints = false |
| largeIconFloatingButton.setImage(plusImage36, for: .normal) |
| largeIconFloatingButton.accessibilityLabel = "Create" |
| largeIconFloatingButton.setContentEdgeInsets(UIEdgeInsetsMake(-6, -6, -6, 0), for: .default, |
| in: .expanded) |
| |
| let label = UILabel() |
| label.translatesAutoresizingMaskIntoConstraints = false |
| label.text = "Try me on an iPad!" |
| |
| view.addSubview(label) |
| view.addSubview(miniFloatingButton) |
| view.addSubview(defaultFloatingButton) |
| view.addSubview(largeIconFloatingButton) |
| |
| let totalHeight = miniFloatingButton.bounds.standardized.height + |
| defaultFloatingButton.bounds.standardized.height + |
| largeIconFloatingButton.bounds.standardized.height + |
| 20 // 10 points between buttons |
| |
| let miniDefaultDifference = defaultFloatingButton.bounds.standardized.width - |
| miniFloatingButton.bounds.standardized.width |
| |
| leadingAlignView(view: miniFloatingButton, onView: self.view, |
| horizontalOffset: 10 + miniDefaultDifference / 2, |
| verticalOffset: -totalHeight / 2) |
| leadingAlignView(view: defaultFloatingButton, onView: miniFloatingButton, |
| horizontalOffset: -miniDefaultDifference / 2, |
| verticalOffset: defaultFloatingButton.bounds.standardized.height + 10) |
| leadingAlignView(view: largeIconFloatingButton, onView: defaultFloatingButton, |
| horizontalOffset: 0, |
| verticalOffset: defaultFloatingButton.bounds.standardized.height + 10) |
| self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .centerX, relatedBy: .equal, |
| toItem: view, attribute: .centerX, multiplier: 1, |
| constant: 0)) |
| self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .bottom, relatedBy: .equal, |
| toItem: miniFloatingButton, attribute: .top, |
| multiplier: 1, constant: -20)) |
| } |
| |
| // MARK: Private |
| |
| private func leadingAlignView(view: UIView, onView: UIView, horizontalOffset: CGFloat, |
| verticalOffset: CGFloat) { |
| self.view.addConstraint(NSLayoutConstraint( |
| item: view, |
| attribute: .leading, |
| relatedBy: .equal, |
| toItem: onView, |
| attribute: .leading, |
| multiplier: 1.0, |
| constant: horizontalOffset)) |
| |
| self.view.addConstraint(NSLayoutConstraint( |
| item: view, |
| attribute: .centerY, |
| relatedBy: .equal, |
| toItem: onView, |
| attribute: .centerY, |
| multiplier: 1.0, |
| constant: verticalOffset)) |
| } |
| } |
| |
| extension FloatingButtonExampleSwiftViewController { |
| |
| class func catalogMetadata() -> [String: Any] { |
| return [ |
| "breadcrumbs": ["Buttons", "Floating Action Button (Swift)"], |
| "primaryDemo": false, |
| "presentable": false, |
| ] |
| } |
| } |
| |
| extension FloatingButtonExampleSwiftViewController { |
| func updateFloatingButtons(to mode: MDCFloatingButtonMode) { |
| if (miniFloatingButton.mode != mode) { |
| miniFloatingButton.mode = mode |
| } |
| if (defaultFloatingButton.mode != mode) { |
| defaultFloatingButton.mode = mode |
| } |
| if (largeIconFloatingButton.mode != mode) { |
| largeIconFloatingButton.mode = mode |
| } |
| } |
| |
| func updateFloatingButtons(whenSizeClass isRegularRegular: Bool) { |
| if (isRegularRegular) { |
| updateFloatingButtons(to: .expanded) |
| miniFloatingButton.setTitle("Add", for: .normal) |
| defaultFloatingButton.setTitle("Create", for: .normal) |
| largeIconFloatingButton.setTitle("Create", for: .normal) |
| } else { |
| updateFloatingButtons(to: .normal) |
| miniFloatingButton.setTitle(nil, for: .normal) |
| defaultFloatingButton.setTitle(nil, for: .normal) |
| largeIconFloatingButton.setTitle(nil, for: .normal) |
| } |
| } |
| |
| override func viewWillAppear(_ animated: Bool) { |
| super.viewWillAppear(animated) |
| let horizontalSizeClass = traitCollection.horizontalSizeClass |
| let verticalSizeClass = traitCollection.verticalSizeClass |
| let isRegularRegular = horizontalSizeClass == .regular && verticalSizeClass == .regular |
| updateFloatingButtons(whenSizeClass: isRegularRegular) |
| } |
| |
| override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { |
| super.willTransition(to: newCollection, with: coordinator) |
| let currentTraits = traitCollection |
| let sizeClassChanged = |
| newCollection.horizontalSizeClass != currentTraits.horizontalSizeClass || |
| newCollection.verticalSizeClass != currentTraits.verticalSizeClass |
| if (sizeClassChanged) { |
| let willBeRegularRegular = |
| newCollection.horizontalSizeClass == .regular && |
| newCollection.verticalSizeClass == .regular |
| |
| coordinator.animate(alongsideTransition:{ (_) in |
| self.updateFloatingButtons(whenSizeClass: willBeRegularRegular) |
| }, completion: nil) |
| } |
| } |
| } |