From 6f4db10d33b371906dd31d3360baf2d4721fbf27 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 16 Sep 2019 10:24:18 -0400 Subject: [PATCH 01/22] beginning work on hero. --- MVMCoreUI/Atoms/Views/Label.swift | 41 +++++++++++++++++++ .../Molecules/ActionDetailWithImage.swift | 5 +++ 2 files changed, 46 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index ed99fcac..99576509 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -502,6 +502,47 @@ public typealias ActionBlock = () -> () let accessibleAction = customAccessibilityAction(range: range) clauses.append(ActionableClause(range: range, actionBlock: actionBlock, accessibilityID: accessibleAction?.hash ?? -1)) } + +// func rectOfCharacter() { +// +//// label.intrinsicContentSize.width +// if let range = mylabel.text?.range(of: String(describing: mylabel.text?.characters.last!)) { +// let prefix = mylabel.text?.substring(to: range.lowerBound) +// let size: CGSize = prefix!.size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 35.0)]) +// let position = CGPoint(x:size.width,y: 0) +// myScrollView.setContentOffset(position, animated: true) +// } +// } + + static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { + + guard let attributedText = label.attributedText else { return CGRect() } + + let paragraph = NSMutableParagraphStyle() + paragraph.alignment = label.textAlignment + + let stagedAttributedString = NSMutableAttributedString(attributedString: attributedText) + stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count)) + + let textStorage = NSTextStorage(attributedString: stagedAttributedString) + let layoutManager = NSLayoutManager() + let textContainer = NSTextContainer(size: .zero) + + layoutManager.addTextContainer(textContainer) + textStorage.addLayoutManager(layoutManager) + + textContainer.lineFragmentPadding = 0 + textContainer.lineBreakMode = label.lineBreakMode + textContainer.maximumNumberOfLines = label.numberOfLines + textContainer.size = label.bounds.size + + var glyphRange = NSRange() + + // Convert the range for glyphs. + layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: &glyphRange) + + return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer) + } } // MARK: - Atomization diff --git a/MVMCoreUI/Molecules/ActionDetailWithImage.swift b/MVMCoreUI/Molecules/ActionDetailWithImage.swift index ec91c479..8cdddb5f 100644 --- a/MVMCoreUI/Molecules/ActionDetailWithImage.swift +++ b/MVMCoreUI/Molecules/ActionDetailWithImage.swift @@ -166,5 +166,10 @@ import UIKit } else { button.isHidden = true } + + if let text = header.messageLabel.text, text.contains("frog") { + let rect = Label.boundingRect(forCharacterRange: NSRange(location: 65, length: 4), in: header.messageLabel) + print(rect) + } } } From b9e80398c16c150d68cfbdb17e16a7b151823f51 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 17 Sep 2019 09:41:14 -0400 Subject: [PATCH 02/22] Decent palce. --- MVMCoreUI/Atoms/Views/Label.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 99576509..862fd829 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -514,7 +514,7 @@ public typealias ActionBlock = () -> () // } // } - static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { + public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { guard let attributedText = label.attributedText else { return CGRect() } @@ -531,7 +531,7 @@ public typealias ActionBlock = () -> () layoutManager.addTextContainer(textContainer) textStorage.addLayoutManager(layoutManager) - textContainer.lineFragmentPadding = 0 + textContainer.lineFragmentPadding = 0.0 textContainer.lineBreakMode = label.lineBreakMode textContainer.maximumNumberOfLines = label.numberOfLines textContainer.size = label.bounds.size From fc4fcc25f6b1ebcbb578d8d3c16fa39ed5e1a157 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 17 Sep 2019 16:37:27 -0400 Subject: [PATCH 03/22] Current take on hero. Needs to be refactored and placed into a protocol. --- MVMCoreUI/Atoms/Views/Label.swift | 12 +++++ .../Templates/MoleculeListTemplate.swift | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 862fd829..81159965 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -25,6 +25,7 @@ public typealias ActionBlock = () -> () /// Set this to use a custom sizing object during updateView instead of the standard. public var sizeObject: MFSizeObject? public var scaleSize: NSNumber? + public var hero: Int? // Used for scaling the font in updateView. private var originalAttributedString: NSAttributedString? @@ -562,6 +563,17 @@ extension Label { clauses = [] Label.setUILabel(self, withJSON: json, delegate: delegateObject, additionalData: additionalData) originalAttributedString = attributedText + + hero = json?["hero"] as? Int + } + + func noticeBounds(_ rect: CGRect, color: UIColor) -> UIView { + + let view = UIView(frame: rect) + view.layer.borderColor = color.cgColor + view.layer.borderWidth = 1.0 + + return view } public func setAsMolecule() { diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 0270cb63..0db27a35 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -88,6 +88,38 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { return cell } + open override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + + cell.layoutIfNeeded() + let heroLabel = findHeroLabel(views: cell.contentView.subviews) + let rect = Label.boundingRect(forCharacterRange: NSRange(location: heroLabel!.hero!, length: 1), in: heroLabel!) + let rectView = heroLabel?.noticeBounds(rect, color: .clear) + heroLabel?.addSubview(rectView!) + let convert = cell.contentView.convert(rectView!.center, from: heroLabel) + + cell.accessoryView?.center.y = convert.y + rectView?.removeFromSuperview() + } + + // TODO: Write recursively. + func findHeroLabel(views: [UIView]) -> Label? { + + var queue: [UIView] = views + + repeat { + for view in queue { + if let label = view as? Label, label.hero != nil { + return label + } else if !view.subviews.isEmpty { + queue.append(contentsOf: view.subviews) + } + queue.removeFirst() + } + } while (!queue.isEmpty) + + return nil + } + open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let cell = tableView.cellForRow(at: indexPath) as? MoleculeListCellProtocol { cell.didSelectCell?(atIndex: indexPath, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) @@ -111,11 +143,24 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { if let tableView = tableView { let point = molecule.convert(molecule.bounds.origin, to: tableView) if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false { + //------------- tableView.beginUpdates() +// let cell = tableView.cellForRow(at: indexPath) +// cell.layoutIfNeeded() +// let heroLabel = findHeroLabel(views: cell.contentView.subviews) +// let rect = Label.boundingRect(forCharacterRange: NSRange(location: heroLabel!.hero!, length: 1), in: heroLabel!) +// let rectView = heroLabel?.noticeBounds(rect, color: .blue) +// heroLabel?.addSubview(rectView!) +// // let rect = Label.boundingRect(forCharacterRange: NSRange(location: 46, length: 6), in: self) +// let convert = cell.contentView.convert(rectView!.center, from: heroLabel) +// +// cell.accessoryView?.center.y = convert.y + /// ------------ tableView.endUpdates() } } } + open override func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { // This dispatch is needed to fix a race condition that can occur if this function is called during the table setup. From 5bc420ac05399ebf31d2310cfe932472b5b77f94 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 18 Sep 2019 14:13:33 -0400 Subject: [PATCH 04/22] accessoryVIew can now center itself in relation to the hero character. --- MVMCoreUI/Atoms/Views/Label.swift | 24 +------- .../Molecules/ActionDetailWithImage.swift | 5 -- .../Items/MoleculeTableViewCell.swift | 57 ++++++++++++++++--- .../Molecules/MVMCoreUIMoleculeViewProtocol.h | 2 + .../Templates/MoleculeListTemplate.swift | 53 ++--------------- 5 files changed, 61 insertions(+), 80 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 81159965..cab341b1 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -25,6 +25,8 @@ public typealias ActionBlock = () -> () /// Set this to use a custom sizing object during updateView instead of the standard. public var sizeObject: MFSizeObject? public var scaleSize: NSNumber? + + /// A specific text index to use as a unique marker. public var hero: Int? // Used for scaling the font in updateView. @@ -503,18 +505,7 @@ public typealias ActionBlock = () -> () let accessibleAction = customAccessibilityAction(range: range) clauses.append(ActionableClause(range: range, actionBlock: actionBlock, accessibilityID: accessibleAction?.hash ?? -1)) } - -// func rectOfCharacter() { -// -//// label.intrinsicContentSize.width -// if let range = mylabel.text?.range(of: String(describing: mylabel.text?.characters.last!)) { -// let prefix = mylabel.text?.substring(to: range.lowerBound) -// let size: CGSize = prefix!.size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 35.0)]) -// let position = CGPoint(x:size.width,y: 0) -// myScrollView.setContentOffset(position, animated: true) -// } -// } - + public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { guard let attributedText = label.attributedText else { return CGRect() } @@ -567,15 +558,6 @@ extension Label { hero = json?["hero"] as? Int } - func noticeBounds(_ rect: CGRect, color: UIColor) -> UIView { - - let view = UIView(frame: rect) - view.layer.borderColor = color.cgColor - view.layer.borderWidth = 1.0 - - return view - } - public func setAsMolecule() { styleB2(true) } diff --git a/MVMCoreUI/Molecules/ActionDetailWithImage.swift b/MVMCoreUI/Molecules/ActionDetailWithImage.swift index 8cdddb5f..ec91c479 100644 --- a/MVMCoreUI/Molecules/ActionDetailWithImage.swift +++ b/MVMCoreUI/Molecules/ActionDetailWithImage.swift @@ -166,10 +166,5 @@ import UIKit } else { button.isHidden = true } - - if let text = header.messageLabel.text, text.contains("frog") { - let rect = Label.boundingRect(forCharacterRange: NSRange(location: 65, length: 4), in: header.messageLabel) - print(rect) - } } } diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index 641b3721..ce9fe93c 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -53,6 +53,16 @@ import UIKit } } + open override func layoutSubviews() { + super.layoutSubviews() + + if let center = heroAccessoryCenter { + accessoryView?.center.y = center.y + } + } + + var heroAccessoryCenter: CGPoint? + func styleStandard() { topMarginPadding = 24 bottomMarginPadding = 24 @@ -128,15 +138,51 @@ import UIKit } } + /// NOTE: Should only be called when displayed or about to be displayed. + public func alignAccessoryToHero() { + + layoutIfNeeded() + guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return } + let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel) + let rectView = UIView(frame: rect) + heroLabel.addSubview(rectView) + accessoryView?.center.y = contentView.convert(rectView.center, from: heroLabel).y + heroAccessoryCenter = accessoryView?.center + rectView.removeFromSuperview() + } + + /** + Used to traverse the view hierarchy for a 🦸‍♂️heroic Label. + */ + private func findHeroLabel(views: [UIView]) -> Label? { + + if views.isEmpty { + return nil + } + + var queue = [UIView]() + + for view in views { + // Only one Label will have a hero in a table cell. + if let label = view as? Label, label.hero != nil { + return label + } + queue.append(contentsOf: view.subviews) + } + + return findHeroLabel(views: queue) + } + // MARK: - MVMCoreUIMoleculeViewProtocol public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - self.json = json; + self.json = json style(with: json?.optionalStringForKey("style")) if let useHorizontalMargins = json?.optionalBoolForKey("useHorizontalMargins") { updateViewHorizontalDefaults = useHorizontalMargins } + if (json?.optionalBoolForKey("useVerticalMargins") ?? true) == false { topMarginPadding = 0 bottomMarginPadding = 0 @@ -161,9 +207,8 @@ import UIKit bottomSeparatorView?.setWithJSON(separator, delegateObject: delegateObject, additionalData: additionalData) } - guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else { - return - } + guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else { return } + if molecule == nil { if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) { contentView.addSubview(moleculeView) @@ -215,9 +260,7 @@ import UIKit // MARK: - Arrow /// Adds the standard mvm style caret to the accessory view public func addCaretViewAccessory() { - guard accessoryView == nil else { - return - } + guard accessoryView == nil else { return } let width: CGFloat = 6 let height: CGFloat = 10 caretView = CaretView(lineThickness: CaretView.thin) diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h index 4c69b1f7..273329aa 100644 --- a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h @@ -24,6 +24,8 @@ /// Resets to default state before set with json is called again. - (void)reset; +/// Currently designed for UITableViewCell. Aligns the accessory view with the center of a character in a line of text. +- (void)alignAccessoryToHero; /// For the molecule list to load more efficiently. + (CGFloat)estimatedHeightForRow:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 0db27a35..84a7e64b 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -51,9 +51,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { // MARK: - table open override func registerWithTable() { super.registerWithTable() - guard let moleculesInfo = moleculesInfo else { - return - } + guard let moleculesInfo = moleculesInfo else { return } + for moleculeInfo in moleculesInfo { tableView?.register(moleculeInfo.class, forCellReuseIdentifier: moleculeInfo.identifier) } @@ -90,34 +89,9 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { open override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { - cell.layoutIfNeeded() - let heroLabel = findHeroLabel(views: cell.contentView.subviews) - let rect = Label.boundingRect(forCharacterRange: NSRange(location: heroLabel!.hero!, length: 1), in: heroLabel!) - let rectView = heroLabel?.noticeBounds(rect, color: .clear) - heroLabel?.addSubview(rectView!) - let convert = cell.contentView.convert(rectView!.center, from: heroLabel) - - cell.accessoryView?.center.y = convert.y - rectView?.removeFromSuperview() - } - - // TODO: Write recursively. - func findHeroLabel(views: [UIView]) -> Label? { - - var queue: [UIView] = views - - repeat { - for view in queue { - if let label = view as? Label, label.hero != nil { - return label - } else if !view.subviews.isEmpty { - queue.append(contentsOf: view.subviews) - } - queue.removeFirst() - } - } while (!queue.isEmpty) - - return nil + if cell.accessoryView != nil, let protocolCell = cell as? (MoleculeTableViewCell & MVMCoreUIMoleculeViewProtocol) { + protocolCell.alignAccessoryToHero() + } } open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { @@ -143,31 +117,16 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { if let tableView = tableView { let point = molecule.convert(molecule.bounds.origin, to: tableView) if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false { - //------------- tableView.beginUpdates() -// let cell = tableView.cellForRow(at: indexPath) -// cell.layoutIfNeeded() -// let heroLabel = findHeroLabel(views: cell.contentView.subviews) -// let rect = Label.boundingRect(forCharacterRange: NSRange(location: heroLabel!.hero!, length: 1), in: heroLabel!) -// let rectView = heroLabel?.noticeBounds(rect, color: .blue) -// heroLabel?.addSubview(rectView!) -// // let rect = Label.boundingRect(forCharacterRange: NSRange(location: 46, length: 6), in: self) -// let convert = cell.contentView.convert(rectView!.center, from: heroLabel) -// -// cell.accessoryView?.center.y = convert.y - /// ------------ tableView.endUpdates() } } } - open override func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { // This dispatch is needed to fix a race condition that can occur if this function is called during the table setup. DispatchQueue.main.async { - guard let cell = sender as? MoleculeTableViewCell, let indexPath = self.tableView?.indexPath(for: cell) else { - return - } + guard let cell = sender as? MoleculeTableViewCell, let indexPath = self.tableView?.indexPath(for: cell) else { return } var indexPaths: [IndexPath] = [] for molecule in molecules { if let info = self.getMoleculeInfo(with: molecule) { From 4ea916bbcd47f01ba6892648bc5f048caf51517c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 18 Sep 2019 14:14:37 -0400 Subject: [PATCH 05/22] commenting. --- MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index ce9fe93c..1f348bb5 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -151,11 +151,9 @@ import UIKit rectView.removeFromSuperview() } - /** - Used to traverse the view hierarchy for a 🦸‍♂️heroic Label. - */ + /// Used to traverse the view hierarchy for a 🦸‍♂️heroic Label. private func findHeroLabel(views: [UIView]) -> Label? { - + if views.isEmpty { return nil } @@ -169,7 +167,7 @@ import UIKit } queue.append(contentsOf: view.subviews) } - + return findHeroLabel(views: queue) } From 1c416b5653b4feb0b308b04135aeb5c1c3cf8ce1 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 18 Sep 2019 14:15:56 -0400 Subject: [PATCH 06/22] revised. --- MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index 1f348bb5..840e681b 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -151,7 +151,7 @@ import UIKit rectView.removeFromSuperview() } - /// Used to traverse the view hierarchy for a 🦸‍♂️heroic Label. + /// Traverses the view hierarchy for a 🦸‍♂️heroic Label. private func findHeroLabel(views: [UIView]) -> Label? { if views.isEmpty { From bbdb2181f22e96db7ca96f9c8b1536158cc564a4 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 8 Oct 2019 11:30:25 -0400 Subject: [PATCH 07/22] aligning with invision. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 6f308651..f82d6bed 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -244,10 +244,17 @@ import MVMCore /// Returns a UIBezierPath detailing the path of a checkmark func checkMarkPath() -> CGPath { - let sideLength = max(bounds.size.height, bounds.size.width) - let startPoint = CGPoint(x: 0.33871 * sideLength, y: 0.53225 * sideLength) - let pivotOffSet = CGPoint(x: 0.46774 * sideLength, y: 0.64516 * sideLength) - let endOffset = CGPoint(x: 0.66935 * sideLength , y: 0.37097 * sideLength) + let length = max(bounds.size.height, bounds.size.width) + let xInsetLeft = length * 0.25 + let xInsetRight = length * 0.25 + let yInsetTop = length * 0.3 + let yInsetBottom = length * 0.35 + let innerWidth = length - (xInsetLeft + xInsetRight) + let innerHeight = length - (yInsetTop + yInsetBottom) + + let startPoint = CGPoint(x: xInsetLeft, y: yInsetTop + (innerHeight / 2)) + let pivotOffSet = CGPoint(x: xInsetLeft + (innerWidth * 0.33), y: yInsetTop + innerHeight) + let endOffset = CGPoint(x: xInsetLeft + innerWidth, y: yInsetTop) let bezierPath = UIBezierPath() bezierPath.move(to: startPoint) From ec190a28bdf137a1134762400fda080ebdd90328 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 8 Oct 2019 11:47:08 -0400 Subject: [PATCH 08/22] Further updates made. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 32 ++++++---------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index f82d6bed..187d9d7c 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -8,22 +8,6 @@ import MVMCore -/* - !!! -- DO NOT REMOVE -- !!! - (Unless Design changes the appearance of the checkmark). - - // Offsets based on the 124x124 example checkmark - let startXOffset: Float = 42.0 / 124.0 ~~ 0.33871 - let startYOffset: Float = 66.0 / 124.0 ~~ 0.53225 - let pivotXOffset: Float = 58.0 / 124.0 ~~ 0.46774 - let pivotYOffset: Float = 80.0 / 124.0 ~~ 0.64516 - let endXOffset: Float = 83.0 / 124.0 ~~ 0.66935 - let endYOffset: Float = 46.0 / 124.0 ~~ 0.37097 - let pivotPercentage: Float = 0.34 - let endPercentage = 1.0 - pivotPercentage - let animationInterval: Float = 0.01 - */ - /** This class expects its height and width to be equal. */ @@ -182,7 +166,7 @@ import MVMCore override open func layoutSubviews() { super.layoutSubviews() - drawCheck() + drawShapeLayer() layer.cornerRadius = isRound ? cornerRadiusValue : 0 layer.borderWidth = borderWidth layer.borderColor = borderColor.cgColor @@ -220,8 +204,8 @@ import MVMCore // MARK: - Methods //-------------------------------------------------- - /// Creates the check mark used for the checkbox. - private func drawCheck() { + /// Creates the check mark layer. + private func drawShapeLayer() { if shapeLayer == nil { @@ -241,16 +225,14 @@ import MVMCore } } - /// Returns a UIBezierPath detailing the path of a checkmark + /// - returns: The CGPath of a UIBezierPath detailing the path of a checkmark func checkMarkPath() -> CGPath { let length = max(bounds.size.height, bounds.size.width) let xInsetLeft = length * 0.25 - let xInsetRight = length * 0.25 let yInsetTop = length * 0.3 - let yInsetBottom = length * 0.35 - let innerWidth = length - (xInsetLeft + xInsetRight) - let innerHeight = length - (yInsetTop + yInsetBottom) + let innerWidth = length - (xInsetLeft + length * 0.25) // + Right X Inset + let innerHeight = length - (yInsetTop + length * 0.35) // + Bottom Y Inset let startPoint = CGPoint(x: xInsetLeft, y: yInsetTop + (innerHeight / 2)) let pivotOffSet = CGPoint(x: xInsetLeft + (innerWidth * 0.33), y: yInsetTop + innerHeight) @@ -274,7 +256,7 @@ import MVMCore self.updateSelectionOnly = true self.isSelected = selected self.updateSelectionOnly = false - self.drawCheck() + self.drawShapeLayer() self.shapeLayer?.removeAllAnimations() self.updateCheckboxUI(isSelected: selected, isAnimated: animated) } From 03f12b8a7a014d4a2533dcc440a9e4b9eff23c04 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 8 Oct 2019 13:15:10 -0400 Subject: [PATCH 09/22] added isEnabled func. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 36 ++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 187d9d7c..1f6a429a 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -62,7 +62,7 @@ import MVMCore private var shapeLayer: CAShapeLayer? /// Width of the check mark. - public var checkWidth: CGFloat = 2 { + public var checkWidth: CGFloat = 2.3 { didSet { if let shapeLayer = shapeLayer { CATransaction.withDisabledAnimations { @@ -75,11 +75,7 @@ import MVMCore /// Color of the check mark. public var checkColor: UIColor = .black { didSet { - if let shapeLayer = shapeLayer { - CATransaction.withDisabledAnimations { - shapeLayer.strokeColor = checkColor.cgColor - } - } + setshapeLayerStrokeColor(checkColor) } } @@ -285,7 +281,7 @@ import MVMCore self.shapeLayer?.strokeEnd = isSelected ? 1 : 0 } - self.backgroundColor = isSelected ? self.checkedBackgroundColor : self.unCheckedBackgroundColor + backgroundColor = isSelected ? checkedBackgroundColor : unCheckedBackgroundColor } } @@ -297,6 +293,32 @@ import MVMCore } } + func isEnabled(_ enabled: Bool) { + + isUserInteractionEnabled = enabled + + if enabled { + layer.borderColor = borderColor.cgColor + backgroundColor = isSelected ? checkedBackgroundColor : unCheckedBackgroundColor + alpha = 1.0 + setshapeLayerStrokeColor(checkColor) + } else { + layer.borderColor = UIColor.mfSilver().cgColor + backgroundColor = .white + alpha = DisableOppacity + setshapeLayerStrokeColor(UIColor.mfSilver()) + } + } + + private func setshapeLayerStrokeColor(_ color: UIColor) { + + if let shapeLayer = shapeLayer { + CATransaction.withDisabledAnimations { + shapeLayer.strokeColor = color.cgColor + } + } + } + //-------------------------------------------------- // MARK: - UITouch //-------------------------------------------------- From 1618583acce693418af22bb1cd758875f9bb2b88 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 8 Oct 2019 15:19:12 -0400 Subject: [PATCH 10/22] corrected comment. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 1f6a429a..0d2c3e75 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -259,7 +259,7 @@ import MVMCore } /// updates the visuals of the check mark and background. - /// - parameter isSelection: the check state of the checkbox. + /// - parameter isSelected: the check state of the checkbox. /// - parameter isAnimated: determines of the changes should animate or immediately refelect. public func updateCheckboxUI(isSelected: Bool, isAnimated: Bool) { From 9922ef467422d6b007f9b6b6213eeb9a1855ed6c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 8 Oct 2019 16:45:34 -0400 Subject: [PATCH 11/22] added enabled molecule logic. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 0d2c3e75..2ece7d4a 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -354,6 +354,7 @@ import MVMCore open func reset() { + isEnabled(true) shapeLayer?.removeAllAnimations() shapeLayer?.removeFromSuperlayer() shapeLayer = nil @@ -424,9 +425,15 @@ import MVMCore self.isRound = isRound } + if let enabled = dictionary["isEnabled"] as? Bool { + isEnabled(enabled) + } + if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } + +// layoutIfNeeded() } } From 960d9e0e7ca847191819cde67a49080c59530000 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 9 Oct 2019 10:18:18 -0400 Subject: [PATCH 12/22] removed comment. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 2ece7d4a..c43accb2 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -432,8 +432,6 @@ import MVMCore if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } - -// layoutIfNeeded() } } From 5ef9754e2cb8a362f098dd74941f6dc17caebed7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 9 Oct 2019 12:45:18 -0400 Subject: [PATCH 13/22] defaulting to clear. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index c43accb2..c3879f96 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -33,7 +33,7 @@ import MVMCore public var updateSelectionOnly: Bool = false /// The color of the background when checked. - public var checkedBackgroundColor: UIColor = .white { + public var checkedBackgroundColor: UIColor = .clear { didSet { if isSelected { backgroundColor = checkedBackgroundColor @@ -42,7 +42,7 @@ import MVMCore } /// The color of the background when unChecked. - public var unCheckedBackgroundColor: UIColor = .white { + public var unCheckedBackgroundColor: UIColor = .clear { didSet { if !isSelected { backgroundColor = unCheckedBackgroundColor @@ -62,7 +62,7 @@ import MVMCore private var shapeLayer: CAShapeLayer? /// Width of the check mark. - public var checkWidth: CGFloat = 2.3 { + public var checkWidth: CGFloat = 2 { didSet { if let shapeLayer = shapeLayer { CATransaction.withDisabledAnimations { @@ -172,7 +172,7 @@ import MVMCore isUserInteractionEnabled = true translatesAutoresizingMaskIntoConstraints = false - backgroundColor = .white + backgroundColor = .clear } //-------------------------------------------------- @@ -304,7 +304,7 @@ import MVMCore setshapeLayerStrokeColor(checkColor) } else { layer.borderColor = UIColor.mfSilver().cgColor - backgroundColor = .white + backgroundColor = .clear alpha = DisableOppacity setshapeLayerStrokeColor(UIColor.mfSilver()) } @@ -358,7 +358,7 @@ import MVMCore shapeLayer?.removeAllAnimations() shapeLayer?.removeFromSuperlayer() shapeLayer = nil - backgroundColor = nil + backgroundColor = .clear borderColor = .black borderWidth = 1.0 checkColor = .black From bb51fba0e59f95c99967597d6b237773fb8ecde5 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 17 Oct 2019 10:31:34 -0400 Subject: [PATCH 14/22] remove legacy os code --- MVMCoreUI/Atoms/TextFields/MFTextField.m | 8 ++-- MVMCoreUI/Atoms/Views/MFTextView.m | 9 ++--- MVMCoreUI/Atoms/Views/MFView.m | 4 +- .../MFProgrammaticTableViewController.m | 8 +--- .../MFScrollingViewController.m | 5 +-- .../ThreeLayerTableViewController.swift | 10 ++--- .../ThreeLayerViewController.swift | 14 +++---- ...MVMCoreUITabBarPageControlViewController.m | 10 ----- ...abelsAndBottomButtonsTableViewController.m | 20 ++++------ .../TopLabelsAndBottomButtonsViewController.m | 27 +++++--------- .../Items/MoleculeCollectionViewCell.swift | 8 ++-- .../Items/MoleculeTableViewCell.swift | 37 ++++++------------- .../Utility/MVMCoreUICommonViewsUtility.m | 25 ++++--------- MVMCoreUI/Utility/MVMCoreUIUtility.m | 21 +++-------- 14 files changed, 62 insertions(+), 144 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.m b/MVMCoreUI/Atoms/TextFields/MFTextField.m index ba68c0ed..e4709844 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.m @@ -83,11 +83,9 @@ self.enabled = YES; // Disable SmartQuotes - if (@available(iOS 11.0, *)) { - self.textField.smartQuotesType = UITextSmartQuotesTypeNo; - self.textField.smartDashesType = UITextSmartDashesTypeNo; - self.textField.smartInsertDeleteType = UITextSmartInsertDeleteTypeNo; - } + self.textField.smartQuotesType = UITextSmartQuotesTypeNo; + self.textField.smartDashesType = UITextSmartDashesTypeNo; + self.textField.smartInsertDeleteType = UITextSmartInsertDeleteTypeNo; } } diff --git a/MVMCoreUI/Atoms/Views/MFTextView.m b/MVMCoreUI/Atoms/Views/MFTextView.m index c120d964..424c8117 100644 --- a/MVMCoreUI/Atoms/Views/MFTextView.m +++ b/MVMCoreUI/Atoms/Views/MFTextView.m @@ -173,11 +173,10 @@ view.placeHolderLabel.textColor = [UIColor mfLightGrayColor]; // Disable SmartQuotes - if (@available(iOS 11.0, *)) { - view.textView.smartQuotesType = UITextSmartQuotesTypeNo; - view.textView.smartDashesType = UITextSmartDashesTypeNo; - view.textView.smartInsertDeleteType = UITextSmartInsertDeleteTypeNo; - } + view.textView.smartQuotesType = UITextSmartQuotesTypeNo; + view.textView.smartDashesType = UITextSmartDashesTypeNo; + view.textView.smartInsertDeleteType = UITextSmartInsertDeleteTypeNo; + [view didSetFont:view.textView.font]; view.hideBorder = YES; return view; diff --git a/MVMCoreUI/Atoms/Views/MFView.m b/MVMCoreUI/Atoms/Views/MFView.m index 4e0d71ab..6d939fc8 100644 --- a/MVMCoreUI/Atoms/Views/MFView.m +++ b/MVMCoreUI/Atoms/Views/MFView.m @@ -48,9 +48,7 @@ - (void)setAsMolecule { self.translatesAutoresizingMaskIntoConstraints = NO; - if (@available(iOS 11.0, *)) { - self.insetsLayoutMarginsFromSafeArea = NO; - } + self.insetsLayoutMarginsFromSafeArea = NO; } - (void)reset { diff --git a/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.m b/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.m index 98d2b5ef..1d0d2a3b 100644 --- a/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.m +++ b/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.m @@ -61,12 +61,8 @@ tableView.separatorStyle = UITableViewCellSeparatorStyleNone; tableView.delegate = self; tableView.dataSource = self; - if (@available(iOS 11.0, *)) { - tableView.insetsContentViewsToSafeArea = NO; - } - if ([tableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)]) { - tableView.cellLayoutMarginsFollowReadableWidth = NO; - } + tableView.insetsContentViewsToSafeArea = NO; + tableView.cellLayoutMarginsFollowReadableWidth = NO; return tableView; } diff --git a/MVMCoreUI/BaseControllers/MFScrollingViewController.m b/MVMCoreUI/BaseControllers/MFScrollingViewController.m index 5486b54a..56019cb7 100644 --- a/MVMCoreUI/BaseControllers/MFScrollingViewController.m +++ b/MVMCoreUI/BaseControllers/MFScrollingViewController.m @@ -91,10 +91,7 @@ static NSTimeInterval const HandScrollAnimationTiming = 7.f; - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - BOOL automaticInset = NO; - if (@available(iOS 11.0, *)) { - automaticInset = self.navigationController && self.scrollView.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic; - } + BOOL automaticInset = self.navigationController && self.scrollView.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic; // Takes into account the navigation bar. if (!automaticInset && (self.edgesForExtendedLayout & UIRectEdgeTop)) { diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 0293e860..d1bfa0db 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -190,13 +190,9 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true - if #available(iOS 11.0, *) { - view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true - safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view) - safeAreaView?.backgroundColor = bottomView?.backgroundColor - } else { - view.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true - } + view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true + safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view) + safeAreaView?.backgroundColor = bottomView?.backgroundColor } else { bottomConstraint?.isActive = true var y: CGFloat? diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index dae861dd..ea6923c5 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -45,7 +45,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { return } - if #available(iOS 11.0, *), scrollView.contentInsetAdjustmentBehavior == UIScrollView.ContentInsetAdjustmentBehavior.automatic { + if scrollView.contentInsetAdjustmentBehavior == UIScrollView.ContentInsetAdjustmentBehavior.automatic { heightConstraint?.constant = -scrollView.adjustedContentInset.top - scrollView.adjustedContentInset.bottom } else { heightConstraint?.constant = -scrollView.contentInset.top - scrollView.contentInset.bottom @@ -233,14 +233,10 @@ extension ThreeLayerViewController { view.topAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true - if #available(iOS 11.0, *) { - parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true - if let safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: parentView) { - safeAreaView.backgroundColor = bottomView?.backgroundColor - self.safeAreaView = safeAreaView - } - } else { - NSLayoutConstraint.pinViewBottom(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + if let safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: parentView) { + safeAreaView.backgroundColor = bottomView?.backgroundColor + self.safeAreaView = safeAreaView } } } diff --git a/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m b/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m index 1d8481d6..cb48eb54 100644 --- a/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m +++ b/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m @@ -283,16 +283,6 @@ // So we will update titles. [self newDataBuildScreen]; - - // Fix for right bar button item with custom view which disappears when user navigates to top tabbar page controller - if (@available(iOS 11.0, *)) { - } else { - NSMutableArray *buttonItems = [[NSMutableArray alloc] init]; - UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:nil]; - [buttonItems addObject:space]; - [buttonItems addObjectsFromArray:self.navigationItem.rightBarButtonItems]; - self.navigationItem.rightBarButtonItems = buttonItems; - } } - (void)viewWillDisappear:(BOOL)animated { diff --git a/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m b/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m index ca75b778..1c90d9e0 100644 --- a/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m +++ b/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m @@ -325,19 +325,13 @@ NSLayoutConstraint *bottomViewTop = [NSLayoutConstraint constraintWithItem:footerView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:tableView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; bottomViewTop.active = YES; - NSLayoutConstraint *bottomViewBot = nil; - if (@available(iOS 11.0, *)) { - bottomViewBot = [self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:footerView.bottomAnchor]; - - UIView *safeAreaView = [MVMCoreUICommonViewsUtility getAndSetupSafeAreaViewOnView:self.view]; - safeAreaView.backgroundColor = footerView.backgroundColor; - self.safeAreaView = safeAreaView; - } else { - // Fallback on earlier versions - bottomViewBot = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:footerView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; - } - bottomViewBot.priority = 900; - bottomViewBot.active = YES; + NSLayoutConstraint *bottomViewBot = [self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:footerView.bottomAnchor]; + bottomViewBot.priority = 900; + bottomViewBot.active = YES; + + UIView *safeAreaView = [MVMCoreUICommonViewsUtility getAndSetupSafeAreaViewOnView:self.view]; + safeAreaView.backgroundColor = footerView.backgroundColor; + self.safeAreaView = safeAreaView; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[footerView]-0@900-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(footerView)]]; } else { diff --git a/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsViewController.m b/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsViewController.m index 77472e11..0c9d1d5d 100644 --- a/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsViewController.m +++ b/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsViewController.m @@ -272,13 +272,8 @@ - (void)updateViewConstraints { [super updateViewConstraints]; - // Updates for ios 11 - if (@available(iOS 11.0, *)) { - if (self.scrollView.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic) { - self.heightConstraint.constant = -self.scrollView.adjustedContentInset.top - self.scrollView.adjustedContentInset.bottom; - } else { - self.heightConstraint.constant = -self.scrollView.contentInset.top - self.scrollView.contentInset.bottom; - } + if (self.scrollView.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic) { + self.heightConstraint.constant = -self.scrollView.adjustedContentInset.top - self.scrollView.adjustedContentInset.bottom; } else { self.heightConstraint.constant = -self.scrollView.contentInset.top - self.scrollView.contentInset.bottom; } @@ -322,17 +317,13 @@ [self.view addSubview:bottomView]; UIScrollView *scrollview = self.scrollView; - if (@available(iOS 11.0, *)) { - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[scrollview]-0-[bottomView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(scrollview,bottomView)]]; - [self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:bottomView.bottomAnchor].active = YES; - - UIView *safeAreaView = [MVMCoreUICommonViewsUtility getAndSetupSafeAreaViewOnView:self.view]; - safeAreaView.backgroundColor = bottomView.backgroundColor; - self.safeAreaView = safeAreaView; - } else { - // Fallback on earlier versions - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[scrollview]-0-[bottomView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(scrollview,bottomView)]]; - } + [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[scrollview]-0-[bottomView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(scrollview,bottomView)]]; + [self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:bottomView.bottomAnchor].active = YES; + + UIView *safeAreaView = [MVMCoreUICommonViewsUtility getAndSetupSafeAreaViewOnView:self.view]; + safeAreaView.backgroundColor = bottomView.backgroundColor; + self.safeAreaView = safeAreaView; + [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[bottomView]-0@900-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(bottomView)]]; } diff --git a/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift index 42a5e5cd..685d2e7a 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift @@ -37,11 +37,9 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi } isAccessibilityElement = false contentView.isAccessibilityElement = false - if #available(iOS 11.0, *) { - insetsLayoutMarginsFromSafeArea = false - contentView.insetsLayoutMarginsFromSafeArea = false - contentView.preservesSuperviewLayoutMargins = false - } + insetsLayoutMarginsFromSafeArea = false + contentView.insetsLayoutMarginsFromSafeArea = false + contentView.preservesSuperviewLayoutMargins = false // Covers the card when peaking. peakingCover.backgroundColor = .white diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index 641b3721..3c20402e 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -87,29 +87,16 @@ import UIKit // MARK: - MFViewProtocol public func updateView(_ size: CGFloat) { MFStyler.setMarginsFor(self, size: size, defaultHorizontal: updateViewHorizontalDefaults, top: topMarginPadding, bottom: bottomMarginPadding) - if #available(iOS 11.0, *) { - if accessoryView != nil { - // Smaller left margin if accessory view. - var margin = directionalLayoutMargins - margin.trailing = 16 - contentView.directionalLayoutMargins = margin - } else { - contentView.directionalLayoutMargins = directionalLayoutMargins - } - topSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading) - bottomSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading) + if accessoryView != nil { + // Smaller left margin if accessory view. + var margin = directionalLayoutMargins + margin.trailing = 16 + contentView.directionalLayoutMargins = margin } else { - if accessoryView != nil { - // Smaller left margin if accessory view. - var margin = layoutMargins - margin.right = 16 - contentView.layoutMargins = margin - } else { - contentView.layoutMargins = layoutMargins - } - topSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left) - bottomSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left) + contentView.directionalLayoutMargins = directionalLayoutMargins } + topSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading) + bottomSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading) molecule?.updateView(size) if let _ = accessoryView, let caretView = caretView, let widthObject = caretViewWidthSizeObject, let heightObject = caretViewHeightSizeObject { @@ -121,11 +108,9 @@ import UIKit public func setupView() { selectionStyle = .none - if #available(iOS 11.0, *) { - insetsLayoutMarginsFromSafeArea = false - contentView.insetsLayoutMarginsFromSafeArea = false - contentView.preservesSuperviewLayoutMargins = false - } + insetsLayoutMarginsFromSafeArea = false + contentView.insetsLayoutMarginsFromSafeArea = false + contentView.preservesSuperviewLayoutMargins = false } // MARK: - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility.m b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility.m index 94c6ca85..fd5c9b21 100644 --- a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility.m +++ b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility.m @@ -198,13 +198,8 @@ static const CGFloat VertialShadowOffset = 6; [view.rightAnchor constraintEqualToAnchor:button.rightAnchor constant:PaddingTwo].active = YES; [view.centerYAnchor constraintEqualToAnchor:button.centerYAnchor].active = YES; } else { - if (@available(iOS 11.0, *)) { - [button.topAnchor constraintEqualToAnchor:view.safeAreaLayoutGuide.topAnchor constant:PaddingOne].active = YES; - [view.safeAreaLayoutGuide.trailingAnchor constraintEqualToAnchor:button.trailingAnchor constant:PaddingTwo].active = YES; - } else { - [NSLayoutConstraint constraintPinSubview:button pinTop:YES topConstant:PaddingOne pinBottom:NO bottomConstant:0 pinLeft:NO leftConstant:0 pinRight:YES rightConstant:PaddingTwo]; - } - + [button.topAnchor constraintEqualToAnchor:view.safeAreaLayoutGuide.topAnchor constant:PaddingOne].active = YES; + [view.safeAreaLayoutGuide.trailingAnchor constraintEqualToAnchor:button.trailingAnchor constant:PaddingTwo].active = YES; } } return button; @@ -249,16 +244,12 @@ static const CGFloat VertialShadowOffset = 6; } + (nullable UIView *)getAndSetupSafeAreaViewOnView:(nonnull UIView *)view { - if (@available(iOS 11.0, *)) { - UIView *safeAreaView = [MVMCoreUICommonViewsUtility commonView]; - [view addSubview:safeAreaView]; - [safeAreaView.topAnchor constraintEqualToAnchor:view.safeAreaLayoutGuide.bottomAnchor].active = YES; - [view.bottomAnchor constraintEqualToAnchor:safeAreaView.bottomAnchor].active = YES; - [NSLayoutConstraint constraintPinSubview:safeAreaView pinTop:NO topConstant:0 pinBottom:NO bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; - return safeAreaView; - } else { - return nil; - } + UIView *safeAreaView = [MVMCoreUICommonViewsUtility commonView]; + [view addSubview:safeAreaView]; + [safeAreaView.topAnchor constraintEqualToAnchor:view.safeAreaLayoutGuide.bottomAnchor].active = YES; + [view.bottomAnchor constraintEqualToAnchor:safeAreaView.bottomAnchor].active = YES; + [NSLayoutConstraint constraintPinSubview:safeAreaView pinTop:NO topConstant:0 pinBottom:NO bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; + return safeAreaView; } #pragma mark - shadows diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility.m b/MVMCoreUI/Utility/MVMCoreUIUtility.m index 4f150783..257014f5 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility.m +++ b/MVMCoreUI/Utility/MVMCoreUIUtility.m @@ -58,21 +58,13 @@ } + (UIEdgeInsets)getMarginsForView:(nullable UIView *)view { - if (@available(iOS 11.0, *)) { - return UIEdgeInsetsMake(view.directionalLayoutMargins.top, view.directionalLayoutMargins.leading, view.directionalLayoutMargins.bottom, view.directionalLayoutMargins.trailing); - } else { - return view.layoutMargins; - } + return UIEdgeInsetsMake(view.directionalLayoutMargins.top, view.directionalLayoutMargins.leading, view.directionalLayoutMargins.bottom, view.directionalLayoutMargins.trailing) } #pragma mark - Setters + (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom { - if (@available(iOS 11.0, *)) { - view.directionalLayoutMargins = NSDirectionalEdgeInsetsMake(top, leading, bottom, trailing); - } else { - view.layoutMargins = UIEdgeInsetsMake(top, leading, bottom, trailing); - } + view.directionalLayoutMargins = NSDirectionalEdgeInsetsMake(top, leading, bottom, trailing); } #pragma mark - Formatting @@ -152,12 +144,9 @@ CGFloat topInset = scrollview.contentInset.top; CGFloat bottomInset = scrollview.contentInset.bottom; - // Updates for ios 11 - if (@available(iOS 11.0, *)) { - if (scrollview.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic) { - topInset = scrollview.adjustedContentInset.top; - bottomInset = scrollview.adjustedContentInset.bottom; - } + if (scrollview.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic) { + topInset = scrollview.adjustedContentInset.top; + bottomInset = scrollview.adjustedContentInset.bottom; } CGFloat remainingSpace = frameHeight - contentSizeHeight - topInset - bottomInset; From 38beb2c7faa28b3c0c7e41688ff6dec9027fadf0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 17 Oct 2019 11:21:42 -0400 Subject: [PATCH 15/22] typo fix --- MVMCoreUI/Utility/MVMCoreUIUtility.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility.m b/MVMCoreUI/Utility/MVMCoreUIUtility.m index 257014f5..48a7a6a1 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility.m +++ b/MVMCoreUI/Utility/MVMCoreUIUtility.m @@ -58,7 +58,7 @@ } + (UIEdgeInsets)getMarginsForView:(nullable UIView *)view { - return UIEdgeInsetsMake(view.directionalLayoutMargins.top, view.directionalLayoutMargins.leading, view.directionalLayoutMargins.bottom, view.directionalLayoutMargins.trailing) + return UIEdgeInsetsMake(view.directionalLayoutMargins.top, view.directionalLayoutMargins.leading, view.directionalLayoutMargins.bottom, view.directionalLayoutMargins.trailing); } #pragma mark - Setters From f267b98438dbd5711e8d0124a3959f499476aea1 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 17 Oct 2019 11:57:30 -0400 Subject: [PATCH 16/22] constraints added. changes made. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 35 ++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index c3879f96..a568622b 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -75,7 +75,7 @@ import MVMCore /// Color of the check mark. public var checkColor: UIColor = .black { didSet { - setshapeLayerStrokeColor(checkColor) + setShapeLayerStrokeColor(checkColor) } } @@ -115,6 +115,21 @@ import MVMCore } } + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + + private var heightConstraint: NSLayoutConstraint? + private var widthConstraint: NSLayoutConstraint? + + /// Updates the height and width anchors of the Checkbox with the assigned value. + public var heigthWidthConstant: Int = Checkbox.defaultHeightWidth { + didSet { + heightConstraint?.constant = heigthWidthConstant + widthConstraint?.constant = heigthWidthConstant + } + } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -170,9 +185,15 @@ import MVMCore open func setupView() { + guard constraints.isEmpty else { return } + isUserInteractionEnabled = true translatesAutoresizingMaskIntoConstraints = false backgroundColor = .clear + + widthConstraint = widthAnchor.constraint(equalToConstant: Checkbox.defaultHeightWidth) + heightConstraint = heightAnchor.constraint(equalToConstant: Checkbox.defaultHeightWidth) + heightWidthIsActive(true) } //-------------------------------------------------- @@ -301,16 +322,16 @@ import MVMCore layer.borderColor = borderColor.cgColor backgroundColor = isSelected ? checkedBackgroundColor : unCheckedBackgroundColor alpha = 1.0 - setshapeLayerStrokeColor(checkColor) + setShapeLayerStrokeColor(checkColor) } else { layer.borderColor = UIColor.mfSilver().cgColor backgroundColor = .clear alpha = DisableOppacity - setshapeLayerStrokeColor(UIColor.mfSilver()) + setShapeLayerStrokeColor(UIColor.mfSilver()) } } - private func setshapeLayerStrokeColor(_ color: UIColor) { + private func setShapeLayerStrokeColor(_ color: UIColor) { if let shapeLayer = shapeLayer { CATransaction.withDisabledAnimations { @@ -319,6 +340,12 @@ import MVMCore } } + public func heightWidthIsActive(_ isActive: Bool) { + + heightConstraint?.isActive = isActive + widthConstraint?.isActive = isActive + } + //-------------------------------------------------- // MARK: - UITouch //-------------------------------------------------- From 2fdc4795f40859be9cd9ade4d4f99a10f25998f2 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 17 Oct 2019 12:00:44 -0400 Subject: [PATCH 17/22] correcting type. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index a568622b..d139f130 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -123,7 +123,7 @@ import MVMCore private var widthConstraint: NSLayoutConstraint? /// Updates the height and width anchors of the Checkbox with the assigned value. - public var heigthWidthConstant: Int = Checkbox.defaultHeightWidth { + public var heigthWidthConstant: CGFloat = Checkbox.defaultHeightWidth { didSet { heightConstraint?.constant = heigthWidthConstant widthConstraint?.constant = heigthWidthConstant @@ -140,7 +140,6 @@ import MVMCore accessibilityTraits = .button accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint") updateAccessibilityLabel() - setupView() } From b5dcf68c5d4344e346d71479dbc2d7b4228c99e5 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 17 Oct 2019 12:17:14 -0400 Subject: [PATCH 18/22] refactoring taxtcontainer. --- MVMCoreUI/Atoms/Views/Label.swift | 44 ++++++++++++------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index cab341b1..cf1ed6f4 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -505,10 +505,12 @@ public typealias ActionBlock = () -> () let accessibleAction = customAccessibilityAction(range: range) clauses.append(ActionableClause(range: range, actionBlock: actionBlock, accessibilityID: accessibleAction?.hash ?? -1)) } - - public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { - - guard let attributedText = label.attributedText else { return CGRect() } + + /// Provides a text container in memory of how the text would appear on screen. + func abstractTextContainer() -> NSTextContainer? { + + // Must configure the attributed string to translate what would appear on screen to accurately analyze. + guard let attributedText = attributedText else { return nil } let paragraph = NSMutableParagraphStyle() paragraph.alignment = label.textAlignment @@ -524,9 +526,16 @@ public typealias ActionBlock = () -> () textStorage.addLayoutManager(layoutManager) textContainer.lineFragmentPadding = 0.0 - textContainer.lineBreakMode = label.lineBreakMode - textContainer.maximumNumberOfLines = label.numberOfLines - textContainer.size = label.bounds.size + textContainer.lineBreakMode = lineBreakMode + textContainer.maximumNumberOfLines = numberOfLines + textContainer.size = bounds.size + + return textContainer + } + + public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { + + let textContainer = abstractTextContainer() var glyphRange = NSRange() @@ -669,26 +678,7 @@ extension UITapGestureRecognizer { return true } - // Must configure the attributed string to translate what would appear on screen to accurately analyze. - guard let attributedText = label.attributedText else { return false } - - let paragraph = NSMutableParagraphStyle() - paragraph.alignment = label.textAlignment - - let stagedAttributedString = NSMutableAttributedString(attributedString: attributedText) - stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count)) - - let textStorage = NSTextStorage(attributedString: stagedAttributedString) - let layoutManager = NSLayoutManager() - let textContainer = NSTextContainer(size: .zero) - - layoutManager.addTextContainer(textContainer) - textStorage.addLayoutManager(layoutManager) - - textContainer.lineFragmentPadding = 0.0 - textContainer.lineBreakMode = label.lineBreakMode - textContainer.maximumNumberOfLines = label.numberOfLines - textContainer.size = label.bounds.size + guard let textContainer = label.abstractTextContainer() else { return false } let indexOfGlyph = layoutManager.glyphIndex(for: location(in: label), in: textContainer) From 73ac4b932bb37dc413b829296d40a017d63ef599 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 17 Oct 2019 12:39:05 -0400 Subject: [PATCH 19/22] refacgtorerd. --- MVMCoreUI/Atoms/Views/Label.swift | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index cf1ed6f4..fefd686d 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -506,14 +506,17 @@ public typealias ActionBlock = () -> () clauses.append(ActionableClause(range: range, actionBlock: actionBlock, accessibilityID: accessibleAction?.hash ?? -1)) } - /// Provides a text container in memory of how the text would appear on screen. - func abstractTextContainer() -> NSTextContainer? { + /** + Provides a text container and layout manager of how the text would appear on screen. + They are used in tandem to derive low-level TextKit results of the label. + */ + public func abstractTextContainer() -> (NSTextContainer, NSLayoutManager)? { // Must configure the attributed string to translate what would appear on screen to accurately analyze. guard let attributedText = attributedText else { return nil } let paragraph = NSMutableParagraphStyle() - paragraph.alignment = label.textAlignment + paragraph.alignment = textAlignment let stagedAttributedString = NSMutableAttributedString(attributedString: attributedText) stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count)) @@ -530,12 +533,14 @@ public typealias ActionBlock = () -> () textContainer.maximumNumberOfLines = numberOfLines textContainer.size = bounds.size - return textContainer + return (textContainer, layoutManager) } public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { - let textContainer = abstractTextContainer() + guard let abstractContainer = label.abstractTextContainer() else { return CGRect() } + let textContainer = abstractContainer.0 + let layoutManager = abstractContainer.1 var glyphRange = NSRange() @@ -678,7 +683,9 @@ extension UITapGestureRecognizer { return true } - guard let textContainer = label.abstractTextContainer() else { return false } + guard let abstractContainer = label.abstractTextContainer() else { return false } + let textContainer = abstractContainer.0 + let layoutManager = abstractContainer.1 let indexOfGlyph = layoutManager.glyphIndex(for: location(in: label), in: textContainer) From 6d52663b4f66bd8ee7ae6760e2ff4b84c6d371c7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 17 Oct 2019 14:06:01 -0400 Subject: [PATCH 20/22] fixed small error in refactor. --- MVMCoreUI/Atoms/Views/Label.swift | 4 ++-- MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index fefd686d..6fc496bd 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -510,7 +510,7 @@ public typealias ActionBlock = () -> () Provides a text container and layout manager of how the text would appear on screen. They are used in tandem to derive low-level TextKit results of the label. */ - public func abstractTextContainer() -> (NSTextContainer, NSLayoutManager)? { + public func abstractTextContainer() -> (NSTextContainer, NSLayoutManager, NSTextStorage)? { // Must configure the attributed string to translate what would appear on screen to accurately analyze. guard let attributedText = attributedText else { return nil } @@ -533,7 +533,7 @@ public typealias ActionBlock = () -> () textContainer.maximumNumberOfLines = numberOfLines textContainer.size = bounds.size - return (textContainer, layoutManager) + return (textContainer, layoutManager, textStorage) } public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect { diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index 568a551c..2e8b9bfc 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -126,14 +126,12 @@ import UIKit /// NOTE: Should only be called when displayed or about to be displayed. public func alignAccessoryToHero() { + // Layout call required to force draw in memory to get dinmensions of subviews. layoutIfNeeded() guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return } let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel) - let rectView = UIView(frame: rect) - heroLabel.addSubview(rectView) - accessoryView?.center.y = contentView.convert(rectView.center, from: heroLabel).y + accessoryView?.center.y = contentView.convert(UIView(frame: rect).center, from: heroLabel).y heroAccessoryCenter = accessoryView?.center - rectView.removeFromSuperview() } /// Traverses the view hierarchy for a 🦸‍♂️heroic Label. From f067a20ba97734c8c82a044fe4630aaeac014dbb Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 18 Oct 2019 08:47:14 -0400 Subject: [PATCH 21/22] hero stuff. --- MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift | 10 ++++++++-- MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h | 3 --- MVMCoreUI/Templates/MoleculeListCellProtocol.h | 3 +++ MVMCoreUI/Templates/MoleculeListTemplate.swift | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index 2e8b9bfc..2ae52775 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -56,6 +56,7 @@ import UIKit open override func layoutSubviews() { super.layoutSubviews() + // Ensures accessory view aligns to the center y derived from the if let center = heroAccessoryCenter { accessoryView?.center.y = center.y } @@ -83,6 +84,11 @@ import UIKit bottomSeparatorView?.hide() } + public func willDisplay() { + + alignAccessoryToHero() + } + // MARK: - Inits public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) @@ -126,7 +132,7 @@ import UIKit /// NOTE: Should only be called when displayed or about to be displayed. public func alignAccessoryToHero() { - // Layout call required to force draw in memory to get dinmensions of subviews. + // Layout call required to force draw in memory to get dimensions of subviews. layoutIfNeeded() guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return } let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel) @@ -240,7 +246,7 @@ import UIKit // MARK: - Arrow /// Adds the standard mvm style caret to the accessory view - public func addCaretViewAccessory() { + @objc public func addCaretViewAccessory() { guard accessoryView == nil else { return } let width: CGFloat = 6 let height: CGFloat = 10 diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h index 273329aa..a499eb7c 100644 --- a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h @@ -24,9 +24,6 @@ /// Resets to default state before set with json is called again. - (void)reset; -/// Currently designed for UITableViewCell. Aligns the accessory view with the center of a character in a line of text. -- (void)alignAccessoryToHero; - /// For the molecule list to load more efficiently. + (CGFloat)estimatedHeightForRow:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; diff --git a/MVMCoreUI/Templates/MoleculeListCellProtocol.h b/MVMCoreUI/Templates/MoleculeListCellProtocol.h index 7603c820..8eae2e58 100644 --- a/MVMCoreUI/Templates/MoleculeListCellProtocol.h +++ b/MVMCoreUI/Templates/MoleculeListCellProtocol.h @@ -17,4 +17,7 @@ /// Handle action - (void)didSelectCellAtIndex:(nonnull NSIndexPath *)indexPath delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData; +/// Currently designed for UITableViewCell. Aligns the accessory view with the center of a character in a line of text. +- (void)willDisplay; + @end diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 84a7e64b..b400f0a9 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -89,8 +89,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { open override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { - if cell.accessoryView != nil, let protocolCell = cell as? (MoleculeTableViewCell & MVMCoreUIMoleculeViewProtocol) { - protocolCell.alignAccessoryToHero() + if let protocolCell = cell as? MoleculeListCellProtocol { + protocolCell.willDisplay?() } } From 0bb1debc77500bfa1b4d833b4800db334ab3ff40 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 18 Oct 2019 10:28:22 -0400 Subject: [PATCH 22/22] no comment. --- MVMCoreUI/Templates/MoleculeListCellProtocol.h | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Templates/MoleculeListCellProtocol.h b/MVMCoreUI/Templates/MoleculeListCellProtocol.h index 8eae2e58..3fa19a02 100644 --- a/MVMCoreUI/Templates/MoleculeListCellProtocol.h +++ b/MVMCoreUI/Templates/MoleculeListCellProtocol.h @@ -17,7 +17,6 @@ /// Handle action - (void)didSelectCellAtIndex:(nonnull NSIndexPath *)indexPath delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData; -/// Currently designed for UITableViewCell. Aligns the accessory view with the center of a character in a line of text. - (void)willDisplay; @end