Slide SideView 표시하기
오늘은 좌우 Gesture로 SideView가 나왔다가 들어가는 화면을 구성해 보자.
아래 동영상은 최종 결과 이다.
=========================================================
1. 화면 구성을 위한 각종 ViewController와 View 설정
2. 초기 화면을 MainViewController로 설정
3. SideView와 MainView 동시 표현
4. MainView에서 sideView toggle하기
5. Animation 효과 넣기 및 mainView 그림자 처리하기
6. SideView에서 항목 선택할 경우 MainView의 BackGround Color 변경
7. Gesture로 sideView toggle하기
=========================================================
1. 화면 구성을 위한 각종 ViewController와 View 설정
우선 화면 구성을 아래 그림과 같이 하자. Main화면을 나타내는 MainViewController, SideView를 나타내는 SideTableViewController, 그리고 이 두 View를 관리하는 ContentViewController 이렇게 세가지를 준비하였다. 다만 MainViewController에는 Navigation Controller를 임베디드 하였다 (Editor▶︎Embed In▶︎Navigation Controller). 이때 ContentViewController에서 따로 segue를 만들지 않는다. 그리고 Navigation Controller의 Identity 속성중 Storyboard ID에는 "mainView", SideTableViewController의 Identity 속성중 Storyboard ID에는 "sideView"라고 설정한다. 추가로 실행했을 때 View를 알아보기 쉽게 하기 위해 MainViewController에는 background Color를 노란색으로, 중앙에 "MainView"라고 Label을 추가하였다.
2. 초기 화면을 MainViewController로 설정
초기 화면은 Storyboard상에 ContentViewController로 나와 있다 하지만 이 ContentViewController는 어느 view를 화면에 나타낼지에 대해 결정하는 곳으로 실제 view에 나타나지 않게 할 것이다. 다만 ContentViewController에 code로 각 View(main,side)를 어떻게 나타낼지에 대해 결정한다. 우선 하기와 같이 ContentViewController에 code를 추가한다.
(1) 나타낼 ViewController들을 변수로 설정 한다.View는 현재 mainView로 NavigationController와 sideView로 SideTableViewController가 있어서 각각 optional variable로 작성한다. 만약 view를 3개를 등록한다면 그 view에 맞는 ViewController를 변수로 설정하면 된다.
아래 동영상은 최종 결과 이다.
=========================================================
1. 화면 구성을 위한 각종 ViewController와 View 설정
2. 초기 화면을 MainViewController로 설정
3. SideView와 MainView 동시 표현
4. MainView에서 sideView toggle하기
5. Animation 효과 넣기 및 mainView 그림자 처리하기
6. SideView에서 항목 선택할 경우 MainView의 BackGround Color 변경
7. Gesture로 sideView toggle하기
=========================================================
1. 화면 구성을 위한 각종 ViewController와 View 설정
우선 화면 구성을 아래 그림과 같이 하자. Main화면을 나타내는 MainViewController, SideView를 나타내는 SideTableViewController, 그리고 이 두 View를 관리하는 ContentViewController 이렇게 세가지를 준비하였다. 다만 MainViewController에는 Navigation Controller를 임베디드 하였다 (Editor▶︎Embed In▶︎Navigation Controller). 이때 ContentViewController에서 따로 segue를 만들지 않는다. 그리고 Navigation Controller의 Identity 속성중 Storyboard ID에는 "mainView", SideTableViewController의 Identity 속성중 Storyboard ID에는 "sideView"라고 설정한다. 추가로 실행했을 때 View를 알아보기 쉽게 하기 위해 MainViewController에는 background Color를 노란색으로, 중앙에 "MainView"라고 Label을 추가하였다.
2. 초기 화면을 MainViewController로 설정
초기 화면은 Storyboard상에 ContentViewController로 나와 있다 하지만 이 ContentViewController는 어느 view를 화면에 나타낼지에 대해 결정하는 곳으로 실제 view에 나타나지 않게 할 것이다. 다만 ContentViewController에 code로 각 View(main,side)를 어떻게 나타낼지에 대해 결정한다. 우선 하기와 같이 ContentViewController에 code를 추가한다.
class ContentViewController: UIViewController {
// (1)
var naviView: UINavigationController?
var sideView: SideTableViewController?
var mainView: MainViewController?
override func viewDidLoad() {
super.viewDidLoad()
setUpMainView()
}
func setUpMainView() {
// (2)
naviView = storyboard?.instantiateViewController(withIdentifier: "mainView") as? UINavigationController
self.addChildViewController(naviView!) // 자식view로 navigationController를 등록함.
self.view.addSubview((naviView?.view)!) // navigationController view를 화면에 표시함.
// (3)
naviView?.didMove(toParentViewController: self) // navigationController에게 ContentViewController가 상위ViewController라고 등록함.
// (4)
mainView = naviView?.viewControllers[0] as? MainViewController
}
}
| cs |
(2) setUpMainView 함수로 mainViewController를 초기 화면에 나타날 수 있게 설정한다. 이때 storyboard에서 설정해둔 Storyboard ID 속성을 이용한다. 그리고 ContentViewController에 naviView를 자식 viewController로 등록하고 naviView의 View를 subView로 등록한다. viewController와 view는 독립적이라 이렇게 따로 등록을 해야 하는거 같다. 이때 naviView를 등록하면 자연스럽게 자식뷰인 mainView가 나타나게 된다.
(3) contentViewController에 naviView를 자식 viewController로 등록했듯이 naviView에 ContentViewController를 parentViewController로 등록을 한다.
실행하면 아래와 같이 MainViewController가 표현된다.
(4) mainView는 naviView의 첫번째 자식뷰 이므로 viewControllers[0]으로 등록할 수 있다. 이때 naviView가 아닌 mainView를 ContentView의 자식뷰로 바로 등록을 해도 되지만 Navigation Bar가 나타나지 않는다. 왜냐하면 UINavigationController이 아닌 UIViewController이므로 Navigation Bar가 나올 수 없게 된다.
3. SideView와 MainView 동시 표현
SideView와 MainView를 동시에 표현해 보자. 2번처럼 sideView를 자식 view로 등록하고 ContentView에 두 자식 View를 addSubview로 등록해 주기만 하면 된다.
class ContentViewController: UIViewController {
var naviView: UINavigationController?
var sideView: UITableViewController?
var mainView: MainViewController?
// (1)
var sideViewWidth: CGFloat {
return self.view.frame.width * 2 / 3
}
override func viewDidLoad() {
super.viewDidLoad()
setUpMainView()
openOrCloseSideView()
}
func setUpMainView() {
....
}
func openOrCloseSideView() {
// (2)
if sideView == nil {
sideView = storyboard?.instantiateViewController(withIdentifier: "sideView") as? SideTableViewController
self.addChildViewController(sideView!)
self.view.addSubview((sideView?.view)!)
sideView?.didMove(toParentViewController: self)
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}else {
sideView?.view.removeFromSuperview()
sideView = nil
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}
}
}
| cs |
class SideTableViewController: UITableViewController {
//(3)
var colorOfMainView:[(String,UIColor)] = [("Red",UIColor.red), ("Blue",UIColor.blue), ("White",UIColor.white), ("Cyan",UIColor.cyan), ("Green",UIColor.green)]
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return colorOfMainView.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = colorOfMainView[indexPath.row].0
return cell
}
}
| cs |
(1) sideViewWidth를 전체 view width의 2/3으로 설정한다.
(2) sideView가 nil이라면 sideView를 2번처럼 자식으로 등록하고 view에 등록하여 준다. 그리고 나서 mainView의 크기 및 위치, sideView의 크기 및 위치를 설정하여 전체 view에서 각각의 subView가 어떻게 표현될지 결정해 준다. 만약 sideView가 nil이 아니라면 view에서 삭제해 주고 sideView를 nil로 만들어 준다.
==> 이렇게 하면 openOrCloseSideView 함수를 실행할 때마다 open과 close가 번갈아 실행될 것이다.
(3) SideTableViewController에는 색을 나타내는 String과 UIColor를 Array로 만들었다. 향후 SideTableView에서 색을 선택하면 mainView 바탕색을 설정할 수 있도록 하기 위함이다.
실행하면 아래와 같다.
4. MainView에서 sideView toggle하기
이제 실제 MainViewController에서 SideTableViewController를 toggle하여 보자. 이를 위해 Storyboard에서 MainView에 Toggle 스위치로 "Menu"를 추가하고 MainViewController와 IBOutlet으로 연결하자(toggleSideView). 그리고 하기와 같이 code를 작성한다.
class MainViewController: UIViewController {
// (1)
var delegate: ContentViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
// (2)
@IBAction func toggleSideView(_ sender: UIBarButtonItem) {
delegate?.openOrCloseSideView()
}
}
| cs |
class ContentViewController: UIViewController {
.....
func setUpMainView() {
naviView = storyboard?.instantiateViewController(withIdentifier: "mainView") as? UINavigationController
self.addChildViewController(naviView!) // 자식view로 navigationController를 등록함.
self.view.addSubview((naviView?.view)!) // navigationController view를 화면에 표시함.
naviView?.didMove(toParentViewController: self) // navigationController에게 ContentViewController가 상위ViewController라고 등록함.
mainView = naviView?.viewControllers[0] as? MainViewController
// (3)
let mainView = naviView?.viewControllers[0] as! MainViewController
mainView.delegate = self
}
func openOrCloseSideView() {
.....
}
}
| cs |
(1) delegate 변수 설정한다. MainViewController에서는 sideView를 toggle할 능력이 없다. SideView가 나타나거나 사라지게 하는건 ContentViewController만 할 수 있다. 하여 MainViewController에서는 이런 일을 위임(delegate)하기 위해 delegate 변수를 ContentViewController type으로 설정한다.
(2) delegate가 ContentViewController이므로 sideView를 toggle하기 위해 ContentViewController에서 정의된 toggle용 함수를 호출한다.
(3) ContentViewController에서는 초기 setting할 때 자신(self)이 MainViewController의 delegate 변수 임을 지정하여야 한다. 이때 naviView는 UINavigationController이므로 최초의 자식 view인 MainViewController를 가져오기 위해 naviView?.viewControllers[0]를 적용한다.
이렇게 함으로써 MainView와 ContentView와의 연결이 형성되어 MainView에서 toggle button을 눌렀을 때, ContentViewController에서 SideView의 open과 close를 실행할 수 있다.
아래와 같이 실행된다.
5. Animation 효과 넣기 및 mainView 그림자 처리하기
자 toggle했을 때 animation 효과를 넣어보자.
class ContentViewController: UIViewController {
....
override func viewDidLoad() {
....
}
func setUpMainView() {
....
//(1)
naviView?.view.layer.shadowOffset = CGSize(width: -2, height: -2)
naviView?.view.layer.shadowColor = UIColor.black.cgColor
naviView?.view.layer.shadowOpacity = 0.8
}
func openOrCloseSideView() {
if sideView == nil {
sideView = storyboard?.instantiateViewController(withIdentifier: "sideView") as? SideTableViewController
self.addChildViewController(sideView!)
self.view.addSubview((sideView?.view)!)
sideView?.didMove(toParentViewController: self)
//(2)
self.view.bringSubview(toFront: (self.naviView?.view)!)
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}, completion: nil)
}else {
//(3)
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}) { (result) in
self.sideView?.view.removeFromSuperview()
self.sideView = nil
}
}
}
}
| cs |
(1) MainView에서 toggle할 때 MainView가 SideView 위에 떠있는 효과를 주기 위해 naviView 외곽의 음영 처리를 한다. naviView의 효과를 주면 자동 MainView에 동일하게 나타나게 된다.
(2) open할 때 animation 효과를 주기 위해 UIView.animate methode를 적용한다. 이 때 주위할점은 sideView가 naviView 이후에 설정되므로 ContentView의 자식view로 sideView가 맨처음으로 올라온다. 하여 animation효과를 주게 되면 sideView가 전체화면으로 시작하게 되어 원하지 않는 효과가 발생한다. 그렇게 때문에 ContentView의 맨처음 자식 view로 naviView를 설정해야 하는데 bringSubview가 이역할을 하게 된다.
(3) close 하게 되면 open할 때 처럼 animate methode를 적용하면 된다. 이 때 close가 실행되고 나서 view가 없어져야 하기 때문에 completion handler에 sideView를 제거 및 nil 적용을 하면 된다.
실행하게 되면 아래 동영상과 같다.
6. SideView에서 항목 선택할 경우 MainView의 BackGround Color 변경
이번에는 sideView table에 있는 항목(color)을 선택할 경우 mainView의 바탕화면이 선택된 color로 변경되게 만들어 보자. 이때 앞에서 나온거 처럼 delegate를 사용한다.
class MainViewController: UIViewController {
var delegate: ContentViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func toggleSideView(_ sender: UIBarButtonItem) {
delegate?.openOrCloseSideView()
}
// (1)
func changeBackGroundColor(color: UIColor) {
self.view.backgroundColor = color
}
}
| cs |
class SideTableViewController: UITableViewController {
// (2)
var delegate: MainViewController?
var colorOfMainView:[(String,UIColor)] = [("Red",UIColor.red), ("Blue",UIColor.blue), ("White",UIColor.white), ("Cyan",UIColor.cyan), ("Green",UIColor.green)]
....
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.changeBackGroundColor(color: colorOfMainView[indexPath.row].1)
}
}
| cs |
class ContentViewController: UIViewController {
....
func setUpMainView() {
....
}
func openOrCloseSideView() {
if sideView == nil {
sideView = storyboard?.instantiateViewController(withIdentifier: "sideView") as? SideTableViewController
self.addChildViewController(sideView!)
self.view.addSubview((sideView?.view)!)
sideView?.didMove(toParentViewController: self)
self.view.bringSubview(toFront: (self.naviView?.view)!)
// (3)
sideView?.delegate = mainView
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}, completion: nil)
}else {
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}) { (result) in
self.sideView?.view.removeFromSuperview()
self.sideView = nil
}
}
}
}
| cs |
(1) 먼저 MainViewController에 changeBackGroundColor 함수를 작성한다. UIColor를 인자로 받아 바탕화면 색을 변경하는 함수이다. MainViewController에서는 이렇게 함수만 작성하는 것으로 끝이다. 왜냐하면 인자를 넣고 함수를 호출하는건 sideView에서 해야 하기 때문이다.
(2) SideTableViewController에서는 이렇게 delegate 변수만 선언을 한다. 여기서 앞에서 처럼 delegate = self 라고 할 수 없는것이 SideTableViewController의 instance는 여기가 아닌 ContentViewController에서 생성 및 소멸이 되기 때문이다. 그리고 cell이 선택되었을 때 delegate 함수를 넣어 color가 바뀌게 하였다.
(3) sideView는 여기(ContentViewController)에서 toggle로 생성 및 사라지게 된다. 그러므로 여기서 sideView가 생성이 되면 sideView의 delegate는 mainView라고 알려줘야 sideView와 mainView간 관계가 성립이 된다.
7. Gesture로 sideView toggle하기
자 이번에는 drag gesture로 sideView를 열고 닫아 보자. 이를 위해 storyboard상 MainViewController에 Pan Gesture Recognizer를 추가한다.
그리고 하기와 같이 작성한다.
class ContentViewController: UIViewController {
....
// (1)
var isSideViewOn: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
setUpMainView()
}
func setUpMainView() {
....
}
func openOrCloseSideView() {
if sideView == nil {
....
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}) { (result) in
// (2)
self.isSideViewOn = true
}
}else {
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}) { (result) in
self.sideView?.view.removeFromSuperview()
self.sideView = nil
// (2)
self.isSideViewOn = false
}
}
}
// (3)
func dragSideView(xDragAmount: CGFloat, isEnded: Bool) {
....
}
}
| cs |
(1) 우선 sideView과 on되었는지 off 되었는지 Bool 변수로 정의하였다.
(2) mainView에서 toggle button으로 toggle 되던 methode에 (1)에서 정의한 Bool 변수에 값을 대입해 준다.
(3) MainViewController과 연결될 함수로 mainView에서 drag하면 x방향으로 얼마나 drag 하였는지와 touch가 끝나 drag가 끝났는지에 대한 정보를 입력받아서 mainView와 sideView를 제어할 함수를 정의한다. 상세 정의는 아래에 정의하겠다.
(2) mainView에서 toggle button으로 toggle 되던 methode에 (1)에서 정의한 Bool 변수에 값을 대입해 준다.
(3) MainViewController과 연결될 함수로 mainView에서 drag하면 x방향으로 얼마나 drag 하였는지와 touch가 끝나 drag가 끝났는지에 대한 정보를 입력받아서 mainView와 sideView를 제어할 함수를 정의한다. 상세 정의는 아래에 정의하겠다.
class MainViewController: UIViewController {
var delegate: ContentViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func toggleSideView(_ sender: UIBarButtonItem) {
delegate?.openOrCloseSideView()
}
func changeBackGroundColor(color: UIColor) {
self.view.backgroundColor = color
}
// (4)
@IBAction func dragGesture(_ sender: UIPanGestureRecognizer) {
if sender.state == .began || sender.state == .changed {
delegate?.dragSideView(xDragAmount: sender.translation(in: self.view).x, isEnded: false)
}else if sender.state == .ended {
delegate?.dragSideView(xDragAmount: sender.translation(in: self.view).x, isEnded: true)
}
}
}
| cs |
(4) pan gesture recognizer와 연결된 @IBAction 함수이다. (3)에서 정의한 methode(dragSideView)를 사용하는 곳으로 drag의 상태가 시작 및 drag중일때 그리고 drag가 멈췄을 때 dragSideView 함수에 drag된 x축 data와 drag중이라는 정보를 함수에 대입한다.
class ContentViewController: UIViewController {
....
override func viewDidLoad() {
....
}
func setUpMainView() {
....
}
func openOrCloseSideView() {
....
}
// (3)
func dragSideView(xDragAmount: CGFloat, isEnded: Bool) {
if !isSideViewOn {
// (5)
if sideView == nil {
sideView = storyboard?.instantiateViewController(withIdentifier: "sideView") as? SideTableViewController
self.addChildViewController(sideView!)
self.view.addSubview((sideView?.view)!)
sideView?.didMove(toParentViewController: self)
self.view.bringSubview(toFront: (self.naviView?.view)!)
sideView?.delegate = mainView
}
self.naviView?.view.frame = CGRect(x: xDragAmount, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: xDragAmount - sideViewWidth, y: 0, width: sideViewWidth, height: self.view.frame.height)
// (6)
if isEnded {
if xDragAmount > 50 {
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}) { (result) in
self.isSideViewOn = true
}
}else {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: -sideViewWidth, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
self.sideView?.view.removeFromSuperview()
self.sideView = nil
}
}
}else {
//(7)
self.naviView?.view.frame = CGRect(x: sideViewWidth + xDragAmount, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: xDragAmount, y: 0, width: sideViewWidth, height: self.view.frame.height)
if isEnded {
if xDragAmount < -50 {
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}) { (result) in
self.sideView?.view.removeFromSuperview()
self.sideView = nil
self.isSideViewOn = false
}
}else {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}
}
}
}
}
| cs |
(5) (4)에서 받은 정보를 바탕으로 mainView와 sideView의 위치를 제어하는 곳이다.
sideView가 off일 때는 mainView의 x point 위치가 0에서 시작할 것이므로 xDragAmount가 x 좌표에 들어간다.
(6) 만약 drag가 끝났다면 drag된 양이 적정 이상이라면 자동으로 sideView를 on의 위치에 놓는다. 이때 animation 효과를 준다.
(7) 만약 sideView가 on 되어 있는 상태에서 drag 할 경우 mainView의 x 위치는 sideViewWidth + xDragAmount 로 표현이 되어야 한다. 이때도 (6)과 동일하게 닫으려고 하는 양의 적정 수준 이상이 되면 자동으로 닫히게 하였다.
사실 openOrCloseSideView() methode와 dragSideView() methode에 중복된 사항이 있어 간소화 해야 겠지만 여기선 이렇게 까지만 정리하자.
아래는 전체 code
sideView가 off일 때는 mainView의 x point 위치가 0에서 시작할 것이므로 xDragAmount가 x 좌표에 들어간다.
(6) 만약 drag가 끝났다면 drag된 양이 적정 이상이라면 자동으로 sideView를 on의 위치에 놓는다. 이때 animation 효과를 준다.
(7) 만약 sideView가 on 되어 있는 상태에서 drag 할 경우 mainView의 x 위치는 sideViewWidth + xDragAmount 로 표현이 되어야 한다. 이때도 (6)과 동일하게 닫으려고 하는 양의 적정 수준 이상이 되면 자동으로 닫히게 하였다.
사실 openOrCloseSideView() methode와 dragSideView() methode에 중복된 사항이 있어 간소화 해야 겠지만 여기선 이렇게 까지만 정리하자.
아래는 전체 code
class ContentViewController: UIViewController {
var naviView: UINavigationController?
var sideView: SideTableViewController?
var mainView: MainViewController?
var sideViewWidth: CGFloat {
return self.view.frame.width * 2 / 3
}
var isSideViewOn: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
setUpMainView()
}
func setUpMainView() {
naviView = storyboard?.instantiateViewController(withIdentifier: "mainView") as? UINavigationController
self.addChildViewController(naviView!) // 자식view로 navigationController를 등록함.
self.view.addSubview((naviView?.view)!) // navigationController view를 화면에 표시함.
naviView?.didMove(toParentViewController: self) // navigationController에게 ContentViewController가 상위ViewController라고 등록함.
mainView = naviView?.viewControllers[0] as? MainViewController
mainView?.delegate = self
naviView?.view.layer.shadowOffset = CGSize(width: -2, height: -2)
naviView?.view.layer.shadowColor = UIColor.black.cgColor
naviView?.view.layer.shadowOpacity = 0.8
}
func openOrCloseSideView() {
if sideView == nil {
sideView = storyboard?.instantiateViewController(withIdentifier: "sideView") as? SideTableViewController
self.addChildViewController(sideView!)
self.view.addSubview((sideView?.view)!)
sideView?.didMove(toParentViewController: self)
self.view.bringSubview(toFront: (self.naviView?.view)!)
sideView?.delegate = mainView
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}) { (result) in
self.isSideViewOn = true
}
}else {
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}) { (result) in
self.sideView?.view.removeFromSuperview()
self.sideView = nil
// (2)
self.isSideViewOn = false
}
}
}
func dragSideView(xDragAmount: CGFloat, isEnded: Bool) {
if !isSideViewOn {
if sideView == nil {
sideView = storyboard?.instantiateViewController(withIdentifier: "sideView") as? SideTableViewController
self.addChildViewController(sideView!)
self.view.addSubview((sideView?.view)!)
sideView?.didMove(toParentViewController: self)
self.view.bringSubview(toFront: (self.naviView?.view)!)
sideView?.delegate = mainView
}
self.naviView?.view.frame = CGRect(x: xDragAmount, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: xDragAmount - sideViewWidth, y: 0, width: sideViewWidth, height: self.view.frame.height)
if isEnded {
if xDragAmount > 50 {
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}) { (result) in
self.isSideViewOn = true
}
}else {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: -sideViewWidth, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
self.sideView?.view.removeFromSuperview()
self.sideView = nil
}
}
}else {
self.naviView?.view.frame = CGRect(x: sideViewWidth + xDragAmount, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: xDragAmount, y: 0, width: sideViewWidth, height: self.view.frame.height)
if isEnded {
if xDragAmount < -50 {
UIView.animate(withDuration: 0.3, animations: {
self.naviView?.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}) { (result) in
self.sideView?.view.removeFromSuperview()
self.sideView = nil
self.isSideViewOn = false
}
}else {
self.naviView?.view.frame = CGRect(x: self.sideViewWidth, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.sideView?.view.frame = CGRect(x: 0, y: 0, width: self.sideViewWidth, height: self.view.frame.height)
}
}
}
}
}
| cs |
class MainViewController: UIViewController {
var delegate: ContentViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func toggleSideView(_ sender: UIBarButtonItem) {
delegate?.openOrCloseSideView()
}
func changeBackGroundColor(color: UIColor) {
self.view.backgroundColor = color
}
@IBAction func dragGesture(_ sender: UIPanGestureRecognizer) {
if sender.state == .began || sender.state == .changed {
delegate?.dragSideView(xDragAmount: sender.translation(in: self.view).x, isEnded: false)
}else if sender.state == .ended {
delegate?.dragSideView(xDragAmount: sender.translation(in: self.view).x, isEnded: true)
}
}
}
| cs |
class SideTableViewController: UITableViewController {
var delegate: MainViewController?
var colorOfMainView:[(String,UIColor)] = [("Red",UIColor.red), ("Blue",UIColor.blue), ("White",UIColor.white), ("Cyan",UIColor.cyan), ("Green",UIColor.green)]
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return colorOfMainView.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = colorOfMainView[indexPath.row].0
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.changeBackGroundColor(color: colorOfMainView[indexPath.row].1)
}
}
| cs |
댓글
댓글 쓰기