2021. 8. 23. 22:42ใiOS/View
์ฝ๋์คํ์ด ๋ฉํ ๋ง์ผ๋ก ์งํํ๋ Bottom Sheet ๊ตฌํ์ ๊ธฐ๋ก์ผ๋ก ๋จ๊ฒจ๋ก๋๋ค.
์ด๊ฑธ ์ ํํ Bottom Sheet์ด๋ผ๊ณ ๋ถ๋ฅด๋์ง, ๋ชจ๋ฌ์ด๋ผ๊ณ ๋ถ๋ฌ์ผํ ์ง ์กฐ๊ธ ์ ๋งคํ ๋ถ๋ถ์ด ์์ง๋ง,
์ด ํฌ์คํธ์์ ๊ถ๊ทน์ ์ผ๋ก ๋ณด์ฌ๋๋ฆฌ๋ ค๊ณ ํ๋๊ฑด ์ด๋ฐ ๋ถ๋ถ์ ๋๋ค.
์ฐ์ ์ ๊ฐ ์ฐธ๊ณ ํ ํ๋ก์ ํธ๋ ์๋์ ๊ฐ์ต๋๋ค.
https://github.com/LucaIaco/SwipeableView
GitHub - LucaIaco/SwipeableView: A simple and easy to use view component for iOS written in Swift which allows to be expanded an
A simple and easy to use view component for iOS written in Swift which allows to be expanded and collapsed with user gestures relying on autolayouts, and supports interpolation of items which can b...
github.com
ํด๋น ํ๋ก์ ํธ๋ฅผ Stack Overflow์์ ๋ฐ๊ฒฌํ๊ณ ์ง์ ๋ค์ด๋ฐ์์ ์คํ์์ผ๋ณด๊ณ ์ฝ๋๋ฅผ ์ด๋์ ๋ ๋๋ฌ๋ณด๋,
๊ถ๊ทน์ ์ผ๋ก '์๋ก์ด ํ๋กํ ์ฝ'์ ๋ง๋ค์ด ๋์ จ๋๋ผ๊ณ ์.
ํด๋น ํ๋กํ ์ฝ ํ์ผ์ ๋ฐ์์ค์ ์ ๋ฐ๋ก ํด์ํ๋ฉด์ ์ ์ฉํ ์ ์๋ ๋ฅ๋ ฅ์ด ๋์ ๋ค๋ฉด ๊ทธ๋ ๊ฒ ํ์๋ฉด ๋๊ฒ ์ง๋ง...
์กฐ๊ธ ์ด๋ ค์ฐ์๋ค๋ฉด ์ฒจ๋ถํ ๋งํฌ์ ๋ ํ์งํ ๋ฆฌ์์ ํ๋ก์ ํธ๋ฅผ ๋ค์ด ๋ฐ์ผ์๊ณ
์ง์ ์ฝ๋์ ๋ธ๋ ์ดํฌ ํฌ์ธํธ๋ฅผ ๊ฑธ์ด๋ณด๋ฉด์ ์๋ฎฌ๋ ์ดํฐ๋ก ์ด๋์ ๋ ๋ง์ ธ๋ณด๊ณ
์ด๋ค ์ํฉ์ ์ด๋ค ํจ์๊ฐ ํธ์ถ๋๊ณ ํด๋น ํ๋กํ ์ฝ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์ง์ ๋์ผ๋ก ํ์ธํ์๋๊ฒ
ํ์ํ ๋ถ๋ถ์ ์ฐพ์์ ์ง์ ๊ตฌํํ๋๋ฐ ๋์์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ผ ์ด์ ์ง์ ๊ตฌํํ ๊ณผ์ ๊ณผ ์ฝ๋๋ฅผ ๊ฐ๋ตํ๊ฒ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์ค๋ ์ ๊ฐ ๊ตฌํํ๊ณ ์ ํ๋ ๊ฒ์, 'map picker'๋ผ๋ ๋ฒํผ์ ๋๋ฅด๋ฉด ์๋์์ ๋ชจ๋ฌ์ด ์ฌ๋ผ์ค๊ณ
๊ทธ ๋ชจ๋ฌ์ ์ ์๋๋ก ํฌ๊ธฐ๋ฅผ ๋๋ฆฌ๊ฑฐ๋ ์ค์ผ ์ ์๊ณ ,
๊ทธ ๋ชจ๋ฌ์ด ์์ง์ผ๋ 'map picker'๋ฒํผ ๋ํ ๊ฐ๊ฒฉ์ ๋ง๊ฒ ์์ง์ฌ์ฃผ๋๊ฒ๋๋ค.
0. ํด๋น ๋ ํ์งํ ๋ฆฌ์์ ํ๋ก์ ํธ ๋ค์ด ๋ฐ์ ๋ค
๋ ๊ฐ์ ํ๋กํ ์ฝ์ ์์ ์ ํ๋ก์ ํธ ํ์ผ์ ํฌํจํ๊ธฐ
ํ์ผ์ ๋ฃ์ด์ค ๋ค์ ํ๋กํ ์ฝ์ ๋ถ๋ฌ์์ค๋๋ค.
class ViewController: UIViewController, SwipeableViewProtocol {
func swipeableViewDidExpand(swipeableView: SwipeableView, previousState: Bool) {
print(2)
}
func swipeableViewDidCollapse(swipeableView: SwipeableView, previousState: Bool) {
print(3)
}
func swipeableViewDidPan(swipeableView: SwipeableView, percentage: CGFloat) {
print(1)
}
ํจ์ ์ด๋ฆ์์ ์ ์ ์๋ฏ์ด expand ํ์๋, collapseํ์๋, pan ๋์์๋ ๋ถ๋ฌ์ง๋ ํจ์์ ๋๋ค.
ํด๋น ํ๋ก์ ํธ๋ฅผ ์ ์ํ์ ๋ถ์ ํด๋น ํจ์๋ค์ด ๋ถ๋ฌ์ง๋๋ง๋ค ์ํธ์์ฉ์ ๋ง๋ค๊ณ ์ถ์ผ์ จ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ ๋ ๋ฑํ ๋ฐ์ดํฐ๋ฅผ ๋๊ฒจ์ค ํ์๋ ์๊ณ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ด์ ๋จ์ print๋ฌธ์ผ๋ก ๋์ฒดํ์ต๋๋ค.
1. Swipe View๋ผ๋ ๋ทฐ๋ฅผ ๋ทฐ ์์ ๋ฃ๊ธฐ & constraint ์ ์ํ๊ธฐ
์ Swipe View์ ๋ชจ๋ฌ ๋ทฐ๋ฅผ ์ฐ๊ฒฐํ ๊ฑด๋ฐ์,
์ ๋ทฐ๊ฐ ์์ง์ฌ์ผ ํ๊ธฐ ๋๋ฌธ์ constraint๊ฐ ์์ ์์ฌ๋ก ๋ฐ๋์ด์ผ ํฉ๋๋ค.
์ฌ๊ธฐ์ ์ ๊ฐ ์ฒจ๋ถํ ๋ ํ์งํ ๋ฆฌ์์ ์ง์ ํ๋ก์ ํธ๋ฅผ ๋ค์ด ๋ฐ๊ณ ๋ง์ ธ๋ณด์ ๋ถ๋ค์ ๋์น์ฑ๊ฒ ์ง๋ง,
ํน์ดํ๊ฒ๋ ์ 'Swipe View'์ ์ constraint(Flex Layout)๋ฅผ var๋ก ์ง์ ํด์ค๋๋ค.
(์ ๋ ์ฐธ๊ณ ํ ํ๋ก์ ํธ์ ๋ค๋ฅด๊ฒ 'map picker'๋ผ๋ ๋ฒํผ์ ๊ธฐ์ค์ผ๋ก ์ผ์์ต๋๋ค.)
2. Swipe View ์ฝ๋ ์ง๊ธฐ
2-1. ์ฒ์ ์ํ
์ ํฌ๋ ๋ฒํผ์ ๋๋ฅด๊ธฐ ์ ์๋ Swipe View๊ฐ ๋ณด์ด์ง ์๋ ์ํ์ฌ์ผ ํฉ๋๋ค.
๊ทธ๊ฑธ ๊ณ ๋ คํด์ ViewDidLoad์์๋ ๋ณด์ด์ง ์๋๋ก ์ค์ ํฉ๋๋ค.
@IBOutlet weak var swipeView: SwipeableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.swipeView.isHidden = true
self.swipeView.isUserInteractionEnabled = false
self.swipeView.delegate = self
}
์คํํด๋ณด๋ฉด ๊ทธ๋ฅ ํ๋ฒํ ํ๋์ ๋ทฐ๊ฐ ๋ํ๋ฉ๋๋ค.
๋น์ฐํฉ๋๋ค! Hidden์ true๋ก ์ค์ ํด๋์์ผ๋๊น์.
2-2. ๋ฒํผ์ ๋๋ ์ ๋(๋ชจ๋ฌ๋ทฐ ์ค์ )
๊ทธ๋ผ ์ด์ ๋ง์ฝ ๋ฒํผ์ ๋๋ ์๋ ์ค์ ํ ๊ฒ๋ค์ ํจ์๋ก ๋ฐ๋ก ๋ง๋ค์ด ์ค๋๋ค.
func childViewSettings() {
self.swipeView.isHidden = false
self.swipeView.isUserInteractionEnabled = true
self.swipeView.flexibleLayout = .init(with: self.flexLayout, end: 40.0)
//indicator ์ฌ๋ถ
self.swipeView.isSwipeIndicatorVisible = false
//๋ฅ๊ทผ ๋ชจ์๋ฆฌ ์ฌ๋ถ
self.swipeView.hasRoundedCorners = true
//์์๋๋ ํด๋๋ ๋ ๋ค child View์ interaction ๊ฐ๋ฅ
self.swipeView.childViewInteractionOnExpandedOnly = false
}
์ฌ๊ธฐ์ flexibleLayout์ด๋ผ๋ ๊ฒ ๋ณด์ด์ฃ ?
์ด๊ฑด QuickHelp๋ฑ์ผ๋ก ํ์ธํด๋ณด๋ฉด Declared In 'SwipeableView.swift'๋ผ๋ ์ค๋ช ์ ๋ณผ ์ ์์ต๋๋ค.
์ฆ, ํ๋ก์ ํธ ์์ฑ์ ๋ถ์ด ๋ง๋ค์ด ๋ ํ๋กํ ์ฝ์ ํฌํจ๋๋ ํจ์์ ๋๋ค.
์๋ ๋ฐฉ์์ ๋ณด์ํ๋ .init(with: (constraint ๋ฃ์ด์ฃผ๊ธฐ), end: (์ซ์))๋ค์.
์ ์ซ์๋ ์ง์ !! ํ ์คํธ ํด๋ณด๋ฉด ๊ธ๋ฐฉ ๋ฐ๊ฒฌํ ์ ์๋๋ฐ์, constraint ์ ์ฉ ๋ฒ์์ ๋๋ค.
์ ๋ 40์ผ๋ก ์ฃผ์์ต๋๋ค.(์ง์ ๊ตฌํํด๋ณด๊ณ ๊ฐ์ฅ ์ ํฉํ๋ค๊ณ ์๊ฐ๋๋ ์ซ์๋ฅผ ๋ฃ์ด์ฃผ์ธ์)
constraint๋ ์๊น ์ ํฌ๊ฐ ์์ ๋ง๋ค์ด์ค flexLayout์ด๊ฒ ์ฃ ?
3. ๋ฒํผ ๋๋ ์ ๋ SwipeView ๋ํ๋๊ฒ ํ๊ธฐ
์ด์ SwipeView๋ฅผ ๋ํ๋๊ฒ ํ๊ณ , ํด๋น View์์ ๋ณด์ฌ์ฃผ๊ณ ์ถ์(๊ตฌํํ๊ณ ์ถ์)
๋ทฐ๋ฅผ ์ฐ๊ฒฐํด์ค๊ฒ๋๋ค.
์ ๋ ์ด๋ฐ์์ผ๋ก ์์ฃผ ๊ฐ๋จํ๊ฒ ๊ตฌํํด๋์์ต๋๋ค.
Storyboard ID๋ฅผ "childVC"๋ผ๊ณ ๋์์ต๋๋ค.
childVC์ ๋ทฐ์ปจํธ๋กค๋ฌ ์ฝ๋๋ ๊ฐ๋จํฉ๋๋ค.
class ChildViewController: UIViewController{
weak var swipeView:SwipeableView? //์ค์
override func viewDidLoad() {
super.viewDidLoad()
}
ํ์ํ ํ ์ด๋ธ๋ทฐ๋.. ๋ฒํผ์ด ์์ผ๋ฉด ์ถ๊ฐ์ ์ผ๋ก ์ฐ๊ฒฐํด์ฃผ๋ฉด ๋๊ฒ ์ฃ ?
๊ทธ๋ผ ์ด์ ๋ค์ ์๋ ๋ทฐ์ปจํธ๋กค๋ฌ ์ฝ๋๋ก ๋์์ค๊ฒ ์ต๋๋ค.
map picker๋ผ๋ ๋ฒํผ์ ๋๋ ์๋ ์คํ๋๋ ํจ์์์ childVC๋ฅผ ๋ถ๋ฌ์์ค๊ฒ๋๋ค.
@IBAction func pickerSelected(_ sender: Any) {
//childViewController์ฐ๊ฒฐ
if let childViewController = self.storyboard?.instantiateViewController(withIdentifier:"childVC") as? ChildViewController {
childViewSettings()
// alternative way to interact with the swipeable view from within a child view
childViewController.swipeView = self.swipeView
// plug the child view into the swipeable view
self.swipeView.setChildView(childVC: childViewController, parentVC: self)
}
}
์ง์ ํ ์คํธ๋ฅผ ํด๋ณด๋ if๋ฌธ์ ๊ฑธ์ด์ฃผ์ง ์์ผ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋๋ผ๊ณ ์.
๊ทธ๋์ if๋ฌธ์ ๊ฑธ๊ณ childViewController์ ์ฐ๋ฆฌ๊ฐ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ "childVC"๋ฅผ ์ ์ฅํด์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ childViewSettings()ํจ์(๋ฐ๋ก ์์์ ๋ง๋ค์ด์ค ํจ์)๋ฅผ ๋ถ๋ฌ์์ฃผ๊ฒ ์ต๋๋ค.
๋ค์ ๋ ์ค์ ํด๋น ํ๋กํ ์ฝ์ ๋ง๋์ ๋ถ์ ํํ ๋ฆฌ์ผ๋๋ก ๋ฐ๋ผ๊ฐ์ต๋๋ค.
(์ ์ด์ ์กด์ฌํ๋ ํจ์๋ค์ด ์๋! ๊ฐ์กฐ)
4. map picker ๋ฒํผ๋ ํจ๊ป ์์ง์ด๊ฒ ํ๊ธฐ
์ 3๋ฒ๊น์ง ํ๊ณ ์คํ์ ํด ๋ณด๋ฉด ์ด์ ๋ชจ๋ฌ์ด ์ ์๊ธธ ๊ฒ์ด๊ณ , ์์ง์์๋ ๋ฌธ์ ๊ฐ ์๊ฒ ์ง๋ง
๋ฒํผ์ด ํจ๊ป ์์ง์ด์ง ์๋๋ค๋๊ฑธ ๋ฐ๊ฒฌํ์ ๊ฒ๋๋ค.
๊ทธ๋์ SwipeableItem ํ๋กํ ์ฝ์ ์ด์ฉํด์ค๊ฒ๋๋ค.
@IBOutlet weak var pickerFlexLayout: NSLayoutConstraint!
@IBOutlet weak var picker: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
.
.
.
//addAnimateableItem์ layout์ ๋ฃ๊ณ end ๊ฐ์ ์กฐ์ ํ๋ฉด์ ์์ง์ด๋๊ฑฐ ํ์ธ
self.swipeView.addAnimatableItem(SwipeableItemLayout(with: pickerFlexLayout, end: 100.0))
}
์์์ ํ ๊ฒ๊ณผ ์ ์ฌํ๊ฒ constraint๋ฅผ ์ ์ํด์ฃผ๊ณ
ํ๋กํ ์ฝ์์ ํ๋ผ๋๋๋ก ํด์ฃผ๋ฉด ๋ชจ๋ ์๋ฃ๋์์ต๋๋ค.
์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ๋ฒํผ์ด ํจ๊ป ์์ง์ด๋ ๋ชจ๋ฌ๋ทฐ bottom sheet๊ฐ ์์ฑ๋์์ต๋๋ค!!
์์ ๋ง์๋๋ ธ์ง๋ง ์ง์ !! ํด๋น ๋ ํ์งํ ๋ฆฌ์์ ํ๋ก์ ํธ๋ฅผ ๋ค์ด๋ฐ์ ํ ์คํธ ํด๋ณด๊ณ
์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ์๋ฉด์ ๊ตฌํํ์๋ ๊ฑธ ์ถ์ฒ๋๋ฆฝ๋๋ค.
(+)
cocoapod์ผ๋ก ์ค์นํ๋ ๋จ์ํ Bottom Sheet๋ ๊ตฌํํด๋ณด์๋๋ฐ,
์คํ๋ ค ํ๋กํ ์ฝ์ ์ด์ฉํ ๋ณต์กํ ์ฝ๋๊ฐ ์ข ๋ ์ปค์คํฐ๋ง์ด์งํ๊ธฐ ์ฝ๊ณ ์ ์๊ฒ ์ ๋ง์๋ ๊ฒ ๊ฐ์ต๋๋ค.