Remove title shadow from shadowed button - ios

I'm trying to remove shadow from my button title.
How I make shadow and corner radius:
func makeShadowRounded() {
layer.cornerRadius = 25
layer.shadowColor = UIColor.darkGray.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowRadius = 3
layer.shadowOpacity = 0.15
}
My button with white background:
let signInButton: UIButton = {
let button = UIButton()
button.layer.borderColor = UIColor.customBlue.cgColor
button.layer.borderWidth = 0.5
button.setTitle("Sign In", for: .normal)
button.setTitleColor(.customBlue, for: .normal)
button.makeShadowRounded()
return button
}()
For removing/replacing (by different color) shadow i replaced setTitle and setTitleColor by:
let shadow = NSShadow()
shadow.shadowColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
shadow.shadowOffset = CGSize(width: 0, height: 2)
shadow.shadowBlurRadius = 2
let attributedString = NSAttributedString(string: "Sign In", attributes: [
NSAttributedStringKey.shadow : shadow,
NSAttributedStringKey.foregroundColor : UIColor.customBlue
])
button.setAttributedTitle(attributedString, for: .normal)
However, It isn't working properly. What will be the better solution for that issue?

Related

How to add gradients on custom class buttons?

I am beginner in Swift/Xcode. I made a custom class in my Xcode project to handle buttons appearance (color, shape etc) that works find.
However, I can't succeed to add gradients to these buttons.
I tried the below code, but it adds a new squared gradient onto my rounded buttons instead of applying the intended gradients to those buttons. Here is what I already gave many tries:
- add this code to my custom button class (inheriting from UIButton)
- add this code to my custom button class (inheriting from UIView)
- above 2 approaches and removing the backgroungColor settings
- Using a separate function called from viewController
func ConfigMenuButtons() {
// Set button shape color
layer.cornerRadius = 37
// Set button size
translatesAutoresizingMaskIntoConstraints = false
widthAnchor.constraint(equalToConstant: 74).isActive = true
heightAnchor.constraint(equalToConstant: 74).isActive = true
// Set button text
setTitleColor(.white, for: .normal)
titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
// Set button shadow
layer.shadowRadius = 2
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowOpacity = 0.8
// Set button gradient colors
let lightBlue = UIColor(red: 122/255, green: 127/255, blue: 249/255, alpha: 1)
let darkBlue = UIColor(red: 74/255, green: 88/255, blue: 205/255, alpha: 1)
// Set gradients
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [lightBlue.cgColor, darkBlue.cgColor]
gradientLayer.locations = [0.0,1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
clipsToBounds = true
// insert gradients to button
layer.insertSublayer(gradientLayer, at: 0)
}
But I always end up with this "square shaped gradient layer" appearing onto the targeted buttons, instead of having these gradients applied directly to these buttons.
If someone had any piece of advice, it would be fantastic.
Thank you!
Here is the screen shot of the button with its partial expected effect
Here is a screenshot of fixed issue
I finally fixed the issue as below adding a CGRect size.
func ConfigMenuButtons() {
// Set button shape
layer.cornerRadius = 37
// Set button size
translatesAutoresizingMaskIntoConstraints = false
widthAnchor.constraint(equalToConstant: 74).isActive = true
heightAnchor.constraint(equalToConstant: 74).isActive = true
// Set button text
setTitleColor(.white, for: .normal)
titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
// Set button shadow
layer.shadowRadius = 2
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowOpacity = 0.8
// Set button gradient colors
let lightBlue = UIColor(red: 112/255, green: 117/255, blue: 239/255, alpha: 1)
let darkBlue = UIColor(red: 70/255, green: 84/255, blue: 201/255, alpha: 1)
// Set gradients
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [lightBlue.cgColor, darkBlue.cgColor]
gradientLayer.locations = [0.0,1.0]
gradientLayer.startPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
// THAT IS THE LINE THAT COULD FIX THE ISSUE
gradientLayer.frame = CGRect(x: 0, y: 0, width: 74, height: 74)
// Set rounded shape
gradientLayer.cornerRadius = 37
// insert gradients to button
layer.insertSublayer(gradientLayer, at: 0)
}

Setting background of game view controller

I would like to change the background of my game view controller,
However the classic self.view.backgroundColor = UIColor.red for example isn't working and I am not sure why. Could someone help me out? maybe I am missing something simple here is some code
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 35/255.0, green: 35/255.0, blue: 33/255.0, alpha: 1.0)
codedLabel.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
codedLabel.textAlignment = .center
codedLabel.text = "Box and Weave"
codedLabel.numberOfLines=1
codedLabel.textColor=UIColor.white
codedLabel.font=UIFont.systemFont(ofSize: 25)
codedLabel.backgroundColor = UIColor(red: 35/255.0, green: 35/255.0, blue: 33/255.0, alpha: 1.0)
self.view.addSubview(codedLabel)
codedLabel.translatesAutoresizingMaskIntoConstraints = false
codedLabel.heightAnchor.constraint(equalToConstant: 200).isActive = true
codedLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
codedLabel.centerXAnchor.constraint(equalTo: codedLabel.superview!.centerXAnchor).isActive = true
codedLabel.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100).isActive = true
playButton.translatesAutoresizingMaskIntoConstraints = false
playButton.backgroundColor = UIColor.white
playButton.setTitle("Play!", for: .normal)
playButton.setTitleColor(UIColor.blue, for: .normal)
playButton.titleLabel!.font = UIFont(name: "HelveticaNeue-Thin", size: 23)
playButton.titleLabel?.adjustsFontSizeToFitWidth = true
playButton.titleLabel?.minimumScaleFactor = 0.5
playButton.layer.cornerRadius = 25
self.view.addSubview(playButton)
// contraints for button
let buttonHeight = playButton.heightAnchor.constraint(equalToConstant: 50)
let buttonWidth = playButton.widthAnchor.constraint(equalToConstant: 125)
let xPlacement = playButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
let yPlacement = playButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
buttonConstraints = [buttonHeight, buttonWidth, xPlacement, yPlacement]
NSLayoutConstraint.activate(buttonConstraints)
playButton.addTarget(self, action: #selector(playButtonMethod), for: .touchUpInside)
}
This is how it looks when loaded

Swift - Apply Shadow to circular button on click

I am creating circular buttons as follow:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = GradientButton.createCircularButton(20, yPos: 20, width: 30, height: 30, circleValue:20)
button.addTarget(self, action: #selector(ViewController.didCircleBtnTouched(_:)), forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
}
}
enum ColorType {
case red, green, orange
}
class GradientButton: UIButton {
var colorType: ColorType?
public class func createCircularButton(xPos: CGFloat, yPos: CGFloat, width: CGFloat, height: CGFloat, circleValue: Int) -> GradientButton {
let button = GradientButton()
button.titleLabel!.font = UIFont(name:"HelveticaNeue", size: 12)
let buttonFrame = CGRect(x: xPos, y: yPos, width: width, height: height)
button.frame = buttonFrame
button.backgroundColor = UIColor.clearColor()
button.backgroundColor = UIColor.whiteColor()
button.layer.borderWidth = 1
button.layer.cornerRadius = 15.0
//this helps making it circular not rectangle
button.clipsToBounds = true
let red = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)//red
let green = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)//green
let orange = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)//orange
if(circleValue <= 3){
button.colorType = .green
button.layer.borderColor = UIColor.greenColor().CGColor
button.setTitleColor(green, forState: .Normal)
} else if(circleValue > 3 && circleValue <= 7){
button.colorType = .orange
button.layer.borderColor = UIColor.orangeColor().CGColor
button.setTitleColor(orange, forState: .Normal)
} else if(circleValue > 7){
button.colorType = .red
button.layer.borderColor = UIColor.redColor().CGColor
button.setTitleColor(red, forState: .Normal)
}
button.setTitle("\(circleValue)", forState: .Normal)
return button
}
}
And on click of button I am applying gradient as follow:
func didCircleBtnTouched(sender:GradientButton!){
ApplyGradientToButton(sender)
}
func ApplyGradientToButton(sender: GradientButton!){
var color1 = UIColor()
var color2 = UIColor()
if(sender.colorType == .red){
color1 = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)
color2 = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0)
}
else if(sender.colorType == .green) {
color1 = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)
color2 = UIColor(red:112/255, green:191/255, blue:65/255, alpha:1.0)
}
else if(sender.colorType == .orange) {
color1 = UIColor(red:200/255, green:110/255, blue:1/255, alpha:1.0)
color2 = UIColor(red:239/255, green:149/255, blue:26/255, alpha:1.0)
}
sender.setTitleColor(UIColor.whiteColor(), forState: .Normal)
var layer = sender.layer
layer.shadowColor = UIColor.blackColor().CGColor
layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
layer.shadowOpacity = 1.0
layer.shadowRadius = 10.0
sender.applyGradient([color2, color1], locations: [0.0, 0.90])
}
I need to display shadow around circular button on button click. But shadow is not getting displayed.
I think button.clipsToBounds = true is responsible as when I am not using this property shadow appears. Unfortunately by removing this property my circular button becomes rectangular after click which is not desirable.
Is there any way to display the shadow without changing the shape of button?
Please advise?
Current output:
Expected output:
Well you can't clip/mask to bounds and add a shadow, as it will also be clipped or masked too.
The solution is to add the shadow on a separate layer and add the image as a sublayer.
This is described in many posts here:
https://stackoverflow.com/a/25591916/312312
Swift - Problems with corner radius and drop shadow
and many many more
Just Put this code in viewController.swift file.. (Or any other file)
extension UIView {
func setRadiusWithShadow(_ radius: CGFloat? = nil) {
self.layer.cornerRadius = radius ?? self.frame.width / 2
self.layer.shadowColor = UIColor.darkGray.cgColor
self.layer.shadowOffset = CGSize(width: 1.5, height: 1.5)
self.layer.shadowRadius = 1.0
self.layer.shadowOpacity = 0.7
self.layer.masksToBounds = false
}
}
and then apply to your button..
btnEdit.setRadiusWithShadow()
Yeah... Just see the output... Everything is done...
Note: You can change CGSize(width: 1.5, height: 1.5) values as per your desired need...

Circular Gradient Buttons in Swift

I am creating circular button in the following way:
func CreateCirclularButton(xpos:CGFloat, ypos:CGFloat, Circlevalue:CGFloat, ParentView:UIView, TagValue:Int){
let button = UIButton()
var buttonFrame = EventStripe.frame
buttonFrame.origin.x = xpos
buttonFrame.origin.y = ypos
buttonFrame.size.width = 30
buttonFrame.size.height = 30
button.frame = buttonFrame
button.tag = TagValue
button.backgroundColor = UIColor.clearColor()
button.backgroundColor = UIColor.whiteColor()
button.layer.borderWidth=1
button.layer.cornerRadius=15.0
if(Circlevalue<=4){
button.layer.borderColor = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0).CGColor
button.setTitleColor(UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0), forState: UIControlState.Normal)
}else if(Circlevalue>4 && Circlevalue<=7){
button.layer.borderColor = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0).CGColor
button.setTitleColor(UIColor(red:244/255, green:179/255, blue:100/255, alpha:1.0), forState: UIControlState.Normal)
}else{
button.layer.borderColor = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0).CGColor
button.setTitleColor(UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0), forState: UIControlState.Normal)
}
let circleval = Int(Circlevalue)
button.setTitle("\(circleval)", forState: UIControlState.Normal)
button.addTarget(self, action: #selector(ViewController.didCircleBtnTouched), forControlEvents: UIControlEvents.TouchUpInside)
ParentView.addSubview(button)
}
When button is clicked, I am applying gradient to the clicked button in following way:
func didCircleBtnTouched(sender:UIButton!){
//let color = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)//red
//let color = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)//green
//let color = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)//orange
//For setting Gradient to selected circle -- unable to identify the border color from selected button
//if any how we can identify the border color
let color1 = UIColor()
let color2 = UIColor()
if(bordercolor == red){
color1 = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)
}
else if(bordercolor == Orange){
color1 = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)
color2 = UIColor(red:200/255, green:110/255, blue:1/255, alpha:1.0)
}
else if(bordercolor == red){
color1 = UIColor(red:37/255, green:200/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:16/255, green:134/255, blue:1/255, alpha:1.0)
}
sender.applyGradient([color1, color2 ], locations: [0.0, 0.90])
}
This is the extension I used for applying gradient:
extension UIView {
func applyGradient(colours: [UIColor]) -> Void {
self.applyGradient(colours, locations: nil)
}
func applyGradient(colours: [UIColor], locations: [NSNumber]?) -> Void
{
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.cornerRadius=3.0
gradient.colors = colours.map { $0.CGColor }
gradient.locations = locations
self.layer.insertSublayer(gradient, atIndex: 0)
}
}
In doing so I have two issues:
Not able to identify the color of selected button so I can apply respective gradient to that button.
When I apply gradient to button, the button becomes rectangular instead of circular.
Ideally needed:
This is how it looks now:
How can I resolve this?
For the first case you can do
button.layer.cornerRadius=15.0
//this line is what you need
button.clipsToBounds = true
For second case you can subclass the UIButton and create an ivar colorType of enum.
Then based on enum you can check what is the color of your button.
Below is the example of the code of a ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = GradientButton.createCircularButton(xPos: 100, yPos: 100, width: 30, height: 30, circleValue: 7)
button.addTarget(self, action: #selector(didCircleBtnTouched(sender:)), for: .touchUpInside)
self.view.addSubview(button)
}
func didCircleBtnTouched(sender: GradientButton!){
var color1 = UIColor()
var color2 = UIColor()
if(sender.colorType == .red){
color1 = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)
}
else if(sender.colorType == .green) {
color1 = UIColor(red:37/255, green:200/255, blue:6/255, alpha:1.0)
color2 = UIColor(red:16/255, green:134/255, blue:1/255, alpha:1.0)
}
else if(sender.colorType == .orange) {
color1 = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)
color2 = UIColor(red:200/255, green:110/255, blue:1/255, alpha:1.0)
}
sender.setTitleColor(UIColor.white, for: .normal)
sender.applyGradient(colours: [color1, color2 ], locations: [0.0, 0.90])
}
}
enum ColorType {
case red, green, orange
}
class GradientButton: UIButton {
var colorType: ColorType?
public class func createCircularButton(xPos: CGFloat, yPos: CGFloat, width: CGFloat, height: CGFloat, circleValue: Int) -> GradientButton {
let button = GradientButton()
let buttonFrame = CGRect(x: xPos, y: yPos, width: width, height: height)
button.frame = buttonFrame
button.backgroundColor = UIColor.clear
button.backgroundColor = UIColor.white
button.layer.borderWidth = 1
button.layer.cornerRadius = 15.0
//this helps making it circular not rectangle
button.clipsToBounds = true
let red = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)//red
let green = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)//green
let orange = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)//orange
if(circleValue <= 4){
button.colorType = .red
button.layer.borderColor = red.cgColor
button.setTitleColor(red, for: .normal)
} else if(circleValue > 4 && circleValue <= 7){
button.colorType = .green
button.layer.borderColor = green.cgColor
button.setTitleColor(green, for: .normal)
} else {
button.colorType = .orange
button.layer.borderColor = orange.cgColor
button.setTitleColor(orange, for: .normal)
}
button.setTitle("\(circleValue)", for: .normal)
return button
}
//keep gradient buttons here
func applyGradient(colours: [UIColor]) -> Void {
self.applyGradient(colours: colours, locations: nil)
}
func applyGradient(colours: [UIColor], locations: [NSNumber]?) -> Void
{
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.cornerRadius=3.0
gradient.colors = colours.map { $0.cgColor }
gradient.locations = locations
self.layer.insertSublayer(gradient, at: 0)
}
}
Try using this:
button.layer.cornerRadius = button.frame.size.width/2.0
button.layer.borderColor = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0).CGColor
button.backgroundColor = UIColor.whiteColor()
button.tintColor = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0).CGColor
button.layer.masksToBounds = true
Make sure your button must have same Height and Width and there is image required for Button.

UIButton sizeToFit not working

This is my code :
let button_video = UIButton(type: .custom)
button_video.frame = CGRect.zero
if subsession.VideoUrl != nil
{
button_video.frame = CGRect(x: 10, y: yAxis + 15, width: 300, height: 30)
button_video.contentEdgeInsets = UIEdgeInsets(top: 3, left: 28, bottom: 7, right: 5)
if iVideoNumber == 0
{
button_video.setTitle(String(format: "Video #%i", 1), for: .normal)
}
else
{
button_video.setTitle(String(format: "Video #%i", iVideoNumber+1), for: .normal)
}
button_video.titleLabel?.font = UIFont(name: "OpenSans-Regular", size: 15)
button_video.titleLabel?.textColor = UIColor.white
button_video.setTitleColor(UIColor.white, for: .normal)
button_video.titleLabel?.numberOfLines = 0
button_video.titleLabel?.lineBreakMode = .byWordWrapping
button_video.titleLabel?.textAlignment = .center
button_video.tag = iCount
button_video.addTarget(self, action: #selector(CourseDetailViewController.loadVideo(sender:)), for: .touchUpInside)
let btnGradient = CAGradientLayer()
btnGradient.frame = button_video.bounds
btnGradient.cornerRadius = 6
btnGradient.colors = [(UIColor(red: 174.0 / 255.0, green: 127.0 / 255.0, blue: 183.0 / 255.0, alpha: 1.0).cgColor as CGColor), (UIColor(red: 78.0 / 255.0, green: 57.0 / 255.0, blue: 96.0 / 255.0, alpha: 1.0).cgColor as CGColor)]
button_video.layer.insertSublayer(btnGradient, at: 0)
button_video.sizeToFit()
view_scrollView.addSubview(button_video)
}
}
The button however occupies the whole width of 300
You are inserting sublayer with defined frame, and inserting it in your button. So sizetofit is working its size is equal to largest layes in button which is 300 due to size of gradient layer.
If you are using multiple titles for different UIControlState, make sure to change the UIControlState before asking for sizeToFit.
In my UIButton I had to use multiple titles, one for UIControlState.normal and another for .selected state, I was expecting the result of .normal state, but the button was on .selected state.

Resources