From ba55ff6c623af86844e8252ad08c4b7a395285ed Mon Sep 17 00:00:00 2001 From: Xin Hong Date: Wed, 12 Dec 2018 17:41:03 +0800 Subject: [PATCH] feature: custom section header --- DropdownMenu/DropdownItem.swift | 4 +- DropdownMenu/DropdownMenu.swift | 93 +++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/DropdownMenu/DropdownItem.swift b/DropdownMenu/DropdownItem.swift index f4c62a6..9ab3721 100644 --- a/DropdownMenu/DropdownItem.swift +++ b/DropdownMenu/DropdownItem.swift @@ -30,9 +30,11 @@ open class DropdownItem { public struct DropdownSection { public var sectionIdentifier: String public var items: [DropdownItem] + public var customSectionHeader: UIView? - public init (sectionIdentifier: String, items: [DropdownItem]) { + public init (sectionIdentifier: String, items: [DropdownItem], customSectionHeader: UIView? = nil) { self.items = items self.sectionIdentifier = sectionIdentifier + self.customSectionHeader = customSectionHeader } } diff --git a/DropdownMenu/DropdownMenu.swift b/DropdownMenu/DropdownMenu.swift index 3950afd..742c9cd 100644 --- a/DropdownMenu/DropdownMenu.swift +++ b/DropdownMenu/DropdownMenu.swift @@ -9,9 +9,11 @@ import UIKit public protocol DropdownMenuDelegate: class { + func dropdownMenu(_ dropdownMenu: DropdownMenu, heightForHeaderInSection section: Int) -> CGFloat func dropdownMenu(_ dropdownMenu: DropdownMenu, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) func dropdownMenu(_ dropdownMenu: DropdownMenu, cellForRowAt indexPath: IndexPath) -> UITableViewCell? func dropdownMenu(_ dropdownMenu: DropdownMenu, didSelectRowAt indexPath: IndexPath) + func dropdownMenu(_ dropdownMenu: DropdownMenu, shouldDismissWhenSelectRowAt indexPath: IndexPath) -> Bool func dropdownMenu(_ dropdownMenu: DropdownMenu, shouldUpdateSelectionAt indexPath: IndexPath) -> Bool func dropdownMenuCancel(_ dropdownMenu: DropdownMenu) func dropdownMenuWillDismiss(_ dropdownMenu: DropdownMenu) @@ -19,9 +21,11 @@ public protocol DropdownMenuDelegate: class { } public extension DropdownMenuDelegate { + func dropdownMenu(_ dropdownMenu: DropdownMenu, heightForHeaderInSection section: Int) -> CGFloat { return 44 } func dropdownMenu(_ dropdownMenu: DropdownMenu, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { } func dropdownMenu(_ dropdownMenu: DropdownMenu, cellForRowAt indexPath: IndexPath) -> UITableViewCell? { return nil } func dropdownMenu(_ dropdownMenu: DropdownMenu, didSelectRowAt indexPath: IndexPath) { } + func dropdownMenu(_ dropdownMenu: DropdownMenu, shouldDismissWhenSelectRowAt indexPath: IndexPath) -> Bool { return true } func dropdownMenu(_ dropdownMenu: DropdownMenu, shouldUpdateSelectionAt indexPath: IndexPath) -> Bool { return true } func dropdownMenuCancel(_ dropdownMenu: DropdownMenu) { } func dropdownMenuWillDismiss(_ dropdownMenu: DropdownMenu) { } @@ -41,6 +45,7 @@ open class DropdownMenu: UIView { fileprivate var windowRootView: UIView? fileprivate var topConstraint: NSLayoutConstraint? fileprivate var navigationBarCoverViewHeightConstraint: NSLayoutConstraint? + fileprivate var tableViewHeightConstraint: NSLayoutConstraint? fileprivate let iPhoneXPortraitTopOffset: CGFloat = 88.0 fileprivate let portraitTopOffset: CGFloat = 64.0 fileprivate let landscapeTopOffset: CGFloat = 32.0 @@ -57,7 +62,6 @@ open class DropdownMenu: UIView { open var backgroudBeginColor: UIColor = UIColor.black.withAlphaComponent(0) open var backgroudEndColor = UIColor(white: 0, alpha: 0.4) open var rowHeight: CGFloat = 50 - open var sectionHeaderHeight: CGFloat = 44 open var tableViewHeight: CGFloat = 0 open var defaultBottonMargin: CGFloat = 150 open var topOffsetY: CGFloat = 0 @@ -123,6 +127,33 @@ open class DropdownMenu: UIView { NotificationCenter.default.addObserver(self, selector: #selector(self.updateForOrientationChange(_:)), name: UIApplication.willChangeStatusBarOrientationNotification, object: nil) } + + public func updateItems(_ items: [DropdownItem]) { + self.sections = [DropdownSection(sectionIdentifier: "", items: items)] + self.tableView.beginUpdates() + self.tableView.reloadSections(IndexSet(integer: 0), with: .fade) + self.tableView.endUpdates() + updateForSectionsChange() + } + + public func updateSections(_ sections: [DropdownSection]) { + self.sections = sections + self.tableView.reloadData() + updateForSectionsChange() + } + + public func updateItems(_ items: [DropdownItem], inSection section: Int) { + guard 0.. Void)? = nil) { + updateTableViewHeight() + tableViewHeightConstraint?.constant = tableViewHeight + UIView.animate(withDuration: 0.3) { [weak self] in + guard let strongSelf = self else { + return + } + animations?() + strongSelf.layoutIfNeeded() + } } fileprivate func setupTopSeperatorView() { @@ -226,11 +275,12 @@ open class DropdownMenu: UIView { fileprivate func tableviewHeight() -> CGFloat { var height: CGFloat = 0 - if displaySectionHeader { - height += sectionHeaderHeight * CGFloat(sections.count) - } - for section in sections { - height += CGFloat(section.items.count) * rowHeight + sections.enumerated().forEach { + if displaySectionHeader { + let sectionHeaderHeight = delegate?.dropdownMenu(self, heightForHeaderInSection: $0) ?? 44 + height += sectionHeaderHeight + } + height += CGFloat($1.items.count) * rowHeight } return height } @@ -370,7 +420,10 @@ extension DropdownMenu: UITableViewDelegate { } public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return displaySectionHeader ? sectionHeaderHeight : CGFloat.leastNormalMagnitude + guard displaySectionHeader else { + return .leastNormalMagnitude + } + return delegate?.dropdownMenu(self, heightForHeaderInSection: section) ?? 44 } public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { @@ -390,13 +443,21 @@ extension DropdownMenu: UITableViewDelegate { } } tableView.deselectRow(at: indexPath, animated: true) - hideMenu(isSelectAction: true) + let shouldDismiss = delegate?.dropdownMenu(self, shouldDismissWhenSelectRowAt: indexPath) ?? true + if shouldDismiss { + hideMenu(isSelectAction: true) + } delegate?.dropdownMenu(self, didSelectRowAt: indexPath) } public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let sectionHeader = SectionHeader(style: sectionHeaderStyle) - sectionHeader.titleLabel.text = sections[section].sectionIdentifier - return sectionHeader + let dropdownSection = sections[section] + if let customSectionHeader = dropdownSection.customSectionHeader { + return customSectionHeader + } else { + let sectionHeader = SectionHeader(style: sectionHeaderStyle) + sectionHeader.titleLabel.text = dropdownSection.sectionIdentifier + return sectionHeader + } } }