需求分析
- 项目中有一个UI页面需要用到自定义UISwitch控件,页面如图:
- 这里有两个需求,一个是播放gif动画:实现参考: swift 播放GIF;另外一个就是定义UISwitch.
- demo 下载地址:Swift 实现自定义控件
实现自定义UISwich控件
1. 实现代码
import Foundation
import UIKit
typealias KYLSwitchValueChange = (Bool) -> ()
struct KYLSwitchConfig {
var offBgColor = UIColor(red: 0 / 255.0, green: 0 / 255.0, blue: 0 / 255.0, alpha: 0.2)
var onBgColor = UIColor(red: 70 / 255.0, green: 0 / 255.0, blue: 3 / 255.0, alpha: 1)
var offPointColor = UIColor(red: 153 / 255.0, green: 153 / 255.0, blue: 153 / 255.0, alpha: 1)
var onPointColor = UIColor(red: 158 / 255.0, green: 0 / 255.0, blue: 6 / 255.0, alpha: 1)
var offBgImage: UIImage?
var onBgImage: UIImage?
var offPointImage: UIImage?
var onPointImage: UIImage?
var bgMargin: CGFloat = 0
var pointMargin: CGFloat = 5
}
class KYLCustomSwitch: UIControl {
var bgView: UIView!
var pointView: UIView!
var config: KYLSwitchConfig!{
didSet{
updateUI()
}
}
var valueChangedHandle: KYLSwitchValueChange?
var isOn: Bool = false {
didSet{
updateUI()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
bgView = UIView()
addSubview(bgView)
bgView.layer.masksToBounds = true
bgView.isUserInteractionEnabled = false
pointView = UIView()
addSubview(pointView)
pointView.layer.masksToBounds = true
pointView.isUserInteractionEnabled = false
config = KYLSwitchConfig()
addTarget(self, action: #selector(stateChanges), for: .touchUpInside)
}
override func layoutSubviews() {
super.layoutSubviews()
bgView.frame = CGRect(x: 0, y: config.bgMargin, width: frame.width, height: frame.height - config.bgMargin * 2)
updateUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func stateChanges() {
isOn ? changeToOffAnimation() : changeToOnAnimation()
isOn = !isOn
valueChangedHandle?(isOn)
}
}
extension KYLCustomSwitch {
func updateUI() {
bgView.layer.cornerRadius = (frame.height - config.bgMargin * 2) * 0.5
bgView.backgroundColor = config.offBgColor
pointView.layer.cornerRadius = (frame.height - config.pointMargin * 2) * 0.5
pointView.backgroundColor = config.offPointColor
let pointWidth = frame.height - config.pointMargin * 2
if isOn {
pointView.frame = CGRect(x: bgView.frame.maxX - pointView.frame.width - config.pointMargin, y: config.pointMargin, width: pointWidth, height: pointWidth)
changeToOnPointViewStyle()
}
else {
pointView.frame = CGRect(x: bgView.frame.minX + config.pointMargin, y: config.pointMargin, width: pointWidth, height: pointWidth)
changeToOffPointViewStyle()
}
}
private func changeToOnAnimation() {
var frame: CGRect = pointView.frame
frame.origin.x = bgView.frame.minX + config.pointMargin
UIView.animate(withDuration: 0.25, animations: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.pointView.frame = frame
strongSelf.changeToOffPointViewStyle()
})
}
private func changeToOffAnimation() {
var frame: CGRect = pointView.frame
frame.origin.x = bgView.frame.maxX - pointView.frame.width - config.pointMargin
UIView.animate(withDuration: 0.25, animations: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.pointView.frame = frame
strongSelf.changeToOnPointViewStyle()
})
}
private func changeToOnPointViewStyle() {
bgView.backgroundColor = config.onBgColor
pointView.backgroundColor = config.onPointColor
if let img = config.onPointImage {
pointView.layer.contents = img.cgImage
}
if let bgImg = config.onBgImage {
bgView.layer.contents = bgImg.cgImage
}
}
private func changeToOffPointViewStyle() {
bgView.backgroundColor = config.offBgColor
self.pointView.backgroundColor = config.offPointColor
if let img = config.offPointImage {
pointView.layer.contents = img.cgImage
}
if let bgImg = config.offBgImage {
bgView.layer.contents = bgImg.cgImage
}
}
}
2. 测试代码
import UIKit
class ViewController: UIViewController {
var customSwitch: KYLCustomSwitch!
override func viewDidLoad() {
super.viewDidLoad()
testSwitch()
}
private func testSwitch() {
self.customSwitch = KYLCustomSwitch()
self.view.addSubview(customSwitch)
customSwitch.center = self.view.center
customSwitch.bounds = CGRect(x: 0, y: 0, width: 200, height: 60)
customSwitch.valueChangedHandle = {(isOn) in
print(isOn)
}
var config = KYLSwitchConfig()
config.offBgColor = UIColor(hex: 0xE9E9F2, alpha: 1.0)
config.onPointImage = UIImage(named: "icon_switch_turn")
config.offPointImage = UIImage(named: "icon_switch_angle")
customSwitch.config = config
}
}