Contents
Chào bạn đến với bài viết thuộc seri Lập trình iOS cho mọi người. Bài viết này sẽ nói về Navigation Controller và cách điều hướng các màn hình trong ứng dụng iOS.
Để vào bài thì bạn cần xem lại các chủ đề sau:
Kiến thức sẽ móc nối nhiều phần trước kia lại với nhau. Còn nếu bạn là fan cứng của Fx Studio và đã theo dõi hết các bài viết trước thì chúng ta …
Bắt đầu thôi!
Chuẩn bị
- MacOS 10.14.4
- Xcode 11.0
- Swift 5.1
1. UINavigationController
Đặc trưng của các ứng dụng trên PC thì chúng hầu hết có 1 window và tất cả view hiển thị đều ở đó. Nhưng đối với mobile nói chung thì giới hạn về kích thước màn hình vẫn là điều lớn nhất. Nên giao diện phải được chia ra thành nhiều màn hình. Chúng sẽ được bố trí ở nhiều View Controller khác nhau. Vấn đề đặt ra là
Làm sao để di chuyển giữa các màn hình với nhau và luồng dữ liệu & sự kiện sẽ như thế nào?
Bài này sẽ chỉ giải quyết một phần của vấn đề trên vì việc di chuyển giữa các màn hình khác nhau thì phức tạp hơn nhiều. Nó còn được gọi là điều hướng ứng dụng. Bạn phải nắm rõ cấu trúc các màn hình trong ứng dụng của bạn thì mới điều khiển được chúng nó.
Quay vào trọng tâm của bài viết là Navigation Controller. Vậy nó là gì?
UINavigationController hay Navigation Controller là một container quản lý các View Controller con và điều hướng chúng. Trong đó, mỗi lần chỉ hiển thị được một View Controller con mà nó quản lý.
Ví dụ đơn giản về Navigation Controller
Navigation Controller giống như một ngăn xếp. View Controller được bỏ vào sau sẽ được hiển thị. Khi lấy ra một View Controller từ ngăn xếp thì View Controller được thêm vào trước đó sẽ được hiển thị. Tới khi nào tới View Controller đầu tiên thì không thể lấy ra được nữa.
Navigation được sử dụng vào việc điều hướng đơn giản khi muốn di chuyển qua các màn hình và quay lại. Các màn hình thường liên quan với nhau.
Vì UINavigationController cũng là con cháu của UIViewController. Nên đối tượng thể hiện của nó, có thể xét ở root
của Window để điều hướng toàn bộ giao diện ứng dụng theo Navigation.
2. Cấu trúc
Cấu trúc của UINavigationController
Về mặt cấu trúc của Navigation Controller thì chúng ta có như sau:
viewControllers
là một stack (array UIViewController) chứa các View Controller.navigationBar
hiển thị ở trên màn hình. Chứa thông tin của View Controller và các buttonstoolbar
là phần hiển thị ở dưới màn hình. Chứa các items phục vụ các chứng năng khác nhau
Giải thích chút
Navigation Bar mặc định được hiển thị và được quản lý bởi Navigation Controller của chính nó. Navigation Controller cập nhật giao diện của navigation bar bằng cách sử dụng nội dung được cung cấp bởi thuộc tính viewControllers quy định stack của navigation.
- View controllers:
- Là stack của các viewControllers, là một mảng các view controllers.
- View controller đầu tiên trong mảng là root view controller.
- View controller cuối cùng trong mảng là view controller đang được hiển thị.
- Sử dụng back button trên navigation bar để remove view controller trên cùng
- Navigation bar:
- Chia làm 3 phần: left item, middle item, right item
- Left:
- backBarButtonItem
- leftBarButtonItem
- leftBarButtonItems
- Middle:
- title
- titleView
- Right:
- rightBarButtonItem
- rightBarButtonItems
- Navigation controller content view
- Navigation Controller là một container, nó gắn nội dung của những view controller khác vào trong nó và quản lý thông qua thuộc tính
view
. - Khi xây dựng giao diện điều hướng, mỗi một view controller được push vào phải luôn có một đối tượng UINavigationItem.
- Navigation item có nhiệm vụ thể hiện những thông tin của view controller chứa nó, bao gồm những button cũng như view được hiển thị trên navigation bar.
- Để thay đổi nội dung của navigation bar, cần config các thuộc tính con của thuộc tính navigationItems của view controller nằm trong stack.
- Để ẩn/hiện navigation bar, sử dụng thuộc tính
isNavigationBarHidden
hoặcsetNavigationBarHidden(_:animated:)
- Navigation Controller là một container, nó gắn nội dung của những view controller khác vào trong nó và quản lý thông qua thuộc tính
3. Điều hướng
Chúng ta sẽ dùng iOS Project không sử dụng StoryBoard để thực hiện demo cho bài này.
3.1. Khởi tạo
Tạo 1 View Controller, đặt tên là FirstViewController
import UIKit class FirstViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() title = "First VC" } }
Chú ý:
title
khi xét giá trị cho nó thì cũng chính là title của NavigationItem (middle)
Mở file SceneDelegate.swift
tiền hành edit đoạn code sau:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } let window = UIWindow(windowScene: windowScene) let vc = FirstViewController() let navi = UINavigationController(rootViewController: vc) window.rootViewController = navi self.window = window window.makeKeyAndVisible() }
Việc tạo 1 đối tượng UINavigationController thì cần có 1 rootViewController. Đó chính là đối tượng vc
khởi tạo từ class FirstViewController
. Quá đơn giản, EZ
3.2. Push
Để đưa một màn hình khác vào thì sử dụng hàm push
của Navigation Controller. Chúng ta tiếp tục với file FirstViewController.swift
- Thêm 1 UIButton & 1 IBAction cho nó
@IBAction func push(_ sender: Any) { let vc = SecondViewController() self.navigationController?.pushViewController(vc, animated: true) }
Tại mỗi UIViewController thì có biến navigationController
. Biến này sẽ trỏ tới đối tượng navigationController
được tạo ra và gán cho root
của Window.
Có thêm tham số animated
để cho có hiệu ứng khi đưa 1 View Controller khác vào.
Chú ý: đối tượng View Controller trước đó vẫn còn tồn tại. Nó chỉ bị View Controller (push vào) đè lên mà thôi. 2 function
viewWillDisappear
&viewDidDisappear
sẽ được gọi.
Xem full code cho FirstViewController
import UIKit class FirstViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() title = "First VC" } override func viewWillDisappear(_ animated: Bool) { print("view Will Disappear") } override func viewDidDisappear(_ animated: Bool) { print("view Did Disappear") } @IBAction func push(_ sender: Any) { let vc = SecondViewController() self.navigationController?.pushViewController(vc, animated: true) } }
Kết quả sau khi nhấn button.
3.3. Pop
Để lấy 1 View Controller ra khỏi Navigation Controller thì sử dụng hàm pop
. Mở file SecondViewController
và tiến hành code.
- Tạo 1 UIButton và 1 IBAction cho nó
@IBAction func pop(_ sender: Any) { self.navigationController?.popViewController(animated: true) }
Rất là đơn giản:
animated
để cho có hiệu ứng khi lấy ra hay không
Chú ý: khi thực hiện lệnh này thì View Controller được
push
vào sau cùng sẽ được lấy ra đầu tiên. Đối tượng View Controller đó sẽ bị giải phỏng. Nên vấn đề đảm bảo việc truyền dữ liệu sẽ rất quan trọng.
3.4. Pop to View Controller
Khi quá nhiều View Controller được push
vào Navigation Controller và muốn pop
ra một lúc nhiều màn hình thì chúng ta sử dụng hàm popToViewController(:)
Mở file ThirdViewController
- Thêm 1 UIButton và 1 IBAction
@IBAction func popController(_ sender: Any) { let vc = (self.navigationController?.viewControllers[1])! self.navigationController?.popToViewController(vc, animated: true) }
Để pop
tới đối tượng View Controller thì cần phải xác định chính xác nó đang ở đâu trong stack hay navigationController?.viewControllers
. Khi lấy được nó, thì nó sẽ là đối số của hàm.
Lưu ý:
- Tránh việc muốn về SecondViewController mà
new
một đối tượng đó ra và truyền vào hàm. Kết quả là crash chương trình - Vì đối tượng cần pop ra thì phải đang tồn tại trong stack của Navigation Controller
Chú ý: khi
pop
tới đối tượng View Controller nào, thì đối tượng đó và các đối tượng sau nó (đượcpush
vào sau nó) sẽ được giải phóng hết. Các đối tượng View Controller trước đó sẽ vẫn còn tồn tại.
3.5. Pop to root
Khi bạn quá mệt mỏi với việc pop
từng View Controller hay nhiều View Controller. Và đôi lúc chúng ta cũng không xác định là có bao nhiêu đối tượng View Controller để pop
mà muốn về View Controller đầu tiên thì sử dụng hàm popToRootViewController
.
Tham khảo code sau:
@IBAction func popRoot(_ sender: Any) { self.navigationController?.popToRootViewController(animated: true) }
Với lệnh này, thì toàn bộ các View Controller được push
vào Navigation Controller sẽ được lấy ra hết. Chỉ riêng rootViewController
lúc khởi tạo Navigation Controller sẽ được giữ lại.
Chú ý: tất cả các đối tượng View Controller sẽ bị giải phóng, trừ
rootViewController
của Navigation Controller.
4. Custom Navigation Bar
Chúng ta sẽ làm một số custom đơn giản đối với Navigation Bar. Đầu tiên xem qua cấu trúc của Navigation Bar như thế nào?
4.1. Bar Item
Back Button
Đôi khi bạn khó chịu khi title của View Controller trước đó cứ hiện ở backBarButtonItem
thì muốn custom nó cũng đơn giản thôi. Tham khảo code sau
let backButton = UIBarButtonItem(title: "Back", style: .plain, target: self, action: nil) navigationItem.backBarButtonItem = backButton
Kết quả
Chú ý: khi bạn thêm
back button
ở đối tượng View Controller nào thì nó sẽ ảnh hưởng ở các màn hình sau. Chứ nó không ảnh hưởng tới màn hình đang hiển thị là chinh View Controller đó.
Left Items & Left Items
Thêm 1 button vào phía trái của Navigation Bar Item
let leftButton = UIBarButtonItem(title: "Left", style: .plain, target: self, action: #selector(leftAction)) navigationItem.leftBarButtonItem = leftButton
Chú ý về function của tham số action
thì cần phải có từ khoá @objc
@objc func leftAction() { print("taped") }
Thêm nhiều button vào phía trái
let leftButton1 = UIBarButtonItem(title: "Left 1", style: .plain, target: self, action: #selector(leftAction)) let leftButton2 = UIBarButtonItem(title: "Left 2", style: .plain, target: self, action: #selector(leftAction)) navigationItem.leftBarButtonItems = [leftButton1, leftButton2]
Chú ý leftBarButtonItems
có thêm 1 chữ s
và nó được gán bằng 1 array.
Right Item & Right Items
Tương tự như bên trái, chúng ta cũng tạo ra các Bar Button Item và thêm chúng vào.
-
rightBarButtonItem
thêm 1 item -
rightBarButtonItems
thêm nhiều item
Kết quả
Item with icon & image
Thêm phần thú vị cho cuộc sống, thì chúng ta có thể các icon của hệ thống hay các ảnh cho các đối tượng Bar Button Item. Tham khảo đoạn code sau:
let searchItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(tap)) let bookMarkItem = UIBarButtonItem(barButtonSystemItem: .bookmarks, target: self, action: #selector(tap)) let settingItem = UIBarButtonItem(image: UIImage(named: "setting-icon"), style: .plain, target: self, action: #selector(tap)) navigationItem.rightBarButtonItems = [searchItem, bookMarkItem, settingItem]
Kết quả:
4.2. Color
Chúng ta tham khảo các cách thay đổi màu sắc trên Navigation Controller với UINavigationBar của nó.
- bar background
navi.navigationBar.backgroundColor = .cyan
- tintColor
navi.navigationBar.tintColor = .systemPink
- barTintColor
navi.navigationBar.barTintColor = .systemPink
- title color
navi.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red]
4.3. Image
Thay đổi ảnh cho background thông qua function setBackgroundImage
self.navigationController?.navigationBar .setBackgroundImage(UIImage(named: "cricket"), for: .default)
4.4. appearance()
Có một cách khác để bạn có thể custom Navigation Bar một lần cho toàn bộ app, cho toàn bộ UINavigationController. Đó là sử dụng appearance()
. Cách sử dụng như sau:
let navigationBarAppearance = UINavigationBar.appearance() navigationBarAppearance.barTintColor = .someUIColor navigationBarAppearance.titleTextAttributes = myTextAttributes navigationBarAppearance.largeTitleTextAttributes = myTextAttributes
Tới đây cũng khá nhiều rồi, tạm thời thì bạn đã đầy đủ vũ khí để điều hướng các màn hình trong ứng dụng của bạn với Navigation Controller. Chúc bạn thành công!
Tạm kết
- Tìm hiểu về UINavigationController
- Cấu trúc của Navigation Controller
- Điều hướng trong ứng dụng iOS
- Custom Navigation Bar
Related Posts:
Written by chuotfx
Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!
Leave a Reply Cancel reply
Fan page
Tags
Recent Posts
- SMART – Hướng dẫn dành tạo Prompt cho người mới bắt đầu
- Nhìn lại năm 2024
- CO-STAR – Công thức vàng để viết Prompt hiệu quả cho LLM
- Prompt Engineering trong 10 phút
- Một số ví dụ sử dụng Prompt cơ bản khi làm việc với AI
- Prompt trong 10 phút
- Charles Proxy – Phần 1 : Giới thiệu, cài đặt và cấu hình
- Complete Concurrency với Swift 6
- 300 Bài code thiếu nhi bằng Python – Ebook
- Builder Pattern trong 10 phút
You may also like:
Archives
- January 2025 (2)
- December 2024 (4)
- September 2024 (1)
- July 2024 (1)
- June 2024 (1)
- May 2024 (4)
- April 2024 (2)
- March 2024 (5)
- January 2024 (4)
- February 2023 (1)
- January 2023 (2)
- November 2022 (2)
- October 2022 (1)
- September 2022 (5)
- August 2022 (6)
- July 2022 (7)
- June 2022 (8)
- May 2022 (5)
- April 2022 (1)
- March 2022 (3)
- February 2022 (5)
- January 2022 (4)
- December 2021 (6)
- November 2021 (8)
- October 2021 (8)
- September 2021 (8)
- August 2021 (8)
- July 2021 (9)
- June 2021 (8)
- May 2021 (7)
- April 2021 (11)
- March 2021 (12)
- February 2021 (3)
- January 2021 (3)
- December 2020 (3)
- November 2020 (9)
- October 2020 (7)
- September 2020 (17)
- August 2020 (1)
- July 2020 (3)
- June 2020 (1)
- May 2020 (2)
- April 2020 (3)
- March 2020 (20)
- February 2020 (5)
- January 2020 (2)
- December 2019 (12)
- November 2019 (12)
- October 2019 (19)
- September 2019 (17)
- August 2019 (10)