实时更改视图渐变背景
Changing view gradient background in real time
我正在为一个更大的应用程序练习渐变背景,并创建了这个虚拟应用程序来简化概念。该视图具有 50/50 渐变背景和 2 行彩色按钮。
我希望用户能够通过点击上下按钮来玩转渐变的颜色,这样渐变背景会随着按钮的颜色而变化。
ViewController的代码如下:
import UIKit
class ViewController: UIViewController {
var currentUpperColor = UIColor.black
var currentLowerColor = UIColor.white
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
view.layer.insertSublayer(gradientLayer, at: 0)
}
@IBAction func upperColorPicked(_ sender: UIButton) {
currentUpperColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
currentLowerColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
但是当应用程序运行时,点击按钮时没有任何反应。我知道应该发生某种视图重绘,但我不确定如何调用它。
原因
view.layer.insertSublayer(gradientLayer, at: 0)
将始终在索引 0 处插入渐变图层。最初你创建了一个黑白图层并添加到位置 0。现在当用户选择新颜色时你创建一个新图层并将其添加到索引 0 使黑色和白色层位于索引 1。因此只有黑色和白色层将始终出现
解法:
删除旧层并添加新层。
第 1 步:
声明gradientLayer为实例变量
class ViewController: UIViewController {
var gradientLayer = CAGradientLayer()
....
}
第 2 步:
在 IBAction 中删除旧层并添加新层
@IBAction func upperColorPicked(_ sender: UIButton) {
self.gradientLayer.removeFromSuperlayer()
currentUpperColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
self.gradientLayer.removeFromSuperlayer()
currentLowerColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
方案二:(不是首选方案)
如果你想堆叠不同颜色的图层(我个人认为没有任何理由这样做,但如果那是你想要的)你可以使用
view.layer.insertSublayer(CALayer(), at: UInt32(view.layer.sublayers?.count ?? 0))
所以修改你的setGradientBackground
为
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
view.layer.insertSublayer(CALayer(), at: UInt32(view.layer.sublayers?.count ?? 0))
}
我试过你的代码,这里似乎发现它可以进行以下更改:
import UIKit
class GradientController: UIViewController {
@IBOutlet weak var vwButtonContainer: UIView!
var currentUpperColor = UIColor.black
var currentLowerColor = UIColor.white
var gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
if gradientLayer != nil {
gradientLayer.removeFromSuperlayer()
}
gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
let sublayersCount = view.layer.sublayers?.count ?? 0
view.layer.insertSublayer(gradientLayer, at: UInt32(sublayersCount))
view.layer.layoutSublayers()
view.bringSubview(toFront: vwButtonContainer)
}
@IBAction func upperColorPicked(_ sender: UIButton) {
currentUpperColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
currentLowerColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
故事板布局:
结果:
代码显示您已将 CAGradientLayer() 声明为局部变量。因此,这意味着每次您想要更新按钮时,都会将 gradientLayer 插入/添加到视图中。
层只能添加一次,并且颜色必须根据按钮操作更新。
var currentUpperColor = UIColor.black
var currentLowerColor = UIColor.white
let gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
view.layer.insertSublayer(gradientLayer, at: 0)
}
@IBAction func upperColorPicked(_ sender: UIButton) {
currentUpperColor = sender.backgroundColor!
gradientLayer.colors = [currentLowerColor.cgColor, currentUpperColor.cgColor]
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
currentLowerColor = sender.backgroundColor!
gradientLayer.colors = [currentLowerColor.cgColor, currentUpperColor.cgColor]
}
我正在为一个更大的应用程序练习渐变背景,并创建了这个虚拟应用程序来简化概念。该视图具有 50/50 渐变背景和 2 行彩色按钮。
我希望用户能够通过点击上下按钮来玩转渐变的颜色,这样渐变背景会随着按钮的颜色而变化。
ViewController的代码如下:
import UIKit
class ViewController: UIViewController {
var currentUpperColor = UIColor.black
var currentLowerColor = UIColor.white
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
view.layer.insertSublayer(gradientLayer, at: 0)
}
@IBAction func upperColorPicked(_ sender: UIButton) {
currentUpperColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
currentLowerColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
但是当应用程序运行时,点击按钮时没有任何反应。我知道应该发生某种视图重绘,但我不确定如何调用它。
原因
view.layer.insertSublayer(gradientLayer, at: 0)
将始终在索引 0 处插入渐变图层。最初你创建了一个黑白图层并添加到位置 0。现在当用户选择新颜色时你创建一个新图层并将其添加到索引 0 使黑色和白色层位于索引 1。因此只有黑色和白色层将始终出现
解法:
删除旧层并添加新层。
第 1 步:
声明gradientLayer为实例变量
class ViewController: UIViewController {
var gradientLayer = CAGradientLayer()
....
}
第 2 步:
在 IBAction 中删除旧层并添加新层
@IBAction func upperColorPicked(_ sender: UIButton) {
self.gradientLayer.removeFromSuperlayer()
currentUpperColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
self.gradientLayer.removeFromSuperlayer()
currentLowerColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
方案二:(不是首选方案)
如果你想堆叠不同颜色的图层(我个人认为没有任何理由这样做,但如果那是你想要的)你可以使用
view.layer.insertSublayer(CALayer(), at: UInt32(view.layer.sublayers?.count ?? 0))
所以修改你的setGradientBackground
为
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
view.layer.insertSublayer(CALayer(), at: UInt32(view.layer.sublayers?.count ?? 0))
}
我试过你的代码,这里似乎发现它可以进行以下更改:
import UIKit
class GradientController: UIViewController {
@IBOutlet weak var vwButtonContainer: UIView!
var currentUpperColor = UIColor.black
var currentLowerColor = UIColor.white
var gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
if gradientLayer != nil {
gradientLayer.removeFromSuperlayer()
}
gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
let sublayersCount = view.layer.sublayers?.count ?? 0
view.layer.insertSublayer(gradientLayer, at: UInt32(sublayersCount))
view.layer.layoutSublayers()
view.bringSubview(toFront: vwButtonContainer)
}
@IBAction func upperColorPicked(_ sender: UIButton) {
currentUpperColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
currentLowerColor = sender.backgroundColor!
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
故事板布局:
结果:
代码显示您已将 CAGradientLayer() 声明为局部变量。因此,这意味着每次您想要更新按钮时,都会将 gradientLayer 插入/添加到视图中。 层只能添加一次,并且颜色必须根据按钮操作更新。
var currentUpperColor = UIColor.black
var currentLowerColor = UIColor.white
let gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground(lowerColor: currentLowerColor, upperColor: currentUpperColor)
}
func setGradientBackground(lowerColor: UIColor, upperColor: UIColor) {
gradientLayer.frame = view.bounds
gradientLayer.colors = [lowerColor.cgColor, upperColor.cgColor]
gradientLayer.locations = [0.5, 1.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
view.layer.insertSublayer(gradientLayer, at: 0)
}
@IBAction func upperColorPicked(_ sender: UIButton) {
currentUpperColor = sender.backgroundColor!
gradientLayer.colors = [currentLowerColor.cgColor, currentUpperColor.cgColor]
}
@IBAction func lowerColorPicked(_ sender: UIButton) {
currentLowerColor = sender.backgroundColor!
gradientLayer.colors = [currentLowerColor.cgColor, currentUpperColor.cgColor]
}