Setting attributed label as navigation title - ios

I am working on IOS using swift 4. I have to make the Navigation controller, with the center Aligned App title with Image at its left. But I am not getting how to attach image to its left. The attributed Image always goes to its right.
For this I am appending the string twice. below is the code
//Get image and set it's size
let image = UIImage(named: "user2")
let newSize = CGSize(width: 30, height: 30)
//Resize image
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image?.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: 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: "")
myString.append(attachmentString)
let strAttachment = NSAttributedString(string: "My Ios App" )
myString.append(strAttachment)
navLabel.attributedText = myString
self.navigationItem.titleView = navLabel
What I am getting is some thing like below image is on left
what I want :
I just want the image to be shown with the space between text and Image.
I want the image to be look good and nice. Text should be center vertically to the image. what is good way of achieving this ?.

Using this code you will get your output :
let navgationView = UIView()
let label = UILabel()
label.text = " My Ios App"
label.sizeToFit()
label.center = navgationView.center
label.textAlignment = NSTextAlignment.center
let image = UIImageView()
image.image = UIImage(named: "user")
let imageAspect = image.image!.size.width/image.image!.size.height
image.frame = CGRect(x: label.frame.origin.x-label.frame.size.height*imageAspect, y: label.frame.origin.y, width: label.frame.size.height*imageAspect, height: label.frame.size.height)
image.contentMode = UIViewContentMode.scaleAspectFit
navgationView.addSubview(label)
navgationView.addSubview(image)
self.navigationItem.titleView = navgationView
navgationView.sizeToFit()
Output:-
Hope it's helps.!!

If you want to adjust your attachment position you must use the attachment.bounds property and if you want to adjust the text vertical alignment you need to use NSAttributedString baselineOffset key
Update
Swift 3 code
let normalNameString = NSMutableAttributedString.init(string: "")
let attachment = NSTextAttachment()
attachment.image = imageHelper.pgImage(textValue: "PG-13")
attachment.bounds = CGRect(x: 0, y: 0, width: (attachment.image?.size.width)!, height: (attachment.image?.size.height)!)
normalNameString.append(NSAttributedString(attachment: attachment))
normalNameString.append(NSAttributedString(string: " My Ios App", attributes: [NSBaselineOffsetAttributeName :6]))
self.lblText.attributedText = normalNameString
Swift 4 code
let normalNameString = NSMutableAttributedString.init(string: "")
let attachment = NSTextAttachment()
attachment.image = imageHelper.pgImage(textValue: "PG-13")
attachment.bounds = CGRect(x: 0, y: 0, width: (attachment.image?.size.width)!, height: (attachment.image?.size.height)!)
normalNameString.append(NSAttributedString(attachment: attachment))
normalNameString.append(NSAttributedString(string: " My Ios App", attributes: [NSAttributedStringKey.baselineOffset :6]))
self.lblText.attributedText = normalNameString
Swift 5 Update
let normalNameString = NSMutableAttributedString.init(string: "")
let attachment = NSTextAttachment()
attachment.image = imageHelper.pgImage(textValue: "PG-13")
attachment.bounds = CGRect(x: 0, y: 0, width: (attachment.image?.size.width)!, height: (attachment.image?.size.height)!)
normalNameString.append(NSAttributedString(attachment: attachment))
normalNameString.append(NSAttributedString(string: " My Ios App", attributes: [NSAttributedString.Key.baselineOffset :6]))
self.lblText.attributedText = normalNameString

Related

UILabel custom Text

How can I make this text using single UILabel or give any other solution to achieve this design.
You can use NSTextAttachment for that behaviour. I modify this for position of attachment.
All code :
#IBOutlet weak var lbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let string = "Urban points users average montly saving is "
let normalNameString = NSMutableAttributedString.init(string: string)
let attachment = NSTextAttachment()
attachment.image = imageHelper.pgImage(textValue: "QAR 115 ", lbl: lbl)
attachment.bounds = CGRect(x: 0, y: (lbl.font.capHeight - attachment.image!.size.height).rounded() / 2, width: attachment.image!.size.width, height: attachment.image!.size.height)
normalNameString.append(NSAttributedString(attachment: attachment))
normalNameString.append(NSAttributedString(string: "You have saved "))
let attachment2 = NSTextAttachment()
attachment2.image = imageHelper.pgImage(textValue: "QAR 29",textColor: UIColor.yellow,backgroundColor: UIColor.black , lbl: lbl)
attachment2.bounds = CGRect(x: 0, y: (lbl.font.capHeight - attachment2.image!.size.height).rounded() / 2, width: attachment2.image!.size.width, height: attachment2.image!.size.height)
normalNameString.append(NSAttributedString(attachment: attachment2))
normalNameString.append(NSAttributedString(string: " this month"))
lbl.attributedText = normalNameString
}
}
class imageHelper{
static func pgImage(textValue:String,textColor : UIColor = UIColor.white , backgroundColor : UIColor = UIColor.red,lbl : UILabel) ->UIImage{
let label = UILabel(frame: CGRect(x: 0, y: 0, width: (textValue as NSString).size(withAttributes: [NSAttributedString.Key.font : lbl.font!]).width, height: lbl.frame.size.height))
label.font = lbl.font
label.textAlignment = .center
label.textColor = textColor
label.backgroundColor = backgroundColor
label.layer.borderColor = UIColor.darkGray.cgColor
label.layer.borderWidth = 1
label.layer.cornerRadius = label.frame.size.height/2
label.layer.masksToBounds = true
label.text = textValue
label.numberOfLines = 1
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false,UIScreen.main.scale)
label.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
And the result is :

How change height in navigation title?

I need to set the rockwell-bold font in the navigation title, but it is cropped for me. how can I fix this problem or change the height of the navigation titleenter image description here
let customText = NSLocalizedString("your_title", comment: "")
let title:NSMutableAttributedString = NSMutableAttributedString(string: customText, attributes: [.font: UIFont(name: "font_name", size: 20.0) ])
let size = title.size()
let width = size.width
guard let height = navigationController?.navigationBar.frame.size.height else {return}
let titleLabel = UILabel(frame: CGRect(x: 0,y: 0, width: width, height: height))
titleLabel.attributedText = title
titleLabel.numberOfLines = 0
titleLabel.textAlignment = .center
navigationItem.titleView = titleLabel

Change icon position in swift 3

I have the following code which shows an icon on the left side of a uilabel, my question is how can I put the icon on the right side of the uilabel:
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "ic_person")
attachment.bounds = CGRect(x: 0, y: -3, width: 15, height: 15)
let attachmentStr = NSAttributedString(attachment: attachment)
let myString = NSMutableAttributedString(string: "")
myString.append(attachmentStr)
let myString1 = NSMutableAttributedString(string: item_empresa[indexPath.item].nombre_emp!)
myString.append(myString1)
cell.lbl_nombreEmpresa.attributedText = myString
Thanks in advance
You can put the image after the text by appending attachment after appending the text itself
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "ic_person")
attachment.bounds = CGRect(x: 0, y: -3, width: 15, height: 15)
let attributedString = NSMutableAttributedString(string: item_empresa[indexPath.item].nombre_emp ?? "")
attributedString.append(NSAttributedString(attachment: attachment))
cell.lbl_nombreEmpresa.attributedText = attributedString

google maps iOS SDK: custom icons to be used as markers

The Android API has a very convenient class for this, IconGenerator. Using the IconGenerator in my Android app, I can easily make a marker that:
is a simple rectangle with the color of my choosing.
resizes to hold text of any length.
is NOT an info window - I'd like the marker itself to contain the text as shown in the image below from the android version.
// Android - problem solved with IconGenerator
IconGenerator iconGenerator = new IconGenerator(context);
iconGenerator.setStyle(IconGenerator.STYLE_GREEN); // or any other color
Bitmap iconBitmap = iconGenerator.makeIcon(myString);
Marker m = new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(iconBitmap))
.position(myLatLng);
map.addMarker(m); // map is a com.google.android.gms.maps.GoogleMap
Is there a way to do something as simple as this in iOS using Swift?
There has been a recent release of the iOS api that allows "marker customization", but I don't see how to apply it to this use case.
// iOS (Swift) - I don't know how to create the icon as in code above
let marker = GMSMarker(position: myLatLng)
marker.icon = // How can I set to a rectangle with color/text of my choosing?
marker.map = map // map is a GMSMapView
Here is what I have done
let marker = GMSMarker()
// I have taken a pin image which is a custom image
let markerImage = UIImage(named: "mapMarker")!.withRenderingMode(.alwaysTemplate)
//creating a marker view
let markerView = UIImageView(image: markerImage)
//changing the tint color of the image
markerView.tintColor = UIColor.red
marker.position = CLLocationCoordinate2D(latitude: 28.7041, longitude: 77.1025)
marker.iconView = markerView
marker.title = "New Delhi"
marker.snippet = "India"
marker.map = mapView
//comment this line if you don't wish to put a callout bubble
mapView.selectedMarker = marker
The output is
And my marker image was
You can change your color as per your need. Also if you want something in rectange, you can just create a simple small rectangular image and use it like I did above and change the color of your need.
Or if you want a rectangle with text within it, you can just create a small UIView with some label and then convert that UIView in UIImage and can do the same thing.
//function to convert the given UIView into a UIImage
func imageWithView(view:UIView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
Hope it helps!!
Here is what i have done for solving the same issue, that you are facing.
I have added below image in my image assets,
Now i added below method in my code:
-(UIImage*)drawText:(NSString*)text inImage:(UIImage*)image
{
UIFont *font = [UIFont boldSystemFontOfSize:11];
CGSize size = image.size;
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.alignment = NSTextAlignmentCenter;
NSDictionary *attributes = #{
NSFontAttributeName : font,
NSParagraphStyleAttributeName : paragraphStyle,
NSForegroundColorAttributeName : [UIColor redColor]
};
CGSize textSize = [text sizeWithAttributes:attributes];
CGRect textRect = CGRectMake((rect.size.width-textSize.width)/2, (rect.size.height-textSize.height)/2 - 2, textSize.width, textSize.height);
[text drawInRect:CGRectIntegral(textRect) withAttributes:attributes];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Now, I called this method, while assigning icon to GMSMarker, like this:
marker.icon = [self drawText:#"$33.6" inImage:[UIImage imageNamed:#"icon-marker"]];
It will generate the image icon like below:
Here, I kept the background Image size fixed, as i needed. You can still customize it to adjust it according to text size, as well as multiple lines.
UPDATE
Updated code in Swift:
func drawText(text:NSString, inImage:UIImage) -> UIImage? {
let font = UIFont.systemFont(ofSize: 11)
let size = inImage.size
//UIGraphicsBeginImageContext(size)
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(inImage.size, false, scale)
inImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let style : NSMutableParagraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
style.alignment = .center
let attributes:NSDictionary = [ NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style, NSAttributedString.Key.foregroundColor : UIColor.black ]
let textSize = text.size(withAttributes: attributes as? [NSAttributedString.Key : Any])
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
let textRect = CGRect(x: (rect.size.width - textSize.width)/2, y: (rect.size.height - textSize.height)/2 - 2, width: textSize.width, height: textSize.height)
text.draw(in: textRect.integral, withAttributes: attributes as? [NSAttributedString.Key : Any])
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
You can simply add a custom view as marker in Google Map.
let marker = GMSMarker(position: coordinate)
marker.iconView = view // Your Custom view here
You can use imageView (for containing that orange color box) and label (for text) above it
I tried to rewrite Mehul Thakkar answer to Swift 3. Hope it will work for you. But it really easier to make custom view as Dari said.
func drawText(text:NSString, inImage:UIImage) -> UIImage? {
let font = UIFont.systemFont(ofSize: 11)
let size = inImage.size
UIGraphicsBeginImageContext(size)
inImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let style : NSMutableParagraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
style.alignment = .center
let attributes:NSDictionary = [ NSFontAttributeName : font, NSParagraphStyleAttributeName : style, NSForegroundColorAttributeName : UIColor.red ]
let textSize = text.size(attributes: attributes as? [String : Any])
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
let textRect = CGRect(x: (rect.size.width - textSize.width)/2, y: (rect.size.height - textSize.height)/2 - 2, width: textSize.width, height: textSize.height)
text.draw(in: textRect.integral, withAttributes: attributes as? [String : Any])
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
Here a Swift 5 version of Eridana's Swift conversion of Mehul Thakkar's answer.
func drawTextT(text:NSString, inImage:UIImage) -> UIImage? {
let font = UIFont.systemFont(ofSize: 11)
let size = inImage.size
UIGraphicsBeginImageContext(size)
inImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let style : NSMutableParagraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
style.alignment = .center
let attributes:NSDictionary = [ NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style, NSAttributedString.Key.foregroundColor : UIColor.red ]
//let textSize = text.size(attributes: attributes as? [String : Any])
let textSize = text.size(withAttributes: attributes as? [NSAttributedString.Key : Any] )
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
let textRect = CGRect(x: (rect.size.width - textSize.width)/2, y: (rect.size.height - textSize.height)/2 - 2, width: textSize.width, height: textSize.height)
text.draw(in: textRect.integral, withAttributes: attributes as? [NSAttributedString.Key : Any] )
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
Simplest way to achieve if you have just 1 image :
marker.icon = #imageLiteral(resourceName: "fault_marker")
1) In latest XCode write marker.icon = "imageLiteral".
2) Double click the dummy image icon appeared just now.
3) select desired image.
//func to get Image view
// Url String :- Your image coming from server
//image :- Background image
func drawImageWithProfilePic(urlString:String, image: UIImage) -> UIImageView {
let imgView = UIImageView(image: image)
imgView.frame = CGRect(x: 0, y: 0, width: 90, height: 90)
let picImgView = UIImageView()
picImgView.sd_setImage(with:URL(string: urlString))
picImgView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
imgView.addSubview(picImgView)
picImgView.center.x = imgView.center.x
picImgView.center.y = imgView.center.y-10
picImgView.layer.cornerRadius = picImgView.frame.width/2
picImgView.clipsToBounds = true
imgView.setNeedsLayout()
picImgView.setNeedsLayout()
// let newImage = imageWithView(view: imgView)
// return newImage
return imgView
}
//SHOW ON MAP
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: Double(lat)!, longitude: Double(long)!)
marker.iconView = self.drawImageWithProfilePic(urlString:getProviderImage,image: UIImage.init(named: "red")!)
Simple and easiest way to change icon. just replace these 3 icon (default marker.png) to your icon (1x,2x,3x).
In Google Cluster there was a problem with marker (icon) change.

How to dynamically draw image for button in iOS?

This is the result I need to accomplish:
I need the icons with basic image: basket and additionally I need to put there UILabel with some text: once it is just a number, and once it is an amount to pay. Any ideas?
This is my example:
var image = UIImage(named: "cart")!
let text = "1 PLN"
UIGraphicsBeginImageContext(CGSizeMake(80, 50))
let context = UIGraphicsGetCurrentContext()
let label = UILabel(frame: CGRectZero)
label.text = text
label.font = UIFont.systemFontOfSize(10)
label.sizeToFit()
let width = max(label.frame.size.width + 10, 15)
let height = CGFloat(15)
CGContextSetFillColorWithColor(context, UIColor.greenColor().CGColor)
CGContextFillRect(context, CGRectMake(0, 0, image.size.width, image.size.height))
image.drawInRect(CGRectMake(80/2-50/2, 0, 50, 50))
let path = UIBezierPath(roundedRect: CGRectMake(75-width, 45-height, width, height), cornerRadius: 5)
path.lineWidth = 2
UIColor.redColor().setStroke()
UIColor.yellowColor().setFill()
path.stroke()
path.fill()
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.Center
let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(10.0), NSParagraphStyleAttributeName: paragraphStyle]
(text as NSString).drawInRect(CGRectMake(75-width, 45-height, width, height), withAttributes: attributes)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
The result is following:
Some examples for different text:

Resources