본문 바로가기
ios 뽀개기/실전

탭바 커스텀하기

by 인생여희 2018. 1. 2.
반응형

탭바 커스텀하기


//

//  ViewController.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

//  Copyright © 2018년 MacBookPro. All rights reserved.

//


import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        let title = UILabel(frame: CGRect(x:0, y:100, width: 100, height: 30))

        

        title.text = "첫번째"

        title.textColor = UIColor.red

        title.textAlignment = .center

        title.font = UIFont.boldSystemFont(ofSize: 14)

        

        title.sizeToFit() //콘텐츠의 내용에 맞게 레이블 크기 변경, center 속성 전에 사용하기

        title.center.x = self.view.frame.width / 2 //x축의 중앙에 오도록

        //값을 입력할때는 self.view.frame.size.width

        //값을 가져올때 self.view.frame.width

        

        self.view.addSubview(title)

        

        

        // 탭바 컨트롤러 -> 탭바를 통해 접근

        // 모든 탭바 아이템을 참조할 수 있다.

        //self.tabBarController?.tabBar.items?[0]

        //탭바를 참조하기 위해서 반드시 tabBarController를 거쳐야 한다.

        //탭바 관련 객체 중에서 뷰 컨트롤러에서 직접 참조할 수 있는 것은 탭바 컨트롤러와 탭 바 아이템 뿐이다.

        //탭바 아이템은 뷰 컨트롤러에서 self.tabBarItem 속성을 이용해서 직접 참조 할 수 있다.

        //self.tabBarItem.image = UIImage(named:"calendar.png")

        //self.tabBarItem.title = "캘린더"

        

        //탭 바 컨트롤러는 연결된 모든 뷰 컨트롤러의 화면을 처음부터 생성하는건 아니다.

        //각 탭이 처음 활성화 되는 순간에, 사용자가 탭을 누르는 순간에 비로소 그 탭에 연결된 뷰 컨트롤러의 화면을 읽어 들인다.

        //이는 viewDidLoad 메소드가 두번째 세번째 뷰 컨트롤러에서 아직 호출 되지 않았다는 뜻

        //해결: appDelegate클래스의 application(:didFinishLaunchingWithOptions:) 메소드로 옮기기

    }


    

    

    // UIViewController의 상위 클래스인 UIResponder에는 화면 터치 관련 메소드들이 정의 되어 있다.

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

        let tabBar = self.tabBarController?.tabBar

       // tabBar?.isHidden = (tabBar?.isHidden == true) ? false : true

        

        //애니메이션 적용해주기

        UIView.animate(withDuration:  TimeInterval(0.1)){

            tabBar?.alpha = (tabBar?.alpha == 0 ? 1 : 0)

            

        }

    }



}



//

//  SecondViewController.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

//  Copyright © 2018년 MacBookPro. All rights reserved.

//


import UIKit


class SecondViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()


        let title = UILabel(frame: CGRect(x:0, y:100, width: 100, height: 30))

        

        title.text = "두 번째 탭"

        title.textColor = UIColor.red

        title.textAlignment = .center

        title.font = UIFont.boldSystemFont(ofSize: 14)

        

        title.sizeToFit() //콘텐츠의 내용에 맞게 레이블 크기 변경, center 속성 전에 사용하기

        title.center.x = self.view.frame.width / 2 //x축의 중앙에 오도록

        //값을 입력할때는 self.view.frame.size.width

        //값을 가져올때 self.view.frame.width

        

        self.view.addSubview(title)

        

        // 탭바 컨트롤러 -> 탭바를 통해 접근

        // 모든 탭바 아이템을 참조할 수 있다.

        //self.tabBarController?.tabBar.items?[0]

        //탭바를 참조하기 위해서 반드시 tabBarController를 거쳐야 한다.

        //탭바 관련 객체 중에서 뷰 컨트롤러에서 직접 참조할 수 있는 것은 탭바 컨트롤러와 탭 바 아이템 뿐이다.

        //탭바 아이템은 뷰 컨트롤러에서 self.tabBarItem 속성을 이용해서 직접 참조 할 수 있다.

        //self.tabBarItem.image = UIImage(named:"file-tree.png")

        //self.tabBarItem.title = "파일"

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}


//

//  ThirdViewController.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

//  Copyright © 2018년 MacBookPro. All rights reserved.

//


import UIKit


class ThirdViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()


        let title = UILabel(frame: CGRect(x:0, y:100, width: 100, height: 30))

        

        title.text = "세 번째 탭"

        title.textColor = UIColor.red

        title.textAlignment = .center

        title.font = UIFont.boldSystemFont(ofSize: 14)

        

        title.sizeToFit() //콘텐츠의 내용에 맞게 레이블 크기 변경, center 속성 전에 사용하기

        title.center.x = self.view.frame.width / 2 //x축의 중앙에 오도록

        //값을 입력할때는 self.view.frame.size.width

        //값을 가져올때 self.view.frame.width

        

        self.view.addSubview(title)

        // 탭바 컨트롤러 -> 탭바를 통해 접근

        // 모든 탭바 아이템을 참조할 수 있다.

        //self.tabBarController?.tabBar.items?[0]

        //탭바를 참조하기 위해서 반드시 tabBarController를 거쳐야 한다.

        //탭바 관련 객체 중에서 뷰 컨트롤러에서 직접 참조할 수 있는 것은 탭바 컨트롤러와 탭 바 아이템 뿐이다.

        //탭바 아이템은 뷰 컨트롤러에서 self.tabBarItem 속성을 이용해서 직접 참조 할 수 있다.

        //self.tabBarItem.image = UIImage(named:"photo.png")

        //self.tabBarItem.title = "사진"

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

    


    /*

    // MARK: - Navigation


    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destinationViewController.

        // Pass the selected object to the new view controller.

    }

    */


}



//

//  AppDelegate.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

//  Copyright © 2018년 MacBookPro. All rights reserved.

//


import UIKit

import CoreData


//@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        

        //1.윈도우 객체에 연결된 루트 뷰 컨트롤러를 읽어와 uitabbarcontroller 타입 캐스팅 한다.

        //루트 뷰 컨트롤러를 uitabbarcontroller로 캐스팅 한다.

        if let tbC = self.window?.rootViewController as? UITabBarController{

            

            //2.탭바로 부터 탭 바 아이템 배열을 가져 온다.

           if let tbItems =  tbC.tabBar.items{

            //tbItems[0].image = UIImage(named:"calendar")

            //tbItems[1].image = UIImage(named:"file-tree")

            //tbItems[2].image = UIImage(named:"photo")

            

            //커스텀 탭바 아이템으로 변경시키기 - 랜더링 메소드 이용!

            tbItems[0].image = UIImage(named:"designbump")?.withRenderingMode(.alwaysOriginal)

            tbItems[1].image = UIImage(named:"rss")?.withRenderingMode(.alwaysOriginal)

            tbItems[2].image = UIImage(named:"facebook")?.withRenderingMode(.alwaysOriginal)

            

            

            //탭바 아이템 전체를 순회하면서 selectedImage 속성에 이미지를 설정한다. -- 랜더링 메소드 이용!

            for tbItem in tbItems{

                let image = UIImage(named: "checkmark")?.withRenderingMode(.alwaysOriginal)

                tbItem.selectedImage = image

                

                //탭바 아이템 타이틀 색깔 속성값 변경하기. - 선택 안되었을때

                tbItem.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.gray], for: .disabled)

                //선택 되었을 때

                tbItem.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.red], for: .selected)

           

                //탭바 아이템의 폰트 값 설정

                tbItem.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 15)], for: .normal)

            }

            

            //외형 프록시 객체를 이용하여 아이템의 타이틀 색상과 폰트 크기를 설정한다.

            //외형 프록시 객체는 화면 요소별 속성을 공통으로 적용할 수 있는 객체다.

            //외형 프록시 객체에 속성을 설정해두면 해 당 타입으로 생성된 모든 객체에 해당 속성이 적용된다.

            

            //let tbItemProxy = UITabBarItem.appearance()

            //tbItemProxy.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.red], for: .selected)

            //tbItemProxy.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.red], for: .disabled)

            //tbItemProxy.setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 15)], for: .normal)

            

            //3. 탭 바 아이템에 타이틀을 설정한다.

            tbItems[0].title = "달력"

            tbItems[1].title = "파일"

            tbItems[2].title = "사진"

            }

            

            //4.활성화된 탭 바 아이템의 이미지 색상을 변경한다.

            //tbC.tabBar.tintColor = UIColor.white

            //tbC.tabBar.backgroundImage = UIImage(named:"menubar-bg-mini")

            

            //let image = UIImage(named: "menubar-bg-mini")!

            //tbC.tabBar.barTintColor = UIColor(patternImage: image)

            

            //인자값으로 입력된 x좌표의 이미지만 늘어나고, x좌표를 기준으로 분할된 좌우측의 이미지는 나뉘어 양쪽 끝에 밀착하게 된다.

            //let bg = UIImage(named: "connectivity-bar")?.stretchableImage(withLeftCapWidth: 5, topCapHeight: 16)

            //tbC.tabBar.backgroundImage = bg

            

            //참고 tbC.tabBar.clipsToBounds = true // 탭바에서 넘쳐나는 이미지 잘라내기

        }

        

        return true

    }


    func applicationWillResignActive(_ application: UIApplication) {

        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.

        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.

    }


    func applicationDidEnterBackground(_ application: UIApplication) {

        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.

        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    }


    func applicationWillEnterForeground(_ application: UIApplication) {

        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.

    }


    func applicationDidBecomeActive(_ application: UIApplication) {

        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    }


    func applicationWillTerminate(_ application: UIApplication) {

        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

        // Saves changes in the application's managed object context before the application terminates.

        self.saveContext()

    }


    // MARK: - Core Data stack


    lazy var persistentContainer: NSPersistentContainer = {

        /*

         The persistent container for the application. This implementation

         creates and returns a container, having loaded the store for the

         application to it. This property is optional since there are legitimate

         error conditions that could cause the creation of the store to fail.

        */

        let container = NSPersistentContainer(name: "TabTab")

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in

            if let error = error as NSError? {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                 

                /*

                 Typical reasons for an error here include:

                 * The parent directory does not exist, cannot be created, or disallows writing.

                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.

                 * The device is out of space.

                 * The store could not be migrated to the current model version.

                 Check the error message to determine what the actual problem was.

                 */

                fatalError("Unresolved error \(error), \(error.userInfo)")

            }

        })

        return container

    }()


    // MARK: - Core Data Saving support


    func saveContext () {

        let context = persistentContainer.viewContext

        if context.hasChanges {

            do {

                try context.save()

            } catch {

                // Replace this implementation with code to handle the error appropriately.

                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                let nserror = error as NSError

                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")

            }

        }

    }


}


앱 델리게이트 새로 만들어서 스토리보드 없이 하기 ~~~~~


//

//  NewDelegate.swift

//  TabTab

//

//  Created by MacBookPro on 2018. 1. 2..

//  Copyright © 2018년 MacBookPro. All rights reserved.

//


import UIKit

import CoreData


@UIApplicationMain //전체를 통해 하나면 구현할 수 있다.

class NewDelegate: UIResponder, UIApplicationDelegate{

    //앱이 실행 될 때 앱 델리게이트 클래스는 스토리 보드 파일을 읽어와 윈도우 객체를 생성하는데, 이 객체를 앱 델리게이트 내의 변수 window에 저장하도록 프로그래밍 되어 있다.

    var window: UIWindow?

    

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

        

        //1. 탭바 컨트롤러를 생성하고 , 배경을 흰색으로 한다.

        let tbC = UITabBarController()

        tbC.view.backgroundColor = .white

        

        //2.생성된 tbC를 루트뷰 컨트롤러로 등록한다. : 윈도우 객체가 참조하는 뷰컨트롤러가 곧 루트 뷰 컨트롤러다.

        self.window?.rootViewController = tbC

        

        //3.각 탭바 아이템에 연결될 뷰 컨트롤러 객체를 생성한다.

        let view01 = ViewController()

        let view02 = SecondViewController()

        let view03 = ThirdViewController()

        

        //4.생성된 뷰 컨트롤러 객체들을 탭 바 컨트롤러에 등록한다.

        tbC.setViewControllers([view01,view02,view03], animated: false)

        

        //5 개별 탭바 아이템 속성을 설정한다.

        view01.tabBarItem = UITabBarItem(title:"달력",image:UIImage(named:"calendar"), selectedImage: nil)

        view02.tabBarItem = UITabBarItem(title:"파일",image:UIImage(named:"file-tree"), selectedImage: nil)

        view03.tabBarItem = UITabBarItem(title:"사진",image:UIImage(named:"photo"), selectedImage: nil)

        

        

        //주의: 탭 바 아이템을 참조할 때 탭바 컨트롤러 -> 탭바 -> 탭바 아이템 순으로 참조(x)

        //뷰 컨트롤러에서 직접 탭바를 참조해야 한다.

        //이유: 탭바 아이템은 각각의 뷰 컨트롤러에 연결되어 있는 속성이다. 탭바 컨트롤러 하위에 뷰컨트롤러가 연결되면 탭바 컨트롤러는 각각의 뷰컨트롤러에게 탭바 아이템을 제공한다.

        //이같은 매커니즘으로 인해 탭 바 아이템의 소유권은 탭바가 아닌 뷰 컨트롤러가 된다.

        // 뷰 컨트롤러 -> 탭바 아이템 형식으로 참조한다.

        return true

    }

    

}



반응형

'ios 뽀개기 > 실전' 카테고리의 다른 글

메모장 - 커스텀(x)  (0) 2018.01.03
커스텀 내비게이션 바  (0) 2018.01.03
커스텀 버튼 및 데이터 전달하기  (0) 2018.01.02
커스터마이징 버튼  (0) 2017.12.27
버튼 커스터마이징  (0) 2017.12.27

댓글