123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
-
- The MIT License (MIT)
- Copyright (c) 2017-2018 Dalton Hinterscher
-
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
- THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- */
- import UIKit
- import SnapKit
- open class GrowingNotificationBanner: BaseNotificationBanner {
-
- public enum IconPosition {
- case top
- case center
- }
-
- /// The height of the banner when it is presented
- override public var bannerHeight: CGFloat {
- get {
- if let customBannerHeight = customBannerHeight {
- return customBannerHeight
- } else {
- // Calculate the height based on contents of labels
-
- // Determine available width for displaying the label
- var boundingWidth = UIScreen.main.bounds.width - padding * 2
-
- // Substract safeAreaInsets from width, if available
- // We have to use keyWindow to ask for safeAreaInsets as `self` only knows its' safeAreaInsets in layoutSubviews
- if #available(iOS 11.0, *), let keyWindow = UIApplication.shared.keyWindow {
- let safeAreaOffset = keyWindow.safeAreaInsets.left + keyWindow.safeAreaInsets.right
-
- boundingWidth -= safeAreaOffset
- }
-
- if leftView != nil {
- boundingWidth -= sideViewSize + padding
- }
-
- if rightView != nil {
- boundingWidth -= sideViewSize + padding
- }
-
- let titleHeight = ceil(titleLabel?.sizeThatFits(
- CGSize(width: boundingWidth,
- height: .greatestFiniteMagnitude)).height ?? 0.0)
-
- let subtitleHeight = ceil(subtitleLabel?.sizeThatFits(
- CGSize(width: boundingWidth,
- height: .greatestFiniteMagnitude)).height ?? 0.0)
-
- let topOffset: CGFloat = shouldAdjustForNotchFeaturedIphone() ? 44.0 : verticalSpacing
- let minHeight: CGFloat = shouldAdjustForNotchFeaturedIphone() ? 88.0 : 64.0
-
- var actualBannerHeight = topOffset + titleHeight + subtitleHeight + verticalSpacing
-
- if !subtitleHeight.isZero && !titleHeight.isZero {
- actualBannerHeight += innerSpacing
- }
-
- return heightAdjustment + max(actualBannerHeight, minHeight)
- }
- } set {
- customBannerHeight = newValue
- }
- }
-
- /// Spacing between the last label and the bottom edge of the banner
- private let verticalSpacing: CGFloat = 14.0
-
- /// Spacing between title and subtitle
- private let innerSpacing: CGFloat = 2.5
-
- /// The bottom most label of the notification if a subtitle is provided
- public private(set) var subtitleLabel: TTTAttributedLabel?
-
- /// The view that is presented on the left side of the notification
- private var leftView: UIView?
-
- /// The view that is presented on the right side of the notification
- private var rightView: UIView?
-
- /// Square size for left/right view if set
- private let sideViewSize: CGFloat
-
- /// Font used for the title label
- internal var titleFont: UIFont = UIFont.systemFont(ofSize: 17.5, weight: UIFont.Weight.bold)
-
- /// Font used for the subtitle label
- internal var subtitleFont: UIFont = UIFont.systemFont(ofSize: 15.0)
-
- public init(title: String? = nil,
- subtitle: String? = nil,
- leftView: UIView? = nil,
- rightView: UIView? = nil,
- style: BannerStyle = .info,
- colors: BannerColorsProtocol? = nil,
- iconPosition: IconPosition = .center,
- sideViewSize: CGFloat = 24.0) {
-
- self.leftView = leftView
- self.rightView = rightView
- self.sideViewSize = sideViewSize
-
- super.init(style: style, colors: colors)
-
- let labelsView = UIStackView()
- labelsView.axis = .vertical
- labelsView.spacing = innerSpacing
-
- let outerStackView = UIStackView()
- outerStackView.spacing = padding
-
- switch iconPosition {
- case .top:
- outerStackView.alignment = .top
- case .center:
- outerStackView.alignment = .center
- }
-
- if let leftView = leftView {
- outerStackView.addArrangedSubview(leftView)
- leftView.snp.makeConstraints { $0.size.equalTo(sideViewSize) }
- }
-
- outerStackView.addArrangedSubview(labelsView)
-
- if let title = title {
- titleLabel = UILabel()
- titleLabel!.font = titleFont
- titleLabel!.numberOfLines = 0
- titleLabel!.textColor = .white
- titleLabel!.text = title
- titleLabel!.setContentHuggingPriority(.required, for: .vertical)
- labelsView.addArrangedSubview(titleLabel!)
- }
-
- if let subtitle = subtitle {
- subtitleLabel = TTTAttributedLabel.init(frame: .zero)
- subtitleLabel!.font = subtitleFont
- subtitleLabel!.numberOfLines = 0
- subtitleLabel!.textColor = .white
- subtitleLabel!.text = subtitle
- if title == nil {
- subtitleLabel!.setContentHuggingPriority(.required, for: .vertical)
- }
- labelsView.addArrangedSubview(subtitleLabel!)
- }
-
- if let rightView = rightView {
- outerStackView.addArrangedSubview(rightView)
- rightView.snp.makeConstraints { $0.size.equalTo(sideViewSize) }
- }
-
- contentView.addSubview(outerStackView)
- outerStackView.snp.makeConstraints { (make) in
- if #available(iOS 11.0, *) {
- make.left.equalTo(safeAreaLayoutGuide).offset(padding)
- make.right.equalTo(safeAreaLayoutGuide).offset(-padding)
- } else {
- make.left.equalToSuperview().offset(padding)
- make.right.equalToSuperview().offset(-padding)
- }
-
- make.centerY.equalToSuperview()
- }
- }
-
- required public init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- override func spacerViewHeight() -> CGFloat {
- return super.spacerViewHeight() + heightAdjustment
- }
- }
- public extension GrowingNotificationBanner {
-
- func applyStyling(cornerRadius: CGFloat? = nil,
- titleFont: UIFont? = nil,
- titleColor: UIColor? = nil,
- titleTextAlign: NSTextAlignment? = nil,
- subtitleFont: UIFont? = nil,
- subtitleColor: UIColor? = nil,
- subtitleTextAlign: NSTextAlignment? = nil) {
-
- if let cornerRadius = cornerRadius {
- contentView.layer.cornerRadius = cornerRadius
- }
-
- if let titleFont = titleFont {
- self.titleFont = titleFont
- titleLabel!.font = titleFont
- }
-
- if let titleColor = titleColor {
- titleLabel!.textColor = titleColor
- }
-
- if let titleTextAlign = titleTextAlign {
- titleLabel!.textAlignment = titleTextAlign
- }
-
- if let subtitleFont = subtitleFont {
- self.subtitleFont = subtitleFont
- subtitleLabel!.font = subtitleFont
- }
-
- if let subtitleColor = subtitleColor {
- subtitleLabel!.textColor = subtitleColor
- }
-
- if let subtitleTextAlign = subtitleTextAlign {
- subtitleLabel!.textAlignment = subtitleTextAlign
- }
-
- if titleFont != nil || subtitleFont != nil {
- updateBannerHeight()
- }
- }
-
- }
|