์ํ๋ switch ๋์์ธ์ด Apple์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ UISwitch์ ๋น์ทํ๋ฉด์๋ ๋ฌ๋ผ ์ปค์คํ ์ ์งํํ๋ค.
UISwitch
testSwitch.transform = CGAffineTransform(scaleX: 2, y: 0.7)
์ฒ์์๋ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ UISwitch์ ํฌ๊ธฐ๋ฅผ ์ค์ฌ ํด๊ฒฐํ๊ณ ์ ํ๋ค. ํ์ง๋ง ์ ๋ง ์ฌ์ด์ฆ๋ง ์กฐ์ ๋์ด ์ํ๋ UI๋ก ๊ตฌ์ฑํ ์ ์์๋ค.
์ดํ๋ก๋ UISwitch๋ฅผ ์ปค์คํ ํ ๋ฐฉ๋ฒ์ ์ฐพ์๋ณด์์ง๋ง ์์ ๊ฐ์ ๋ฐฉ๋ฒ๋ง ์ ์๋์ด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ผ๊ฒ ๋ค๊ณ ํ๋จํ๋ค.
UIView
switch๋ฅผ ์ํ๋ ๋์์ธ์ผ๋ก ๋ง๋ค๊ธฐ ์ํด ๊ฐ์ฅ ๊ทผ๋ณธ์ ์ธ UIView๋ฅผ ์ปค์คํ ํ๊ธฐ๋ก ํ๋ค.
๋ฐํ์ด ๋๋ bar์ ์๋๋๋ ๊ฑธ ๋ณด์ฌ์ฃผ๋ ์ํ๋ฒํผ์ผ๋ก switch๋ฅผ ๊ตฌ๋ถํด view๋ฅผ ์์ฑํ๋ค. ์ด ๋ ๊ฐ์ ๋ทฐ๋ฅผ ๊ฒน์ณ ํ๋์ switch๋ก ๋ณด์ด๊ฒ ๊ตฌ์ฑํด ์ํ๋ ๋์์ธ์ switch๋ฅผ ๋ง๋ค์๋ค.
private func configureButton(frame: CGRect){
barView = {
let view = UIView(
frame: CGRect(
x: 0,
y: 0,
width: frame.width,
height: frame.height
)
)
view.backgroundColor = isOn ? onTintColor : offTintColor
view.layer.cornerRadius = frame.height / 2
view.layer.masksToBounds = true
return view
}()
circleView = {
let view = UIView(
frame: CGRect(
x: isOn ? frame.width - (circleHorizontalMargin + (circleSize/2)) : circleHorizontalMargin + (circleSize/2),
y: circleVerticalMargin,
width: circleSize,
height: circleSize
)
)
view.backgroundColor = ColorType.white01.color
view.layer.cornerRadius = circleSize / 2
view.layer.masksToBounds = true
return view
}()
guard let circleView = circleView else { return }
guard let barView = barView else { return }
self.addSubviews(barView, circleView)
}
touchesBegan
UISwitch๊ฐ ์๋ UIView๋ฅผ ์ปค์คํ ํ๊ธฐ ๋๋ฌธ์ touch ์ด๋ฒคํธ ๋ํ ๊ฐ๋ฐ์๊ฐ ์ก์์ผ ํ๋ค. UITapGestureRecognizer๋ฅผ ์ฌ์ฉํ ๊น๋ ๊ณ ๋ฏผํ์ง๋ง, UITapGestureRecognizer๋ ํน์ ํ ๊ฐ์์ ์๊ฐ๋ฝ ํฐ์น๋ฅผ ์ธ์ํด ์ข ๋ฅ ๋ณ๋ก ์์ ์ ์งํํ๋ class๋ผ์ ์ปค์คํ Switch์์๋ ๋จ์ํ๊ฒ ํฐ์น ์ ๋ฌด์ ๋ฐ๋ผ ์์ ์ด ์ด๋ฃจ์ด์ง๋ touchesBegan(_:with:)๊ฐ ๋ ์ ํฉํ๋ค๊ณ ์๊ฐํ๋ค.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
isOn.toggle()
}
Animation
Switct์ On/Off๋ฅผ ๋์์ธ์ ์ผ๋ก ๊ตฌ๋ถํด ์ฃผ๊ธฐ ์ํด isOn ํ๋กํผํฐ๋ฅผ ์์ฑํด ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค bar์ ์ํ ๋ทฐ์ ์์์ ๋ณ๊ฒฝํ๋ค. ๊ทธ๋ฆฌ๊ณ switch๋ ์์ ๋ฟ๋ง ์๋๋ผ ์ํ๋ทฐ์ ์์ง์๋ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ ๋๋ฉ์ด์ ๋ ์ ์ฉํด์ผ ํ๋ค.
var isOn: Bool = false {
didSet {
...
}
}
์์ ๋ณ๊ฒฝ๊ณผ ์ํ ๋ทฐ์ ์ ๋๋ฉ์ด์ ๋ ์ ์งํ๋๊ธฐ๋ ํ์ง๋ง ์ํ ๋ทฐ๊ฐ ๊ณ์ ๋ฒ์ ๋ฐ๊น์ง ๋๊ฐ๋ ๋ฌธ์ ๊ฐ ์๊ฒผ๋ค.
switch๋ฅผ ์์ง ๋๋ฅด์ง ์์ ์ด๊ธฐ ์ํ์ผ๋๋ ์ํ๋ ์์น์ ์์์ง๋ง, switch๋ฅผ ํด๋ฆญ ํ๋ฉด ์ด๊ธฐ ์ํ์๋ ์ํ ๋ทฐ์ ์์น๊ฐ ๋ฌ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํ ๋นํ๋ ๊ฐ๋ ๋ฐ๊ฟ๋ณด๊ณ , constaint๋ ๋ฐ๊ฟ๋ณด๋ ๋ฑ ์ฌ๋ฌ ๋ ธ๋ ฅ์ ํ์ง๋ง ์ฌ์ ํ ์ํ๋ ์์น์ ๋ฐฐ์น๋์ง ์์๋ค.
์ค๋ ๊ณ ๋ฏผํ๋ค ๋์น๋ ๋ถ๋ถ์ด ์๋ ๊ฒ ๊ฐ์ ์ด๊ธฐ ์ํ์ ํด๋ฆญ ์ด๋ฒคํธ์์ ์ฐจ์ด๊ฐ ์๋ค๋ ์ฌ์ค์ ์ง์คํ๋ค. ์๊ณ ๋ณด๋ ์ด๊ธฐ ์ค์ ์์๋ ์ํ ๋ทฐ ์์ฒด์ x์ ๊ฐ์ ํ ๋นํ๊ณ , switch ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ํ์๋ ์ํ ๋ทฐ์ center.x์ ๊ฐ์ ํ ๋นํ๊ณ ์์๋ค.
circleView = {
let view = UIView(
frame: CGRect(
x: isOn ?
frame.width - (circleHorizontalMargin + (circleSize/2))
: circleHorizontalMargin + (circleSize/2),
...
)
)
...
}()
UIView.animate(
withDuration: animationDuration,
animations: { [weak self] in
guard let self = self else { return }
self.circleView?.center.x = self.isOn ?
frame.width - (circleHorizontalMargin + (circleSize/2))
: circleHorizontalMargin + (circleSize/2)
}
)
์ ๋๋ฉ์ด์ ์ ๋ง๋ค ๋ ์ฝ๋๋ก x์ y ์ขํ๋ฅผ ํ ๋นํด์ฃผ๋๋ฐ, ์ด๋ค ๊ฐ์ x ๋๋ y ์ขํ์ธ์ง ์ ํ์ ํด์ผ ํ๋ค๋ ๊ฑธ ๋๋ผ๊ฒ ๋ ๋ฌธ์ ์๋ค.
completion
switch On/Off์ ๋ฐ๋ผ BottomSheet ํ๋ฉด ์ ํ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํด์ผํ๋ค. ํ์ผ์ ๋ฐ๋ก ํด๋น ์ด๋ฒคํธ๋ฅผ ๊ตฌํํด ๋ผ ์๋ ์์์ง๋ง, ์ปค์คํ ๋ทฐ๋ ์ฌ์ฌ์ฉ์ฑ์ด ์ค์ํ ๊ฒ ๊ฐ์ completion ํด๋ก์ ๋ฅผ ์์ฑํด ์ด ์ปค์คํ switch๋ฅผ ์ฌ์ฉํ๋ ๊ณณ๋ง๋ค ์ํ๋ ์์ ์ ๊ตฌํํ ์ ์๋๋ก ํ๋ค.
var completion: ((_ isOn: Bool) -> Void) = { isOn in }
๊ธฐ๋ฅ์ ์ฌ์ฉ์ํํ๋ ๋ฐฉ๋ฒ์๋ DelegatePattern๋ ์๋๋ฐ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ ์ด์ ๋ ์ปค์คํ ์ ๊ท๋ชจ๊ฐ ํฌ์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค. Delegate๋ฅผ ์ฌ์ฉํ๋ Apple ํด๋์ค๋ฅผ ์๊ฐํด๋ณด๋ฉด ๋ํ์ ์ผ๋ก UICollectionView์ UITableView๊ฐ ์๋ค. ์ด ๋์ Delegate๋ฅผ ํตํด ์ฌ์ฉํ ์ ์๋ ๋ฉ์๋๊ฐ ์ ๋ง ๋ง๋ค. ํ์ง๋ง ๋ด๊ฐ ๋ง๋ ์ปค์คํ Switch๊ฐ์ ๊ฒฝ์ฐ ๋จ ํ๋์ ํด๋ก์ ๋ง ๊ตฌ์ฑํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ Delegate ํจํด์ ์ฌ์ฉํ์ง ์๊ธฐ๋ก ๊ฒฐ์ ํ๋ค. ๋ ๋ค๋ฅธ ์ด์ ๋ก๋ Delegate ํจํด์ ๋นํด ํด๋ก์ ๋ ์ง๊ด์ ์ด๊ธฐ ๋๋ฌธ์ ์ถํ ์ฌ์ฌ์ฉํ ๋ ํธํ ๊ฒ ๊ฐ์๋ค.