Swift實作自定義控件之---UISwitch
需求分析
- 項目中有一個UI頁面需要用到自定義UISwitch控件,頁面如圖:
Swift實作自定義控件之---UISwitch需求分析實作自定義UISwich控件 - 這裡有兩個需求,一個是播放gif動畫:實作參考: swift 播放GIF;另外一個就是定義UISwitch.
- demo 下載下傳位址:Swift 實作自定義控件
實作自定義UISwich控件
1. 實作代碼
//
// KYLCustomSwitch.swift
//
//
// Created by yulu kong on 2019/7/16.
// Copyright © 2019 ubt. All rights reserved.
//
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?
/// 背景View的上下邊距
var bgMargin: CGFloat = 0
/// 圓點的上下邊距
var pointMargin: CGFloat = 5
}
class KYLCustomSwitch: UIControl {
/// 背景View
var bgView: UIView!
/// 開關圓點View
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")
}
// MARK: - 響應事件
@objc func stateChanges() {
isOn ? changeToOffAnimation() : changeToOnAnimation()
isOn = !isOn
valueChangedHandle?(isOn)
}
}
// MARK: - UI 邏輯
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
}
}
}
//測試1
//測試2
2. 測試代碼
//
// ViewController.swift
// kyl_swift_UIDemo
//
// Created by yulu kong on 2019/7/16.
// Copyright © 2019 yulu kong. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
var customSwitch: KYLCustomSwitch!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
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
}
}