Applying gradient to UIImage - ios

I want to apply color gradient(from top to bottom) to an image named 'newspaperImage'. This is my code using swift language.
#IBOutlet weak var newspaperImage: UIImageView!
func imageGradient(){
let newspaperview = UIView(frame: newspaperImage.frame)
let gradient = CAGradientLayer()
gradient.frame = newspaperview.bounds
let startColor = UIColor(red: 30, green: 113, blue: 79, alpha: 0).cgColor
let endColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
gradient.colors = [startColor, endColor]
newspaperview.layer.insertSublayer(gradient, at: 0)
newspaperImage.addSubview(newspaperview)
newspaperImage.bringSubviewToFront(newspaperview)
}
override func viewDidLoad() {
super.viewDidLoad()
imageGradient()
}
After running, I find it doesn't work at all. Where's the problem?

First lets start with UIColor(red:green:blue:alpha) expects the parameters to be normalised values of 0-1.
So...
let startColor = UIColor(red: 30, green: 113, blue: 79, alpha: 0).cgColor
should be
let startColor = UIColor(red: 30/255, green: 113/255, blue: 79/255, alpha: 0).cgColor
Next, I took your basic code and dumped into Playground
let image = UIImage(named: "Miho_Small.png")
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
imageView.contentMode = .scaleAspectFit
imageView.image = image
let gradient = CAGradientLayer()
gradient.frame = imageView.bounds
let startColor = UIColor(red: 30/255, green: 113/255, blue: 79/255, alpha: 0).cgColor
let endColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
gradient.colors = [startColor, endColor]
imageView.layer.insertSublayer(gradient, at: 0)
imageView
And it generated...
Okay, that's not what I was expecting, but it's not entirely unsurprising. The CALayer is been painted over the top of the image, because the image is been painted by the UIView's draw function.
Okay, so how can we fix it? With out going to the extend of making a new images and painting the gradient and image into it, you could make use of a "background" UIView, onto which the layer and UIImageView are applied...
let image = UIImage(named: "Miho_Small.png")
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
imageView.contentMode = .scaleAspectFit
imageView.image = image
imageView.backgroundColor = nil
let backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
let gradient = CAGradientLayer()
gradient.frame = backgroundView.bounds
let startColor = UIColor(red: 30/255, green: 113/255, blue: 79/255, alpha: 0).cgColor
let endColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
gradient.colors = [startColor, endColor]
backgroundView.layer.insertSublayer(gradient, at: 0)
backgroundView.addSubview(imageView)
backgroundView
which generates...
And, that's probably more along the lines of what you're trying to achieve...at a guess
:(, the two views can not be overlapped
I don't "overlap", so to speak, I add the UIImageView onto the backgroundView, which contains the CALayer. Remember, the view's frame is relative to it's parent's coordinate space.
In almost all cases, I prefer to use auto layout, and I prefer to use story boards, but those are difficult to make int an answer, so I've done it by hand for this example...
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "Miho_Small.png")
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 250, height: 250))
imageView.contentMode = .scaleAspectFit
imageView.image = image
imageView.backgroundColor = nil
let backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: 250, height: 250))
backgroundView.translatesAutoresizingMaskIntoConstraints = false
let gradient = CAGradientLayer()
gradient.frame = backgroundView.bounds
let startColor = UIColor(red: 30/255, green: 113/255, blue: 79/255, alpha: 0).cgColor
let endColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
gradient.colors = [startColor, endColor]
backgroundView.layer.insertSublayer(gradient, at: 0)
backgroundView.addSubview(imageView)
view.addSubview(backgroundView)
imageView.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: backgroundView.trailingAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: backgroundView.topAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor).isActive = true
backgroundView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
backgroundView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
backgroundView.addConstraint(NSLayoutConstraint(item: backgroundView,
attribute: .width,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 1.0,
constant: 250))
backgroundView.addConstraint(NSLayoutConstraint(item: backgroundView,
attribute: .width,
relatedBy: .equal,
toItem: backgroundView,
attribute: .height,
multiplier: 1.0,
constant: 0))
}
}
For what it's worth, you can checkout the project I used to test the code from GitHub - TestCALayerGradientAndImageOverlay

Related

auto layout and bottom line textfield

I've set constraints for these UITextField like this
But when I custom the textfield it's gone over the constraint
emailTextField.backgroundColor = UIColor.clear
emailTextField.attributedPlaceholder = NSAttributedString(string: emailTextField.placeholder!, attributes: [NSAttributedString.Key.foregroundColor: #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)])
emailTextField.borderStyle = .none
emailTextField.tintColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
let bottomLayer = CALayer()
bottomLayer.frame = CGRect(x: 0, y: 20, width: 1000, height: 0.7)
bottomLayer.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
emailTextField.layer.addSublayer(bottomLayer)
Run..
Please tell me why? Many thanks for that...
You have set CALayer width 1000. It should be width of your TextField.
Change below code:
Add below code to get updated frame of emailTextField and set the width of Layer:
emailTextField.setNeedsLayout()
emailTextField.layoutIfNeeded()
bottomLayer.frame = CGRect(x: 0, y: 20, width: emailTextField.frame.size.width, height: 0.7)
UPDATE
If you want to reuse this textField configuration you can create one function like below:
func setupTextField(textField: UITextField) {
textField.backgroundColor = UIColor.clear
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder!, attributes: [NSAttributedString.Key.foregroundColor: #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)])
textField.borderStyle = .none
textField.tintColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
textField.setNeedsLayout()
textField.layoutIfNeeded()
let bottomLayer = CALayer()
bottomLayer.frame = CGRect(x: 0, y: 20, width: textField.frame.size.width, height: 0.7)
bottomLayer.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
textField.layer.addSublayer(bottomLayer)
}
You can call above method this way:
setupTextField(textField: textField)

Layer zPosition has no effect

Three layers are given the same parent, but the zPosition value on the first layer to be added has no effect - it remains at the back. Why is this? The book I'm reading says that the position in the sublayers array can be overridden with the zPosition value.
import UIKit
import PlaygroundSupport
extension CGRect {
init(_ x:CGFloat, _ y:CGFloat, _ w:CGFloat, _ h:CGFloat) {
self.init(x:x, y:y, width:w, height:h)
}
}
let v0 = UIView(frame: CGRect(0, 0, 500, 500))
v0.backgroundColor = .white
let v1 = UIView(frame: v0.frame)
let lay1 = CALayer()
lay1.backgroundColor = UIColor(red: 1, green: 0.4, blue: 1, alpha: 1).cgColor
lay1.frame = CGRect(113, 111, 132, 194)
lay1.zPosition = 100
v1.layer.addSublayer(lay1)
let lay2 = CALayer()
lay2.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0, alpha: 1).cgColor
lay2.frame = CGRect(41, 56, 132, 194)
v1.layer.addSublayer(lay2)
let lay3 = CALayer()
lay3.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1).cgColor
lay3.frame = CGRect(43, 197, 160, 230)
v1.layer.addSublayer(lay3)
v0.addSubview(v1)
PlaygroundPage.current.liveView = v0
I think your code is working as expected. I just changed the colors of the view to
lay1.backgroundColor = UIColor.green.cgColor
lay2.backgroundColor = UIColor.blue.cgColor
lay3.backgroundColor = UIColor.red.cgColor
This is the output. You can see green view(lay1) which has z position is at the top.
Also , had fun playing with literals here:
Code works as expected in an app. Seems that it's an issue with Playground.

Swift iOS: Set Gradient Background To A UITextView?

I'm trying to apply gradient background to a UITextView object, not sure if it's possible because I get white background instead.
Here is my UIView extension:
extension UIView{
func setTextGradient(startColor:UIColor,endColor:UIColor)
{
let gradient:CAGradientLayer = CAGradientLayer()
gradient.colors = [startColor.cgColor, endColor.cgColor]
gradient.locations = [0.0 , 1.0]
gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
gradient.endPoint = CGPoint(x: 0.0, y: 1.0)
gradient.frame = self.bounds
self.layer.insertSublayer(gradient, at: 0)
}
Here where I assign gradient to the text view:
detailTxtView.translatesAutoresizingMaskIntoConstraints = false
detailTxtView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
detailTxtView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -8).isActive = true
detailTxtView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8).isActive = true
detailTxtView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.5).isActive = true
detailTxtView.setTextGradient(startColor: Constants.Colors.bluLight, endColor: Constants.Colors.silver)
// Set up text
let attributedTxt = NSMutableAttributedString(string: titleStr, attributes:[NSFontAttributeName: UIFont(name: "Jazeel-Bold", size: 24)!, NSForegroundColorAttributeName: Constants.Colors.bluLight])
attributedTxt.append(NSAttributedString(string: "\n\n\(detailStr)", attributes:[NSFontAttributeName: UIFont(name: "HacenTunisia", size: 20)!, NSForegroundColorAttributeName: Constants.Colors.aluminum]))
let txtStyle = NSMutableParagraphStyle()
txtStyle.alignment = .center
let length = attributedTxt.string.count
attributedTxt.addAttribute(NSParagraphStyleAttributeName, value: txtStyle, range: NSRange(location: 0, length: length))
detailTxtView.attributedText = attributedTxt
Here are the colors in the Constants class:
struct Colors{
static let bluDark = UIColor(colorLiteralRed: 51/255, green: 50/255, blue: 80/255, alpha: 1)
static let bluLight = UIColor(colorLiteralRed: 68/255, green: 85/255, blue: 138/255, alpha: 1)
static let greenLight = UIColor(colorLiteralRed: 200/255, green: 255/255, blue: 132/255, alpha: 1)
static let mercury = UIColor(colorLiteralRed: 235/255, green: 235/255, blue: 235/255, alpha: 1)
static let silver = UIColor(colorLiteralRed: 214/255, green: 214/255, blue: 214/255, alpha: 1)
static let magnesium = UIColor(colorLiteralRed: 192/255, green: 192/255, blue: 192/255, alpha: 1)
static let aluminum = UIColor(colorLiteralRed: 169/255, green: 169/255, blue: 169/255, alpha: 1)
static let blu2 = UIColor(colorLiteralRed: 88/255, green: 120/255, blue: 166/255, alpha: 0.2)
static let bluLighter = #colorLiteral(red: 0.451, green: 0.5569, blue: 0.8314, alpha: 1) /* #738ed4 */
}
I always get white background when using the gradient method. Appreciate any suggestions.
i think you forget location
extension UIView
{
func setGradient(startColor:UIColor,endColor:UIColor)
{
let gradient:CAGradientLayer = CAGradientLayer()
gradient.colors = [startColor.cgColor, endColor.cgColor]
gradient.locations = [0.0 , 1.0]
gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
gradient.endPoint = CGPoint(x: 0.0, y: 1.0)
gradient.frame = self.bounds
self.layer.insertSublayer(gradient, at: 0)
}
}
use
txtView.setGradient(startColor: UIColor.blue, endColor: UIColor.green)
Output:
You need to use locations property of CAGradientLayer
extension UIView{
func setGriadientBackrnd(color1: UIColor, color2: UIColor){
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [color1.cgColor, color2.cgColor]
gradientLayer.locations = [0.5 , 0.5] //here you can set percentage of color part are display betwin 0 to 1
layer.insertSublayer(gradientLayer, at: 0)
}
}
Please check your code Output
Hi Folk try like that hope you helps,
let titleStr = "Hi How are you ?"
let detailStr = "HI How UR preparation..."
gradientTextview.translatesAutoresizingMaskIntoConstraints = false
gradientTextview.bottomAnchor.constraint(equalTo:self.view.bottomAnchor).isActive = true
gradientTextview.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -8).isActive = true
gradientTextview.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 8).isActive = true
gradientTextview.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.5).isActive = true
gradientTextview.setGradient(startColor: UIColor(colorLiteralRed: 68/255, green: 85/255, blue: 138/255, alpha: 1), endColor: UIColor(colorLiteralRed: 214/255, green: 214/255, blue: 214/255, alpha: 1))
let attributedTxt = NSMutableAttributedString(string: titleStr, attributes:[NSFontAttributeName: UIFont (name: "HelveticaNeue-Bold", size: 20)! , NSForegroundColorAttributeName: UIColor(colorLiteralRed: 68/255, green: 85/255, blue: 138/255, alpha: 1)])
attributedTxt.append(NSAttributedString(string: "\n\n\(detailStr)", attributes:[NSFontAttributeName: UIFont (name: "HelveticaNeue-Bold", size: 18)! , NSForegroundColorAttributeName:UIColor(colorLiteralRed: 169/255, green: 169/255, blue: 169/255, alpha: 1)]))
let txtStyle = NSMutableParagraphStyle()
txtStyle.alignment = .center
let length = attributedTxt.string.characters.count
attributedTxt.addAttribute(NSParagraphStyleAttributeName, value: txtStyle, range: NSRange(location: 0, length: length))
gradientTextview.attributedText = attributedTxt
===============================================================
extension UIView{
func setTextGradient(startColor:UIColor,endColor:UIColor)
{
let gradient:CAGradientLayer = CAGradientLayer()
gradient.colors = [startColor.cgColor, endColor.cgColor]
gradient.locations = [0.0 , 1.0]
gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
gradient.endPoint = CGPoint(x: 0.0, y: 1.0)
gradient.frame = self.bounds
self.layer.insertSublayer(gradient, at: 0)
}
NOTE:-
instead of view you can add self.gradientTextview also...
The gradient worked when I set it after setting text attributes
detailTxtView.attributedText = attributedTxt
detailTxtView.setTextGradient(startColor: Constants.Colors.silver, endColor: Constants.Colors.bluDark)

Swift - set position

How I can set the position of the colored bar to the bottom of the screen?
I have these lines:
let ground = SKSpriteNode(color: UIColor(red: 144/255, green: 100/255,
blue: 144/255, alpha: 1.0) , size: CGSize(width: view.frame.size.width, height: 20))
ground.position = ???
addChild(ground)
This should work:
let ground = SKSpriteNode(color: UIColor(red: 144/255, green: 100/255,
blue: 144/255, alpha: 1.0) , size: CGSize(width: self.size.width, height: 20))
ground.anchorPoint = CGPoint(x: 0, y: 0)
ground.position = CGPoint(x: 0,y: 0)
addChild(ground)
Possible pitfalls:
You must reposition if an orientation change happens. Also make sure that the scene is not bigger as the screen.
Try with these lines of code:
let ground = SKSpriteNode(color: UIColor(red: 144/255, green: 100/255,
blue: 144/255, alpha: 1.0) , size: CGSize(width: view.frame.size.width, height: 20))
view.addSubview(ground)
ground.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true
ground.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true
ground.widthAnchor.constraintEqualToAnchor(view.widthAnchor).active = true
ground.heightAnchor.constraintEqualToConstant(40).active = true

Move coordinates of UIView to LLO with Swift

I would expect this code to move my newLabel from the upper left corner (ULO) to the lower left corner (LLO) but it doesn't! Apparently I need someone to hold my hand through the process of setting (0, 0) to LLO for a UIView. I've been through the documentation and read post after post on this forum but can't seem to make it happen. Disclaimer: I am trying to accomplish this in a playground in xCode 6 beta 2 so it possible it's a bug or not supported.
var newLabel = UILabel(frame: CGRectMake(0, 0, 150, 50))
newLabel.text = "This is a test"
newLabel.layer.borderWidth = 2
newLabel.textAlignment = NSTextAlignment.Center
newLabel.backgroundColor = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.8)
var myView = UIView(frame: CGRectMake(0, 0, 200, 100))
myView.layer.borderWidth = 2
myView.addSubview(newLabel)
myView.transform = CGAffineTransformMakeScale(1, -1)
myView.backgroundColor = UIColor(red: 0.8, green: 0, blue: 0, alpha: 0.8)
It seems like you haven't added Myview in main view try this code:--
var newLabel = UILabel(frame: CGRectMake(0, 0, 150, 50))
newLabel.text = "This is a test"
newLabel.layer.borderWidth = 2
newLabel.textAlignment = NSTextAlignment.Center
newLabel.backgroundColor = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.8)
var myView = UIView(frame: CGRectMake(0, 0, 200, 100))
myView.layer.borderWidth = 2
myView.addSubview(newLabel)
myView.transform = CGAffineTransformMakeScale(1, -1)
myView.backgroundColor = UIColor(red: 0.8, green: 0, blue: 0, alpha: 0.8)
self.view.addSubview(myView);
To flip the UIView it has to be a subView of another view... My issue was I was trying to flip the mainView or baseView which apparently cant be done. This make since, since it needs a graphic space to be able to draw to. Below is the code achieving what I was looking for. Also of not I also had to "flip" my label as well to return it to it upright state (again this is logical).
var newLabel = UILabel(frame: CGRectMake(0, 0, 150, 50))
newLabel.transform = CGAffineTransformMakeScale(1, -1)
newLabel.text = "This is a test"
newLabel.layer.borderWidth = 2
newLabel.textAlignment = NSTextAlignment.Center
newLabel.backgroundColor = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.8)
var subView = UIView(frame: CGRectMake(50, 50, 200, 100))
subView.transform = CGAffineTransformMakeScale(1, -1)
subView.layer.borderWidth = 2
subView.addSubview(newLabel)
subView.backgroundColor = UIColor(red: 0.8, green: 0, blue: 0, alpha: 0.8)
var myView = UIView()
myView = UIView(frame: CGRectMake(0, 0, 300, 200))
//myView.transform = CGAffineTransformMakeScale(1, -1)
myView.layer.borderWidth = 2
myView.addSubview(subView)
myView.backgroundColor = UIColor(red: 0, green: 0.8, blue: 0, alpha: 0.8)
Thanks #Mohit for your input in helping me to find the solution.

Resources