Text Shadow - iOS, swift 3.0 - ios

I'm trying to make shadow size a bit bigger but I can't do it.
so far:
findAPlace.titleLabel?.layer.shadowOffset = CGSize(width: -1, height: 1)
findAPlace.titleLabel?.layer.shouldRasterize = true
findAPlace.titleLabel?.layer.shadowRadius = 1
findAPlace.titleLabel?.layer.shadowOpacity = 1
findAPlace.titleLabel?.layer.shadowColor = UIColor(red:0.07, green:0.07, blue:0.07, alpha:1.0).cgColor
how to scale shadow to be bigger than the text itself?
something like this.
Maybe with a border can be done, My text is the title of a UIButton!!!I expect it to be all around text of the uiButton

You can do in this way
Actually You need to use setTitleShadowColor instead of titleLabel?.layer.shadowColor
Here is full working code
let btnTemp = UIButton(type: .custom)
btnTemp.frame = CGRect(x: 50, y: 200, width: 150, height: 40)
btnTemp.setTitle("Hello", for: .normal)
btnTemp.titleLabel?.layer.shouldRasterize = true
btnTemp.titleLabel?.layer.shadowRadius = 1.0
btnTemp.titleLabel?.layer.shadowOpacity = 1.0
btnTemp.setTitleColor(UIColor.blue, for: .normal)
btnTemp.backgroundColor = UIColor.gray
btnTemp.titleLabel?.shadowOffset = CGSize(width: -1, height: 1)
btnTemp.setTitleShadowColor(UIColor(red:0.07, green:0.07, blue:0.07, alpha:1.0), for: .normal)
self.view.addSubview(btnTemp)
Hope it helps
Output:

You can follow this way to achieve the outlined text.
You have to use attributed string and use setAttributedTitle property of button to get required result.
Here is the code:
Swift 4
let strokeTextAttributes: [NSAttributedStringKey : Any] = [
NSAttributedStringKey.strokeColor : UIColor.red,
NSAttributedStringKey.foregroundColor : UIColor.gray,
NSAttributedStringKey.strokeWidth : -2.0,
]
let attributedString = NSAttributedString(string: "text", attributes: strokeTextAttributes)
self.btnTemp.setAttributedTitle(attributedString, for: .normal)
Swift 3
let strokeTextAttributes = [
NSStrokeColorAttributeName : UIColor.red,
NSForegroundColorAttributeName : UIColor.gray,
NSStrokeWidthAttributeName : -2.0,
] as [String : Any]
let attributedString = NSAttributedString(string: "text", attributes: strokeTextAttributes)
self.btnTemp.setAttributedTitle(attributedString, for: .normal)
Output:

Related

something wrong with UIButton setImage

I am attempting to make my own custom Facebook login button. I am close, but for some reason when I setImage on the UIButton it still has a really large frame that is pushing the text to the right and the icon to the right as well.
What am I missing? I tried setting the frame and that did not help.
(The actual image is large, but .scaleAspetFit makes it look perfect, but I think the frame persists?)
let customFacebookButton: UIButton = {
let view = UIButton()
view.setImage(UIImage(named: "fb-logo"), for: .normal)
view.imageEdgeInsets = UIEdgeInsetsMake(8, 8, 8, 4)
view.imageView?.contentMode = .scaleAspectFit
view.backgroundColor = UIColor.init(hex: "3B5998")
view.layer.cornerRadius = 6
let mutableAttributedString = NSMutableAttributedString()
let attributes: [NSAttributedStringKey: Any] = [
NSAttributedStringKey.font : UIFont.systemFont(ofSize: 14),
NSAttributedStringKey.foregroundColor : UIColor.init(hex: "#EFEFEF") ]
let string = NSMutableAttributedString(string: "Continue with Facebook", attributes: attributes)
mutableAttributedString.append(string)
view.setAttributedTitle(mutableAttributedString, for: .normal)
return view
}()
It is because of the size of image. Reduce the size of image. It will work perfectly.
I have tested you code with two image sizes 512*512 and 80*80.
512*512
https://i.stack.imgur.com/zuRWo.png
80*80
https://i.stack.imgur.com/YvID9.png
for left align the image:
view.contentHorizontalAlignment = .left
There is no way to centre the title with left align image. Temporally you can change titleEdgeInsets to do that:
view.titleEdgeInsets = UIEdgeInsetsMake(8, 16, 8, 4)
OR
You can take a imageView to the left of button. And remove the image as part of button. then centre align the contentHorizontalAlignment.
Code:
let customFacebookButton: UIButton = {
let view = UIButton()
// view.setImage(UIImage(named: "logo"), for: .normal)
// view.imageEdgeInsets = UIEdgeInsetsMake(8, 8, 8, 4)
view.backgroundColor = UIColor.blue
view.layer.cornerRadius = 6
view.contentHorizontalAlignment = .center
let mutableAttributedString = NSMutableAttributedString()
let attributes: [NSAttributedStringKey: Any] = [
NSAttributedStringKey.font : UIFont.systemFont(ofSize: 14),
NSAttributedStringKey.foregroundColor : UIColor.white ]
let string = NSMutableAttributedString(string: "Continue with Facebook", attributes: attributes)
mutableAttributedString.append(string)
view.setAttributedTitle(mutableAttributedString, for: .normal)
return view
}()
customFacebookButton.frame = CGRect.init(x: 10, y: 20, width: 300, height: 40)
self.view.addSubview(customFacebookButton)
let imageView = UIImageView.init(frame: CGRect.init(x: 12, y: 22, width: 38, height: 38))
imageView.image = #imageLiteral(resourceName: "logo")
self.view.addSubview(imageView)
Output:

NSAttributedString on UIButton

let strNo = "2222555" // size 18, this should be bold
let remainingStr = "Call to" + "\(strNo)" + "Number"
Now, in my UIButton, say button, How to set this title "Call to 2222555 number" And i need to change the size according to device, so I have to do it by coding.
Update
I need like following image.
And need to change the size of the title by coding. Above screenshot is from iPhone 7, In iPhone 5 it become bigger and in iPad it become smaller, so i have to set the size of the title according to requirement.
Any help will be appreciable.
Thanks
I found the Answer by struggling few days. And it is quite easy.
guard
let font1 = UIFont(name: "HelveticaNeue-Bold", size: 22),
let font2 = UIFont(name: "HelveticaNeue-Medium", size: 22) else { return }
let dict1:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle.rawValue,
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white
]
let dict2:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white,
// NSFontAttributeName: UIFont.boldSystemFont(ofSize: 20)
]
let dict3:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white
]
let dict4:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white
]
let attString = NSMutableAttributedString()
attString.append(NSAttributedString(string: "Call to", attributes: dict1))
attString.append(NSAttributedString(string: " 2222555 ", attributes: dict2))
attString.append(NSAttributedString(string: " To Book Your Skip ", attributes: dict3))
attString.append(NSAttributedString(string: "NOW", attributes: dict4))
btnCall.setAttributedTitle(attString, for: .normal)
And its Working perfectly as expected.

why multiline attributedString UITextView has a different line height?

I get different line height in textView with using same font
How to set fixed line height?
I have done a lot of attempts, any help is appreciated, thanks
set NSMutableParagraphStyle lineSpacing is useless
set lineHeightMultiple is to make the difference more obvious
[
demo
import UIKit
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 1000))
let data: [String] = [
"商品名称: 巧克力",
"商品名称: 巧克力",
"商品名称: 巧克力",
"注册未成功,请验证电子邮件",
"注册未成功,请验证电子邮件",
"注册未成功,请验证电子邮件",
"测试文字, 测试文字,测试文字",
"测试文字, 测试文字,测试文字",
"测试文字, 测试文字,测试文字",
]
let textView = UITextView(frame: view.frame)
let paragraphStyle = NSMutableParagraphStyle()
let bodyFont = UIFont.systemFont(ofSize: 20.0)
paragraphStyle.lineHeightMultiple = 4
var stripe = false
// attributedString
let mutableAttributedString = NSMutableAttributedString(string: "Test TextViewAttributedString\n", attributes: [
NSFontAttributeName: UIFont.systemFont(ofSize: 18.0)
])
for text: String in data {
var backgroundColor = UIColor(red:0.13, green:0.38, blue:0.95, alpha:1.00)
if stripe {
backgroundColor = UIColor(red:0.92, green:0.12, blue:0.38, alpha:1.00)
}
let contentAttributedString = NSAttributedString(string: text, attributes: [
NSBackgroundColorAttributeName: backgroundColor,
NSParagraphStyleAttributeName: paragraphStyle,
NSFontAttributeName: bodyFont
])
mutableAttributedString.append(contentAttributedString)
stripe = !stripe
// add newline character
let newlineAttributedString = NSAttributedString(string: "\n")
mutableAttributedString.append(newlineAttributedString)
}
textView.attributedText = mutableAttributedString
view.addSubview(textView)
PlaygroundPage.current.liveView = view
I found the reason, the newlineAttributedString also need NSFontAttributeName
let newlineAttributedString = NSAttributedString(string: "\n", attributes: [
NSFontAttributeName: bodyFont
])
mutableAttributedString.appendAttributedString(newlineAttributedString)

Outline UILabel text in UILabel Subclass

I'm trying hard to find a way to simply add an outline/stroke/contour to my UILabel text. Talking about a stroke around the letters of the text not around the background of a UILabel.
I'm using swift 3 and I'd like to outline my text directly into my subclass: UILabel.
I found multiple answers suggesting this way to do things :
let strokeTextAttributes = [
NSStrokeColorAttributeName : UIColor.black,
NSForegroundColorAttributeName : UIColor.white,
NSStrokeWidthAttributeName : -4.0,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 30)
]
self.attributedText = NSMutableAttributedString(string: self.text!, attributes: strokeTextAttributes)
But the thing is that it doesn't work. My text is still the same with no outline...
Could anyone help me here ?
That would be a great thing :)
Thanks a lot. Cheers guys.
This code works for me.
Swift 3
let strokeTextAttributes = [
NSStrokeColorAttributeName : UIColor.black,
NSForegroundColorAttributeName : UIColor.white,
NSStrokeWidthAttributeName : -4.0,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 30)
] as [String : Any]
myLabel.attributedText = NSMutableAttributedString(string: "Test me i have color.", attributes: strokeTextAttributes)
Swift 4.2 & 5.1
let strokeTextAttributes = [
NSAttributedString.Key.strokeColor : UIColor.red,
NSAttributedString.Key.foregroundColor : UIColor.white,
NSAttributedString.Key.strokeWidth : -4.0,
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 30)]
as [NSAttributedString.Key : Any]
labelOutLine.attributedText = NSMutableAttributedString(string: "Your outline text", attributes: strokeTextAttributes)
#anandnimje answer converted to Swift 4.2 and wrapped it into a function:
public func stroke(font: UIFont, strokeWidth: Float, insideColor: UIColor, strokeColor: UIColor) -> [NSAttributedStringKey: Any]{
return [
NSAttributedStringKey.strokeColor : strokeColor,
NSAttributedStringKey.foregroundColor : insideColor,
NSAttributedStringKey.strokeWidth : -strokeWidth,
NSAttributedStringKey.font : font
]
}
Usage:
label.attributedText = NSMutableAttributedString(string: "Hello World",
attributes: stroke(font: UIFont(name: "SourceSansPro-Black", size: 20)!,
strokeWidth: 4, insideColor: .white, strokeColor: .black))
Make sure you have the right name for your UIFont, else it crashes. Should never be a problem if you have the right name.
Here you have class with implementation, copy and paste to playgrond for test:
class StrokedLabel: UILabel {
var strockedText: String = "" {
willSet(newValue) {
let strokeTextAttributes = [
NSStrokeColorAttributeName : UIColor.black,
NSForegroundColorAttributeName : UIColor.white,
NSStrokeWidthAttributeName : -4.0,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 30)
] as [String : Any]
let customizedText = NSMutableAttributedString(string: newValue,
attributes: strokeTextAttributes)
attributedText = customizedText
}
}
}
//////////// PLAYGROUND IMPLEMENTATION PART /////////
let text = "Stroked text"
// UILabel subclass initialization
let label = StrokedLabel(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
// simple assign String to 'strockedText' property to see the results
label.strockedText = text
label.backgroundColor = UIColor.white
label
Swift 4.2
import UIKit
class StrokedLabel: UILabel {
var strockedText: String = "" {
willSet(newValue) {
let strokeTextAttributes : [NSAttributedString.Key : Any] = [
NSAttributedString.Key.strokeColor : UIColor.black,
NSAttributedString.Key.foregroundColor : UIColor.white,
NSAttributedString.Key.strokeWidth : -4.0,
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 30)
] as [NSAttributedString.Key : Any]
let customizedText = NSMutableAttributedString(string: newValue,
attributes: strokeTextAttributes)
attributedText = customizedText
}
}
}
//////////// PLAYGROUND IMPLEMENTATION PART /////////
let text = "Stroked text"
// UILabel subclass initialization
let label = StrokedLabel(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
// simple assign String to 'strockedText' property to see the results
label.strockedText = text
label.backgroundColor = UIColor.clear
label
Maybe refactoring for this class will be welcomed, but should work for you at this form
As you can see usage is very convenient. 👾
Update to Swift 5
This answer is built on Anandnimje and J.Doe answers, and is meant to update and streamline it to make the usage clearer and simpler.
Simply use these two functions:
func outline(string:String, font:String, size:CGFloat, outlineSize:Float, textColor:UIColor, outlineColor:UIColor) -> NSMutableAttributedString {
return NSMutableAttributedString(string:string,
attributes: outlineAttributes(font: UIFont(name: font, size: size)!,
outlineSize: outlineSize, textColor: textColor, outlineColor: outlineColor))
}
func outlineAttributes(font: UIFont, outlineSize: Float, textColor: UIColor, outlineColor: UIColor) -> [NSAttributedString.Key: Any]{
return [
NSAttributedString.Key.strokeColor : outlineColor,
NSAttributedString.Key.foregroundColor : textColor,
NSAttributedString.Key.strokeWidth : -outlineSize,
NSAttributedString.Key.font : font
]
}
Then use outline with your labels as the following:
label.attributedText = outline(string: "Label Text", font: "HelveticaNeue", size: 14, outlineSize: 4, textColor: .white, outlineColor: .black)
Below is what I used in my App written in Swift 4.1
Swift 4.x
let strokeTextAttributes: [NSAttributedStringKey: Any] = [
NSAttributedStringKey.strokeColor: UIColor.black,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strokeWidth : -3.0,
NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 18)
]
Your code works for me if I set the type of the attributes dictionary, like this:
let strokeTextAttributes: [String: Any] = [
// etc...
]
Maybe that's all your missing?

Multiple UICollectionView layers on same cells

This might be a compound question, so please bear with me.
Upon finishing loading objects from Parse and populating the CollectionViewCells with them, it shows a strange bouncing animation even if I explicitly set self.collectionView?.bounces = false. Moreover, the labels are clearly drawing over each other and you can see a picture bouncing under another.
Here are the bugs I'm seeing:
https://youtu.be/q306SGM_tLE and https://youtu.be/gK9HN877nRo
This is how I handle the cells:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("itemCell", forIndexPath: indexPath) as UICollectionViewCell
let nameLabelFont = UIFont(name: "Lato-Regular", size: 13)
let priceLabelFont = UIFont(name: "Lato-Regular", size: 10)
var priceLabel = UILabel(frame: CGRectMake(0, 0, 50, 40))
var name = UILabel(frame: CGRectMake(0, 180, self.view.frame.size.width/2-5, 20))
var unitLabel = UILabel(frame: CGRectMake(0, 200, self.view.frame.size.width/2-5, 20))
var addToCartButton = UIButton(frame: CGRectMake(0, 220, 100, 30))
if self.productImageArray.count != 0 {
var image = self.productImageArray.objectAtIndex(indexPath.row) as UIImage
var imageView = UIImageView(image: image)
imageView.frame.size = CGSize(width: 187.5, height: 180)
name.attributedText = NSAttributedString(
string: self.productArray.objectAtIndex(indexPath.row).valueForKey("name") as NSString,
attributes: [NSFontAttributeName : nameLabelFont!, NSForegroundColorAttributeName : UIColor.blackColor()])
var price:Float = self.productArray.objectAtIndex(indexPath.row).valueForKey("price_tipsy") as Float
priceLabel.backgroundColor = UIColor.redColor()
priceLabel.attributedText = NSAttributedString(
string: "$\(price)",
attributes: [NSFontAttributeName : nameLabelFont!, NSForegroundColorAttributeName : UIColor.whiteColor()])
unitLabel.attributedText = NSAttributedString(
string: self.productArray.objectAtIndex(indexPath.row).valueForKey("unit") as NSString,
attributes: [NSFontAttributeName : nameLabelFont!, NSForegroundColorAttributeName : UIColor.blackColor()])
addToCartButton.setAttributedTitle(NSAttributedString(
string: "ADD TO CART",
attributes: [NSFontAttributeName : priceLabelFont!, NSForegroundColorAttributeName : UIColor.redColor()]),
forState: UIControlState.Normal)
addToCartButton.backgroundColor = UIColor.whiteColor()
addToCartButton.layer.borderColor = UIColor.redColor().CGColor
addToCartButton.layer.borderWidth = 1
addToCartButton.layer.cornerRadius = 5
cell.addSubview(imageView)
cell.addSubview(name)
cell.addSubview(priceLabel)
cell.addSubview(unitLabel)
cell.addSubview(addToCartButton)
} else {
cell.backgroundColor = UIColor.whiteColor()
}
return cell
}
EDIT
This is my UI
and its Debug View Hierarchy
after a few times of pull to refresh, Debug View Hierarchy shows multiple layers on the same cell, number of layers corresponding to number of refreshes.
EDIT 2
Here is my custom cell class:
override init(frame: CGRect) {
super.init(frame: frame)
}
func setup(frameWidth:CGFloat, image: UIImage, name: NSString, price:Float, unit:NSString) {
let nameLabelFont = UIFont(name: "Lato-Regular", size: 13)
let priceLabelFont = UIFont(name: "Lato-Regular", size: 10)
var priceLabel = UILabel(frame: CGRectMake(0, 0, 50, 40))
var nameLabel = UILabel()
var unitLabel = UILabel()
var addToCartButton = UIButton(frame: CGRectMake(0, 220, 100, 40))
nameLabel = UILabel(frame: CGRectMake(0, 180, frameWidth/2-5, 20))
unitLabel = UILabel(frame: CGRectMake(0, 200, frameWidth/2-5, 20))
nameLabel.backgroundColor = UIColor.whiteColor()
unitLabel.backgroundColor = UIColor.whiteColor()
var imageView = UIImageView(image: image)
imageView.frame.size = CGSize(width: frameWidth/2-5, height: 180)
nameLabel.attributedText = NSAttributedString(
string: name,
attributes: [NSFontAttributeName : nameLabelFont!, NSForegroundColorAttributeName : UIColor.blackColor()])
priceLabel.backgroundColor = UIColor.redColor()
priceLabel.attributedText = NSAttributedString(
string: "$\(price)",
attributes: [NSFontAttributeName : nameLabelFont!, NSForegroundColorAttributeName : UIColor.whiteColor()])
unitLabel.attributedText = NSAttributedString(
string: unit,
attributes: [NSFontAttributeName : nameLabelFont!, NSForegroundColorAttributeName : UIColor.blackColor()])
addToCartButton.setAttributedTitle(NSAttributedString(
string: "ADD TO CART",
attributes: [NSFontAttributeName : priceLabelFont!, NSForegroundColorAttributeName : UIColor.redColor()]),
forState: UIControlState.Normal)
addToCartButton.backgroundColor = UIColor.whiteColor()
addToCartButton.layer.borderColor = UIColor.redColor().CGColor
addToCartButton.layer.borderWidth = 1
addToCartButton.layer.cornerRadius = 5
self.contentView.addSubview(imageView)
self.contentView.addSubview(nameLabel)
self.contentView.addSubview(priceLabel)
self.contentView.addSubview(unitLabel)
self.contentView.addSubview(addToCartButton)
}
And in terms of UICollectView class, self.collectionView?.reloadData() is called when RefreshController is pulled, and here:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("itemCell", forIndexPath: indexPath) as ShopCell
cell.setup(self.view.frame.width, image: UIImage(), name: "AAA", price: 20.00, unit: "aaa")
cell.contentView.backgroundColor = UIColor.orangeColor()
return cell
}

Resources