Center NSTextAttachment image next to single line UILabel
You can change the rect by subclassing NSTextAttachment
and overriding attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex:
. Example:
- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex {
CGRect bounds;
bounds.origin = CGPointMake(0, -5);
bounds.size = self.image.size;
return bounds;
}
It's not a perfect solution. You have to figure out the Y-origin “by eye” and if you change the font or the icon size, you'll probably want to change the Y-origin. But I couldn't find a better way, except by putting the icon in a separate image view (which has its own disadvantages).
Vertically aligning NSTextAttachment in NSMutableAttributedString
This answer, which is about vertically centering two differently sized fonts in a single NSAttributedString
, mentions using the baseline offset to calculate the center of the string.
You can use the same approach when using an image:
Subtract the font size from the image's height and divide it by 2.
Subtract the font's descender from the value (since font size isn't the same as the ascent of your font). The font that you are particularly using (Baloo-Regular) has a descender value that differs from the standard and it should be divided by 2. Other fonts (including San Fransisco) don't need that fix or require a different divisor.
This code covers most cases, if your font behaves differently, you should check out the guide for managing texts in Text Kit.
// *Setting up icon*
let moneyIcon = NSTextAttachment()
// If you're sure a value is not and will never be nil, you can use "!".
// Otherwise, avoid it.
let moneyImage = UIImage(named: "MoneyIcon")!
moneyIcon.image = moneyImage
let moneyIconString = NSAttributedString(attachment: moneyIcon)
// *Setting up NSAttributedString attributes*
let balanceFontSize: CGFloat = 16
let balanceFont = UIFont(name: "Baloo", size: balanceFontSize)!
let balanceBaselineOffset: CGFloat = {
let dividend = moneyImage.size.height - balanceFontSize
return dividend / 2 - balanceFont.descender / 2
}()
let balanceAttr: [NSAttributedString.Key: Any] = [
.font: balanceFont,
.baselineOffset: balanceBaselineOffset
]
// *Setting up text*
let balanceString = NSMutableAttributedString(
string: " 1,702,200",
attributes: balanceAttr
)
balanceString.insert(moneyIconString, at: 0)
How to center image in attributed string?
You just need to Alignment your lebel text to center and it will work :
label.textAlignment = .center
How can I center an image on a textView who is attached to a NSTextAttachment type?
Answer(worked for me!):
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
attributedText.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: length))
let size = CGSize(width: 100, height: 100)
//Here is an attempt to resize image and center it...
let image = ResizeImage(image: UIImage(named: "logo")!.withRenderingMode(.alwaysTemplate), targetSize: size)
let textAttachment = NSTextAttachment()
let imageStyle = NSMutableParagraphStyle()
imageStyle.alignment = .center
textAttachment.image = image
let imageText = NSAttributedString(attachment: textAttachment).mutableCopy() as! NSMutableAttributedString
let length2 = imageText.length
imageText.addAttribute(NSAttributedString.Key.paragraphStyle, value: imageStyle, range: NSRange(location: 0, length: length2))
Lines missing from tall UILabel when embedding NSTextAttachment
It really has nothing to do with the NSTextAttachment. It's that in iOS 7 as released so far, UILabel is not very good at drawing attributed strings. A simple attributed string with some underlining and a centered paragraph style will show up blank, or partially blank, in a UILabel; the same attributed string draws fine in a UITextView.
So, one solution for now is: Use UITextView instead. This is actually a pretty good solution because, in iOS 7, UITextView is just a wrapper around the Text Kit stack. So it is drawing the attributed string in a straightforward way. It is not hampered by the under-the-hood relationship to Web Kit that it had in previous iOS versions.
On the other hand, I have also found a workaround for this UILabel bug; you have to fiddle with the number of lines of the label and the string in such a way as to jam the text up to the top of the label: see my answer here - https://stackoverflow.com/a/19409962/341994
Or you could just wait for Apple to fix the bug and keep your fingers crossed. EDIT: In iOS 7.1, it appears that the bug will be fixed and no workaround will be needed.
Vertically center NSTextAttachment in a UITextView
Vertically center the content of a UITextView.
In viewWillAppear of your UIViewController.
textView.addObserver(self, forKeyPath: "contentSize", options: .New, context: nil)
In viewWillDisappear of your UIViewController.
textView.removeObserver(self, forKeyPath: "contentSize")
Override observeValueForKeyPath in your UIViewController.
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "contentSize" {
let height = textView.bounds.size.height
let contentHeight = textView.contentSize.height
let zoom = textView.zoomScale
let top = (height - contentHeight * zoom) / 2.0
textView.contentInset.top = top < 0.0 ? 0.0 : top
}
}
Horizontally center the content of an NSAttributtedString inside a UITextView.
let attachment = NSTextAttachment()
let attachmentAttrString = NSAttributedString(attachment: attachment)
let result = NSMutableAttributedString(attributedString: attachmentAttrString)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .Center
let attrs:[String:AnyObject] = [NSParagraphStyleAttributeName: paragraphStyle]
let range = NSMakeRange(0, result.length)
result.addAttributes(attrs, range: range)
textView.attributedText = result
Related Topics
Error When Trying to Call Setdata(From: ) in the Cloud Firestore iOS API. How to Fix It
Upload Files to Dropbox from iOS App with Swift
How to Limit an iOS App Only to 4 Inch Screen Devices
Fixing Xcode 9 Issue: "iPhone Is Busy: Preparing Debugger Support for Iphone"
Notificationcenter Issue on Swift 3
Uiscrollview with Centered Uiimageview, Like Photos App
Avaudioplayer Throws Breakpoint in Debug Mode
How to Call JavaScript Function in Objective C
Google Maps iOS Sdk, Getting Current Location of User
Could Not Find an Overload for "Init" That Accepts the Supplied Arguments in Swift
Autolayout Complains About Constraints for 2 Uitextfields with No Borders
Googlemaps Basic iOS Demo App Crash - Unrecognized Selector Sent to Instance
Xcode 10: a Valid Provisioning Profile for This Executable Was Not Found
After Upgrading to Xcode 11.2 from Xcode 11.1, App Crashes Due to _Uitextlayoutview
Linking Objective-C Categories in a Static Library
Upload Image to the PHP Server from iOS
Ios7 Uiswitch Its Event Valuechanged: Calling Continuously Is This Bug or What..