How can I add image in UITextView? [duplicate] - ios

This question already has answers here:
How to add image and text in UITextView in IOS?
(10 answers)
Closed 6 years ago.
I'm making a note taking app but I ran into trouble.
I want to put a image in UITextView. I used NSAttributedString to put the image in UITextView but when I put image from the imagepicker, the image size is too big like this
I want to make it like the apple notes app
How can I figure that?
let images = selectedImage
let attachment = NSTextAttachment()
attachment.image = images
let attString = NSAttributedString(attachment: attachment)
textView.textStorage.insertAttributedString(attString, atIndex: textView.selectedRange.location)

This might be helpful to you
let textView = UITextView(frame: CGRectMake(50, 50, 200, 300))
let attributedString = NSMutableAttributedString(string: "before after")
let textAttachment = NSTextAttachment()
textAttachment.image = UIImage(named: "sample_image.jpg")!
let oldWidth = textAttachment.image!.size.width;
let scaleFactor = oldWidth / (textView.frame.size.width - 10); //for the padding inside the textView
textAttachment.image = UIImage(CGImage: textAttachment.image!.CGImage, scale: scaleFactor, orientation: .Up)
var attrStringWithImage = NSAttributedString(attachment: textAttachment)
attributedString.replaceCharactersInRange(NSMakeRange(6, 1), withAttributedString: attrStringWithImage)
textView.attributedText = attributedString;
self.view.addSubview(textView)

Related

Vertically aligning NSTextAttachment in NSMutableAttributedString

I'm adding an icon to a UILabel using NSTextAttachment inside an NSMutableAttributedString like this:
//Setting up icon
let moneyIcon = NSTextAttachment()
moneyIcon.image = UIImage(named: "MoneyIcon")
let moneyIconString = NSAttributedString(attachment: moneyIcon)
//Setting up text
let balanceString = NSMutableAttributedString(string: " 1,702,200")
balanceString.insert(moneyIconString, at: 0)
//Adding string to label
self.attributedText = balanceString
self.sizeToFit()
But for some reason the icon isn't vertically aligned
Does anybody know how can I align it?
Thank you!
use bounds property of NSTextAttachment.
//Setting up icon
let moneyIcon = NSTextAttachment()
moneyIcon.image = UIImage(named: "MoneyIcon")
let imageSize = moneyIcon.image!.size
moneyIcon.bounds = CGRect(x: CGFloat(0), y: (font.capHeight - imageSize.height) / 2, width: imageSize.width, height: imageSize.height)
let moneyIconString = NSAttributedString(attachment: moneyIcon)
//Setting up text
let balanceString = NSMutableAttributedString(string: " 1,702,200")
balanceString.insert(moneyIconString, at: 0)
//Adding string to label
self.attributedText = balanceString
self.sizeToFit()
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)

Swift iOS -How to Set NSTextAttachment Content Mode to Aspect Fit?

I have a PDF image that I appended to a String. I used NSTextAttachment and NSAttributedString to get it done. I add them to a textView and the result is Hello with an image of the World underneath of it.
The problem is when I set the bounds for the PDF image on the textAttachment the World image is distorted. It's stretched long and wide.
How can I set a contentMode on the textAttachment object to redraw the image correctly using .aspectRatio?
number #4 is where I set the bounds
// #1. Define dict attribute for string
let bold17 = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: 17)]
// #2. Create "hello" string and add the dict attribute to it
let helloStr = NSAttributedString(string: "Hello\n\n", attributes: bold17)
// #3. Create NSTextAttachment
let textAttachment = NSTextAttachment()
// #4. Add image to the textAttachment then set it's bounds
textAttachment.image = UIImage(named: "world_PDF")
textAttachment.bounds = CGRect(x: 0, y: 0, width: 200, height: 200)
// #5. Set image as NSAttributedString
let worldImage = NSAttributedString(attachment: textAttachment)
// #6. Create NSMutableString to
let mutableAttributedString = NSMutableAttributedString()
// #7. Append the "hello" string and the "world" image to each other using the mutableAttributedString object
mutableAttributedString.append(helloStr)
mutableAttributedString.append(worldImage)
// #8. Set the mutableAttributedString to the textView then center it
textView.attributedText = mutableAttributedString
textView.textAlignment = .center
I followed #Maciej Swic's answer
Resize NSTextAttachment Image
For some reason I couldn't extend the NSTextAttachment class so I added it to the bottom of the class I was using it in. I removed the bounds property that I used in my question and used his function instead. It's on #4, the second line:
class MyController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
// #1. Define dict attribute for string
let bold17 = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: 17)]
// #2. Create "hello" string and add the dict attribute to it
let helloStr = NSAttributedString(string: "Hello\n\n", attributes: bold17)
// #3. Create NSTextAttachment
let textAttachment = NSTextAttachment()
// #4. Add image to the textAttachment then set it's bounds
textAttachment.image = UIImage(named: "world_PDF")
textAttachment.setImageHeight(height: 200) // <----HIS ANSWER HERE
// #5. Set image as NSAttributedString
let worldImage = NSAttributedString(attachment: textAttachment)
// #6. Create NSMutableString to
let mutableAttributedString = NSMutableAttributedString()
// #7. Append the "hello" string and the "world" image to each other using the mutableAttributedString object
mutableAttributedString.append(helloStr)
mutableAttributedString.append(worldImage)
// #8. Set the mutableAttributedString to the textView then center it
textView.attributedText = mutableAttributedString
textView.textAlignment = .center
}
}
extension NSTextAttachment {
func setImageHeight(height: CGFloat) {
guard let image = image else { return }
let ratio = image.size.width / image.size.height
bounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: ratio * height, height: height)
}
}

image and string in same label in swift 2

I have image and string in label togher in navigation bar
When I use coins, say use all 50 of them it should be 0 with image coins but its not
but when I click to another viewcontroller and back to same viewcontroller with coins the image is back
here is code:
let coinLabel = UILabel()
override func viewWillAppear(animated: Bool) {
// Set icon in label in navigation bar ////
let image = UIImage(named: "coins.jpeg")
let newSize = CGSize(width: 15, height: 15)
//Resize image
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
let imageResized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//Create attachment text with image
let attachment = NSTextAttachment()
attachment.image = imageResized
let attachmentString = NSAttributedString(attachment: attachment)
let myString = NSMutableAttributedString(string: "\(coins)")
myString.appendAttributedString(attachmentString)
coinLabel.attributedText = myString
coinLabel.sizeToFit()
// Set defined label to navigation bar right corner
let leftItem = UIBarButtonItem(customView: coinLabel)
self.navigationItem.rightBarButtonItem = leftItem
coinLabel.font = coinLabel.font.fontWithSize(15)
}
I think the problem is with reloading... or something. Any Idea??
Don't sure that it's a reason but at least you need to set font before calling sizeToFit()
coinLabel.font = coinLabel.font.fontWithSize(15)
coinLabel.sizeToFit()
Also you missed call to super.viewWillAppear(animated)

Text size is not same when draw text on UIimage

I am working on project where I need to add text to the image which is coming from the textfield.
But when I see the text on the image it shows the font size smaller than the font size of textfield.
I am using following method to draw text on image
func drawText(text: String, inImage image: UIImage, atPoint point: CGPoint, fontName:String, fontSize: String,textColor: UIColor) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(image.size, true, UIScreen.mainScreen().scale)
UIGraphicsBeginImageContext(image.size)
image.drawInRect(CGRectMake(0, 0, image.size.width, image.size.height))
let rect: CGRect = CGRectMake(point.x, point.y, image.size.width, image.size.height)
// UIColor.whiteColor().set()
// set the font to Helvetica Neue 18
if let sizeFont = NSNumberFormatter().numberFromString(fontSize) {
// TODO: - Need to resolve issue
let originalSize = sizeFont.integerValue
let finalFontSize = CGFloat(originalSize)
let fieldFont = UIFont(name: fontName, size:finalFontSize*1.5)
// set the line spacing to 6
let paraStyle = NSMutableParagraphStyle()
// paraStyle.lineSpacing = 6.0
// set the Obliqueness to 0.1
// let skew = 0.1
let attributes: NSDictionary = [
NSForegroundColorAttributeName: textColor,
// NSParagraphStyleAttributeName: paraStyle,
// NSObliquenessAttributeName: skew,
NSFontAttributeName: fieldFont!
]
NSString(string: text).drawInRect(rect, withAttributes: attributes as? [String : AnyObject])
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
return nil
}
And font size could be 16-60px.
Please let me know what could be the solution.
Thanks
Everything seems fine with your code.
One possible problem is that you don't see the image at full size inside your ImageView because it scales it, so you see the font smaller than what you want.
You could resize the image before drawing the text on it to fit the container it will be displayed on.
Or you can calculate the fontSize multiplying it with 1/scale, with scale = the scale at will the image will be shown
For example if the image is taller than larger and the container (the imageView) is smaller than the image scale will be image.size.height/imageView.frame.size.height.
I think that this could resolve your problem.
As suggested by LorenzOliveto, this could be due to scaling issues. One of the easy workaround would be to add text as a subview of imageView and then convert the imageView to image using this extension.
extension UIView {
/**
Convert UIView to UIImage
*/
func toImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return snapshotImageFromMyView!
}
}

Taking a screenshot and adding a text/watermark on top in Swift

Im trying to allow the ability for a user to share a screenshot of an App and share it. I have got the taking of a screenshot and sharing but was interested in finding out if anyone knew how to add a layer of text on top of that screenshot when it is being taken, kind of like a watermark.
Here I take the screenshot:
let layer = UIApplication.sharedApplication().keyWindow!.layer
let scale = UIScreen.mainScreen().scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.renderInContext(UIGraphicsGetCurrentContext()!)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let croppedImage = self.cropImage(screenshot)
let activityViewController = UIActivityViewController(activityItems: [croppedImage], applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)
I crop the screenshot image in this function so it just shows middle of screen:
func cropImage(screenshot: UIImage) -> UIImage {
let scale = screenshot.scale
let imgSize = screenshot.size
let screenHeight = UIScreen.mainScreen().bounds.height
let bound = self.view.bounds.height
let navHeight = self.navigationController!.navigationBar.frame.height
let bottomBarHeight = screenHeight - navHeight - bound
let crop = CGRectMake(0, 200, //"start" at the upper-left corner
(imgSize.width - 1) * scale, //include half the width of the whole screen
(imgSize.height - bottomBarHeight - 300) * scale) //include the height of the navigationBar and the height of view
let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop)
let image: UIImage = UIImage(CGImage: cgImage!)
return image
}
Yes it is possible to do that. Try adding subview to your image view like below
let newImageView = UIImageView(image : croppedImage)
let labelView = UILabel(frame: CGRectMake(30, 30, 100, 20)) //adjust frame to change position of water mark or text
labelView.text = "my text"
newImageView.addSubview(labelView)
UIGraphicsBeginImageContext(newImageView.frame.size)
newImageView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let watermarkedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

Resources