I would like to highlight text field four-side border when user clicked inside and reverting back when user's editing end. To achieve this I have following code snippet inside editingDidBegin function of my text field.
func pulseBorderColor() {
let pulseAnimation = CABasicAnimation(keyPath: "borderColor")
pulseAnimation.duration = 0.35
pulseAnimation.fromValue = UIColor.green.cgColor
pulseAnimation.toValue = UIColor(red: 252/255, green: 180/255, blue: 29/255, alpha: 1.0).cgColor
pulseAnimation.fillMode = kCAFillModeForwards
pulseAnimation.isRemovedOnCompletion = false
pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
nationalIdentityTextField.layer.sublayers![0].add(pulseAnimation,forKey: nil)
}
And to revert back my text field color I have following code inside text field editingDidEnd function
func reversePulseBorderColor() {
let pulseAnimation = CABasicAnimation(keyPath: "borderColor")
pulseAnimation.duration = 0.35
pulseAnimation.fromValue = UIColor(red: 252/255, green: 180/255, blue: 29/255, alpha: 1.0).cgColor
pulseAnimation.toValue = UIColor.green.cgColor
pulseAnimation.fillMode = kCAFillModeForwards
pulseAnimation.isRemovedOnCompletion = false
pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
nationalIdentityTextField.layer.sublayers![0].add(pulseAnimation,forKey: nil)
}
However, it could't achieve what I want. What could be the reason and how can I fix it?
I think you should set keyPath to the layer of the textfield in question rather than in the CABasicAnimation
and also you need to set borderWidth to atleast 1 for the color to be visible.
And here is what I tried to modify the code above and had it working
func pulseBorderColor() {
let pulseAnimation = CABasicAnimation(keyPath: nil)
pulseAnimation.duration = 0.35
pulseAnimation.fromValue = UIColor.green.cgColor
pulseAnimation.toValue = UIColor(red: 252/255, green: 180/255, blue: 29/255, alpha: 1.0).cgColor
pulseAnimation.fillMode = CAMediaTimingFillMode.forwards
pulseAnimation.isRemovedOnCompletion = false
pulseAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
txtInput.layer.add(pulseAnimation, forKey: "borderColor")
}
func reversePulseBorderColor() {
let pulseAnimation = CABasicAnimation(keyPath: nil)
pulseAnimation.duration = 0.35
pulseAnimation.fromValue = UIColor(red: 252/255, green: 180/255, blue: 29/255, alpha: 1.0).cgColor
pulseAnimation.toValue = UIColor.green.cgColor
pulseAnimation.fillMode = CAMediaTimingFillMode.forwards
pulseAnimation.isRemovedOnCompletion = false
pulseAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
txtInput.layer.add(pulseAnimation, forKey: "borderColor")
}
to set borderWidth you can do that by setting it in the code like this
txtInput.layer.borderWidth = 1
or in the User Defined Runtime Attributes in the identity inspector.
Hope this helps.
Related
I have encountered a problem involving setting gradients for labels and buttons. I know this question has been asked a lot, but no answer has seemed to solve my problem. Here is the screen as I want it to look:
This is my code:
#IBOutlet weak var loginButton: UIButton!
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var logoLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
loginButton.backgroundColor = UIColor.clear
let loginButtonGradient = createBlueGreenGradient(from: loginButton.bounds)
self.view.layer.insertSublayer(loginButtonGradient, at: 0)
signUpButton.backgroundColor = UIColor.clear
let signUpButtonGradient = createBlueGreenGradient(from: signUpButton.bounds)
self.view.layer.insertSublayer(signUpButtonGradient, at: 0)
logoLabel.backgroundColor = UIColor.clear
let logoLabelGradient = createBlueGreenGradient(from: logoLabel.bounds)
self.view.layer.insertSublayer(logoLabelGradient, at: 0)
loginButton.layer.cornerRadius = 100
signUpButton.layer.cornerRadius = 100
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func createBlueGreenGradient(from bounds: CGRect) -> CAGradientLayer{
let topColor = UIColor(red: 84/255, green: 183/255, blue: 211/255, alpha: 1)
let bottomColor = UIColor(red: 119/255, green: 202/255, blue: 151/255, alpha: 1)
let gradientColors: [UIColor] = [topColor, bottomColor]
let gradientLocations: [NSNumber] = [0.0, 1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations
gradientLayer.frame = bounds
return gradientLayer
}
And this is the wrong result:
Somebody please help me. I'm not sure what I'm doing wrong.
There are lots of issue with your code.
Divide the color with Float number instead of Int means it should be 255.0 not 255.
Now for colors property of CAGradientLayer you need to set array of CGColor not array of UIColor.
Also set startPoint and endPoint property of CAGradientLayer to make horizontal gradient color.
Currently you are adding this GradientLayer in your self.view instead of its specific button.
Set the cornerRadius of your button on basis of its height not with some constant 100 also after setting cornerRadius you need to also set masksToBounds property of layer to true.
Now for your logo label, you cannot set textColor as Gradient color directly what you need to do is draw the desired gradient on a UIImage and then use that UIImage to set the color pattern for your Label check this SO reference for that.
After making all this changes your code should be like.
func createBlueGreenGradient(from bounds: CGRect) -> CAGradientLayer{
let topColor = UIColor(red: 84/255.0, green: 183/255.0, blue: 211/255.0, alpha: 1).cgColor
let bottomColor = UIColor(red: 119/255.0, green: 202/255.0, blue: 151/255.0, alpha: 1).cgColor
let gradientColors = [topColor, bottomColor]
let gradientLocations: [NSNumber] = [0.0, 1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations
//Set startPoint and endPoint property also
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
gradientLayer.frame = bounds
return gradientLayer
}
Now set gradientLayer in viewDidLoad this way.
override func viewDidLoad() {
super.viewDidLoad()
let loginButtonGradient = createBlueGreenGradient(from: loginButton.bounds)
self.loginButton.layer.insertSublayer(loginButtonGradient, at: 0)
let signUpButtonGradient = createBlueGreenGradient(from: signUpButton.bounds)
self.signUpButton.layer.insertSublayer(signUpButtonGradient, at: 0)
loginButton.layer.cornerRadius = loginButton.frame.size.height / 2
loginButton.layer.masksToBounds = true
signUpButton.layer.cornerRadius = signUpButton.frame.size.height / 2
signUpButton.layer.masksToBounds = true
}
Your method like this:
func createBlueGreenGradient(from bounds: CGRect) -> CAGradientLayer{
let topColor = UIColor(red: 84/255, green: 183/255, blue: 211/255, alpha: 1).cgColor
let bottomColor = UIColor(red: 119/255, green: 202/255, blue: 151/255, alpha: 1).cgColor
let gradientColors = [topColor, bottomColor]
let gradientLocations: [NSNumber] = [0.0, 1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations
gradientLayer.frame = bounds
return gradientLayer
}
Oh my goodness I had the same problem, but played around with it. This is caused because you didnt add .cgcolor. For example :
let topColor = UIColor(red: 84/255, green: 183/255, blue: 211/255, alpha: 1).cgColor
let bottomColor = UIColor(red: 119/255, green: 202/255, blue: 151/255, alpha: 1).cgColor
let gradientColors = [topColor, bottomColor]
Let me know if it works.
I was developing in Swift 3 and I had a little problem with a UIButton. I will try to explain my problem. First I created my UIButton:
let Button: UIButton = {
let button = UIButton(type: .system)
button.setBackgroundImage(UIImage(named: "button"), for: .normal)
button.layer.borderWidth = 2
button.layer.borderColor = UIColor(red: 0, green: 0, blue: 80/255, alpha: 1).cgColor
button.layer.cornerRadius = 10
//button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
After in the viewDidLoad I implemented the action:
button.addTarget(self, action: #selector(buttonUnpressed), for: .touchUpInside)
In which "favButtonPressed" is a function with no importance
The problem is when I touch the button the border doesn't get unhighlighted as the image or the text does. It is a detail of little importance but quite annoying.
I have tried changing the alpha value when pressed and re-change it but the problem is i dont know how to animate it to make the animation for 2 seconds (the next line of code doesnt work, it does change the color but not during 2 seconds):
func buttonUnpressed(){
UIButton.animate(withDuration: 2, animations: {
self.button.layer.borderColor = UIColor(red: 0, green: 0, blue: 80/255, alpha: 1).cgColor
})
}
The question; is there any way of adding the border to the UIButton "total behavior" of highlighting and unhighlighting when pressed?
Excuse me for my english if there are some expression or gramatical faults.
EDIT
I tried with this function:
func buttonUnpressed(){
button.alpha = 0.2
UIButton.animate(withDuration: 1) {
self.button.alpha = 1
}
button.layer.borderColor = UIColor(red: 0, green: 0, blue: 80/255, alpha: 1).cgColor
}
there is a weird highlight of the image but now it works more or less.
You can use this extension to animate change of border color:
extension UIButton {
func borderColorAnimation(from: CGColor, to: CGColor, duration: CFTimeInterval) {
let animation = CABasicAnimation(keyPath: "borderColor")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.fromValue = from
animation.toValue = to
animation.duration = duration
self.layer.add(animation, forKey: "borderColor")
self.layer.borderColor = to
}
}
Like this:
let fromColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
let toColor = UIColor(red: 255, green: 0, blue: 0, alpha: 1).cgColor
self.button.borderColorAnimation(from: fromColor, to: toColor, duration: 200)
I did find the final answer.
Thanks to krotov who tried to help!
class BorderButton: UIButton {
override init(frame: CGRect){
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var colorPast: Bool = true
override var isHighlighted: Bool {
didSet {
if isHighlighted && colorPast {
borderDissapear(highlighted: isHighlighted)
colorPast = false
} else if !isHighlighted && !colorPast {
borderDissapear(highlighted: isHighlighted)
colorPast = true
}
}
}
func borderDissapear (highlighted: Bool) {
let animation = CABasicAnimation(keyPath: "borderColor")
animation.duration = 0.1
animation.autoreverses = false
animation.repeatCount = 1
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
if highlighted {
animation.fromValue = self.layer.borderColor?.copy(alpha: 1)
animation.toValue = self.layer.borderColor?.copy(alpha: 0.3)
} else if !highlighted {
animation.fromValue = self.layer.borderColor?.copy(alpha: 0.3)
animation.toValue = self.layer.borderColor?.copy(alpha: 1)
}
self.layer.add(animation, forKey: "borderColor")
}
}
I have an 'attach node' that has 2 child nodes that are Blender models. I have added a third node to this attach node that is a SCNCone. For some reason, I can't change the color of the cone node, only the transparency. I can't seem to see anything wrong with the code, but during runtime the cone is always a black color no matter what color I set it to.
let coneGeo = SCNCone(topRadius: 0.1, bottomRadius: 0.7, height: 4)
let coneMaterial = SCNMaterial()
coneMaterial.diffuse.contents = UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2)
coneGeo.materials = [coneMaterial]
let coneNode = SCNNode(geometry: coneGeo)
coneNode.position = SCNVector3(0, -1.5, 0)
coneNode.name = "coneNode"
AttachNode.addChildNode(coneNode)
Replace coneMaterial.diffuse.contents = UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2) with coneGeo.geometry?.firstMaterial?.diffuse.contents.diffuse.contents = UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2). Instead of changing the cone's material color without geometry, you have to access it's material color through it's geometry parameter.
coneGeo.materials = [coneMaterial]
This will also work. I tested your code by adding the cone node to an empty scene.
I just get a black screen.
But if I change the alpha value to say 0.5, this is what I get.
The code.
override func viewDidLoad()
{
super.viewDidLoad()
// create a new scene
let scene = SCNScene()
let coneGeo = SCNCone(topRadius: 0.1, bottomRadius: 0.7, height: 4)
let coneMaterial = SCNMaterial()
coneMaterial.diffuse.contents = UIColor(red: 255.0 / 255.0,
green: 108.0 / 255.0,
blue: 91.0 / 255.0, alpha: 0.5)
coneGeo.materials = [coneMaterial]
let coneNode = SCNNode(geometry
: coneGeo)
coneNode.position = SCNVector3(0, -1.5, 0)
coneNode.name = "coneNode"
scene.rootNode.addChildNode(coneNode)
// retrieve the SCNView
let scnView = self.view as! SCNView
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
// configure the view
scnView.backgroundColor = UIColor.black
}
So I would say, check your alpha value in UIColor(red: 255.0/255.0, green: 108.0/255.0, blue: 91.0/255.0, alpha: 0.2)
I am trying to achieve a gradient color on a UIView or button with two color black which fades out to clear color or white color (please see image).
I have tried using different combinations of white color, clear color; experimenting with alpha as well. I have also set the locations property as can be seen in below code but I am not able to achieve desired results.
Can anyone tell me where I am wrong. :)
let colorClear = UIColor.clearColor().CGColor
let colorLeft = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.9).CGColor
let colorRight = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).CGColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorLeft, colorRight]
gradientLayer.locations = [ 0.1, 0.9]
gradientLayer.frame = self.createAccountView.bounds
gradientLayer.startPoint = CGPoint(x:0.0, y:0.5)
gradientLayer.endPoint = CGPoint(x:1.0, y:0.5)
createAccountView.layer.addSublayer(gradientLayer)
createAccountView.layer.masksToBounds = true
The desired result is the one in which black color transitions to a faded one.
I have already tried setting both colors as black and the color1 with an alpha.
I have already tried commenting locations property.
you should set gradientLayer.frame in viewDidLayoutSubviews().
Like this:
class ViewController: UIViewController {
let gradientLayer = CAGradientLayer()
override func viewDidLoad() {
let colorClear = UIColor.clearColor().CGColor
let colorLeft = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.9).CGColor
let colorRight = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).CGColor
self.gradientLayer.colors = [colorLeft, colorRight]
self.gradientLayer.locations = [ 0.1, 0.9]
self.gradientLayer.startPoint = CGPoint(x:0.0, y:0.5)
self.gradientLayer.endPoint = CGPoint(x:1.0, y:0.5)
createAccountView.layer.addSublayer(self.gradientLayer)
createAccountView.layer.masksToBounds = true
}
override viewDidLayoutSubviews() {
super.viewDidLayoutSubViews()
self.gradientLayer.frame = self.createAccountView.bounds
}
I am trying to add gradient background to my labels (which are connected from UserInterface) , but it hides label's text.
This is my code so far:
//MARK: Grdient label func
func gradientBackground(label:UILabel){
let four = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1).CGColor
let three = UIColor.whiteColor().CGColor
let two = UIColor.whiteColor().CGColor
let one = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1).CGColor
let gradient = CAGradientLayer()
gradient.locations = [0.0,0.2,0.8,1.0]
gradient.colors = [one,two,three,four]
gradient.startPoint = CGPointMake(0.0, 0.5)
gradient.endPoint = CGPointMake(1.0, 0.5)
gradient.frame = CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, label.bounds.height)
let backView = UIView()
backView.frame = CGRectMake(0, 0, label.bounds.width, label.bounds.height)
backView.backgroundColor = UIColor.clearColor()
backView.layer.insertSublayer(gradient, atIndex: 0)
label.insertSubview(backView, atIndex: 0)
label.backgroundColor = UIColor.clearColor()
label.textColor = UIColor.blackColor()
label.tintColor = UIColor.blackColor()
}
Then I use the function like this:
override func viewDidLoad() {
super.viewDidLoad()
//MARK: Gradient background
gradientBackground(firstLabel)
}
My question is, what is wrong?
Thank you.
check if it is your label "firstLabel" visible
check if your func draw img under the text