Label Improvements. Conveniences added. Greater accuracy to tap detection provided.
This commit is contained in:
parent
b3cc938a9e
commit
4770aa6e6b
@ -115,25 +115,11 @@ public typealias ActionBlock = () -> ()
|
||||
standardFontSize = size
|
||||
}
|
||||
|
||||
/// Convenience to init Label as a TextButton. All text will behave as a link.
|
||||
@objc convenience public init(text: String, actionBlock: @escaping ActionBlock) {
|
||||
self.init()
|
||||
self.text = text
|
||||
setTextLinkState(range: getRange, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
/// Convenience to init Label where the provided text will be marked as tappable by the given range.
|
||||
@objc convenience public init(text: String, range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
self.init()
|
||||
self.text = text
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
/// Convenience to init Label with the link comprised of range, actionMap and delegateObject
|
||||
@objc convenience public init(text: String, range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
self.init()
|
||||
self.text = text
|
||||
if let actionBlock = Label.createActionBlockFor(label: self, actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
@ -333,7 +319,7 @@ public typealias ActionBlock = () -> ()
|
||||
guard let actionLabel = label as? Label else { continue }
|
||||
|
||||
actionLabel.addActionAttributes(range: range, string: attributedString)
|
||||
if let actionBlock = Label.createActionBlockFor(label: actionLabel, actionMap: json, additionalData: additionalData, delegateObject: delegate) {
|
||||
if let actionBlock = actionLabel.createActionBlockFor(actionMap: json, additionalData: additionalData, delegateObject: delegate) {
|
||||
actionLabel.appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
@ -510,7 +496,7 @@ public typealias ActionBlock = () -> ()
|
||||
}
|
||||
|
||||
/// Call to detect in the attributedText contains an NSTextAttachment.
|
||||
func textContainsTextAttachment() -> Bool {
|
||||
func containsTextAttachment() -> Bool {
|
||||
|
||||
guard let attributedText = attributedText else { return false }
|
||||
|
||||
@ -588,10 +574,9 @@ extension Label {
|
||||
clauses = []
|
||||
}
|
||||
|
||||
public static func createActionBlockFor(label: Label?, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) -> ActionBlock? {
|
||||
guard let label = label else { return nil }
|
||||
return {
|
||||
if (delegateObject as? MVMCoreUIDelegateObject)?.buttonDelegate?.button?(label, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true {
|
||||
public func createActionBlockFor(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) -> ActionBlock? {
|
||||
return { [weak self] in
|
||||
if let wSelf = self, (delegateObject as? MVMCoreUIDelegateObject)?.buttonDelegate?.button?(wSelf, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true {
|
||||
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
@ -635,19 +620,19 @@ extension Label {
|
||||
*/
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
if let actionBlock = Label.createActionBlockFor(label: self, actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func makeAllTextLinkable(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
@objc public func makeTextButton(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
if let actionBlock = Label.createActionBlockFor(label: self, actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: getRange, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func makeAllTextLinkable(actionBlock: @escaping ActionBlock) {
|
||||
@objc public func makeTextButton(actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setTextLinkState(range: getRange, actionBlock: actionBlock)
|
||||
}
|
||||
@ -689,7 +674,7 @@ extension UITapGestureRecognizer {
|
||||
paragraph.alignment = label.textAlignment
|
||||
|
||||
let stagedAttributedString = NSMutableAttributedString(attributedString: attributedText)
|
||||
stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count))
|
||||
stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count))
|
||||
|
||||
let textStorage = NSTextStorage(attributedString: stagedAttributedString)
|
||||
let layoutManager = NSLayoutManager()
|
||||
@ -703,9 +688,33 @@ extension UITapGestureRecognizer {
|
||||
textContainer.maximumNumberOfLines = label.numberOfLines
|
||||
textContainer.size = label.bounds.size
|
||||
|
||||
let indexOfGlyph = layoutManager.glyphIndex(for: location(in: label), in: textContainer)
|
||||
|
||||
return layoutManager.boundingRect(forGlyphRange: targetRange, in: textContainer).contains(location(in: label)) && NSLocationInRange(indexOfGlyph, targetRange)
|
||||
let tapLocation = location(in: label)
|
||||
let indexOfGlyph = layoutManager.glyphIndex(for: tapLocation, in: textContainer)
|
||||
let intrinsicWidth = label.intrinsicContentSize.width
|
||||
|
||||
// Assert that tapped occured within acceptable bounds based on alignment.
|
||||
switch label.textAlignment {
|
||||
case .right:
|
||||
if tapLocation.x < label.bounds.width - intrinsicWidth {
|
||||
return false
|
||||
}
|
||||
case .center:
|
||||
let halfBounds = label.bounds.width / 2
|
||||
let halfintrinsicWidth = intrinsicWidth / 2
|
||||
|
||||
if tapLocation.x > halfBounds + halfintrinsicWidth{
|
||||
return false
|
||||
} else if tapLocation.x < halfBounds - halfintrinsicWidth {
|
||||
return false
|
||||
}
|
||||
default: // Left align
|
||||
if tapLocation.x > intrinsicWidth {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Affirms that the tap occured in the desired rect of provided by the target range.
|
||||
return layoutManager.boundingRect(forGlyphRange: targetRange, in: textContainer).contains(tapLocation) && NSLocationInRange(indexOfGlyph, targetRange)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -207,7 +207,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
|
||||
@objc public func setActionMap(_ actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
actionBlock = Label.createActionBlockFor(label: label, actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
actionBlock = label?.createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
@ -377,7 +377,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
actionText = actionMap?.optionalStringForKey(KeyTitle)
|
||||
backText = actionMap?.optionalStringForKey(KeyTitlePostfix)
|
||||
text = getTextFromStringComponents()
|
||||
actionBlock = Label.createActionBlockFor(label: label, actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
actionBlock = label?.createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
setLabelAttributes()
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user